1 /* 2 * Copyright (C) 2006 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.app.AppOpsManager; 20 import android.app.BroadcastOptions; 21 import android.content.IIntentReceiver; 22 import android.content.ComponentName; 23 import android.content.Intent; 24 import android.content.pm.ActivityInfo; 25 import android.content.pm.ResolveInfo; 26 import android.os.Binder; 27 import android.os.Bundle; 28 import android.os.IBinder; 29 import android.os.SystemClock; 30 import android.os.UserHandle; 31 import android.util.PrintWriterPrinter; 32 import android.util.TimeUtils; 33 import android.util.proto.ProtoOutputStream; 34 35 import java.io.PrintWriter; 36 import java.text.SimpleDateFormat; 37 import java.util.Arrays; 38 import java.util.Date; 39 import java.util.List; 40 import java.util.Set; 41 42 /** 43 * An active intent broadcast. 44 */ 45 final class BroadcastRecord extends Binder { 46 final Intent intent; // the original intent that generated us 47 final ComponentName targetComp; // original component name set on the intent 48 final ProcessRecord callerApp; // process that sent this 49 final String callerPackage; // who sent this 50 final int callingPid; // the pid of who sent this 51 final int callingUid; // the uid of who sent this 52 final boolean callerInstantApp; // caller is an Instant App? 53 final boolean ordered; // serialize the send to receivers? 54 final boolean sticky; // originated from existing sticky data? 55 final boolean initialSticky; // initial broadcast from register to sticky? 56 final int userId; // user id this broadcast was for 57 final String resolvedType; // the resolved data type 58 final String[] requiredPermissions; // permissions the caller has required 59 final int appOp; // an app op that is associated with this broadcast 60 final BroadcastOptions options; // BroadcastOptions supplied by caller 61 final List receivers; // contains BroadcastFilter and ResolveInfo 62 final int[] delivery; // delivery state of each receiver 63 IIntentReceiver resultTo; // who receives final result if non-null 64 long enqueueClockTime; // the clock time the broadcast was enqueued 65 long dispatchTime; // when dispatch started on this set of receivers 66 long dispatchClockTime; // the clock time the dispatch started 67 long receiverTime; // when current receiver started for timeouts. 68 long finishTime; // when we finished the broadcast. 69 int resultCode; // current result code value. 70 String resultData; // current result data value. 71 Bundle resultExtras; // current result extra data values. 72 boolean resultAbort; // current result abortBroadcast value. 73 int nextReceiver; // next receiver to be executed. 74 IBinder receiver; // who is currently running, null if none. 75 int state; 76 int anrCount; // has this broadcast record hit any ANRs? 77 int manifestCount; // number of manifest receivers dispatched. 78 int manifestSkipCount; // number of manifest receivers skipped. 79 BroadcastQueue queue; // the outbound queue handling this broadcast 80 81 static final int IDLE = 0; 82 static final int APP_RECEIVE = 1; 83 static final int CALL_IN_RECEIVE = 2; 84 static final int CALL_DONE_RECEIVE = 3; 85 static final int WAITING_SERVICES = 4; 86 87 static final int DELIVERY_PENDING = 0; 88 static final int DELIVERY_DELIVERED = 1; 89 static final int DELIVERY_SKIPPED = 2; 90 static final int DELIVERY_TIMEOUT = 3; 91 92 // The following are set when we are calling a receiver (one that 93 // was found in our list of registered receivers). 94 BroadcastFilter curFilter; 95 96 // The following are set only when we are launching a receiver (one 97 // that was found by querying the package manager). 98 ProcessRecord curApp; // hosting application of current receiver. 99 ComponentName curComponent; // the receiver class that is currently running. 100 ActivityInfo curReceiver; // info about the receiver that is currently running. 101 dump(PrintWriter pw, String prefix, SimpleDateFormat sdf)102 void dump(PrintWriter pw, String prefix, SimpleDateFormat sdf) { 103 final long now = SystemClock.uptimeMillis(); 104 105 pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId); 106 pw.print(prefix); pw.println(intent.toInsecureString()); 107 if (targetComp != null && targetComp != intent.getComponent()) { 108 pw.print(prefix); pw.print(" targetComp: "); pw.println(targetComp.toShortString()); 109 } 110 Bundle bundle = intent.getExtras(); 111 if (bundle != null) { 112 pw.print(prefix); pw.print(" extras: "); pw.println(bundle.toString()); 113 } 114 pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.print(" "); 115 pw.print(callerApp != null ? callerApp.toShortString() : "null"); 116 pw.print(" pid="); pw.print(callingPid); 117 pw.print(" uid="); pw.println(callingUid); 118 if ((requiredPermissions != null && requiredPermissions.length > 0) 119 || appOp != AppOpsManager.OP_NONE) { 120 pw.print(prefix); pw.print("requiredPermissions="); 121 pw.print(Arrays.toString(requiredPermissions)); 122 pw.print(" appOp="); pw.println(appOp); 123 } 124 if (options != null) { 125 pw.print(prefix); pw.print("options="); pw.println(options.toBundle()); 126 } 127 pw.print(prefix); pw.print("enqueueClockTime="); 128 pw.print(sdf.format(new Date(enqueueClockTime))); 129 pw.print(" dispatchClockTime="); 130 pw.println(sdf.format(new Date(dispatchClockTime))); 131 pw.print(prefix); pw.print("dispatchTime="); 132 TimeUtils.formatDuration(dispatchTime, now, pw); 133 pw.print(" ("); 134 TimeUtils.formatDuration(dispatchClockTime-enqueueClockTime, pw); 135 pw.print(" since enq)"); 136 if (finishTime != 0) { 137 pw.print(" finishTime="); TimeUtils.formatDuration(finishTime, now, pw); 138 pw.print(" ("); 139 TimeUtils.formatDuration(finishTime-dispatchTime, pw); 140 pw.print(" since disp)"); 141 } else { 142 pw.print(" receiverTime="); TimeUtils.formatDuration(receiverTime, now, pw); 143 } 144 pw.println(""); 145 if (anrCount != 0) { 146 pw.print(prefix); pw.print("anrCount="); pw.println(anrCount); 147 } 148 if (resultTo != null || resultCode != -1 || resultData != null) { 149 pw.print(prefix); pw.print("resultTo="); pw.print(resultTo); 150 pw.print(" resultCode="); pw.print(resultCode); 151 pw.print(" resultData="); pw.println(resultData); 152 } 153 if (resultExtras != null) { 154 pw.print(prefix); pw.print("resultExtras="); pw.println(resultExtras); 155 } 156 if (resultAbort || ordered || sticky || initialSticky) { 157 pw.print(prefix); pw.print("resultAbort="); pw.print(resultAbort); 158 pw.print(" ordered="); pw.print(ordered); 159 pw.print(" sticky="); pw.print(sticky); 160 pw.print(" initialSticky="); pw.println(initialSticky); 161 } 162 if (nextReceiver != 0 || receiver != null) { 163 pw.print(prefix); pw.print("nextReceiver="); pw.print(nextReceiver); 164 pw.print(" receiver="); pw.println(receiver); 165 } 166 if (curFilter != null) { 167 pw.print(prefix); pw.print("curFilter="); pw.println(curFilter); 168 } 169 if (curReceiver != null) { 170 pw.print(prefix); pw.print("curReceiver="); pw.println(curReceiver); 171 } 172 if (curApp != null) { 173 pw.print(prefix); pw.print("curApp="); pw.println(curApp); 174 pw.print(prefix); pw.print("curComponent="); 175 pw.println((curComponent != null ? curComponent.toShortString() : "--")); 176 if (curReceiver != null && curReceiver.applicationInfo != null) { 177 pw.print(prefix); pw.print("curSourceDir="); 178 pw.println(curReceiver.applicationInfo.sourceDir); 179 } 180 } 181 if (state != IDLE) { 182 String stateStr = " (?)"; 183 switch (state) { 184 case APP_RECEIVE: stateStr=" (APP_RECEIVE)"; break; 185 case CALL_IN_RECEIVE: stateStr=" (CALL_IN_RECEIVE)"; break; 186 case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break; 187 case WAITING_SERVICES: stateStr=" (WAITING_SERVICES)"; break; 188 } 189 pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr); 190 } 191 final int N = receivers != null ? receivers.size() : 0; 192 String p2 = prefix + " "; 193 PrintWriterPrinter printer = new PrintWriterPrinter(pw); 194 for (int i = 0; i < N; i++) { 195 Object o = receivers.get(i); 196 pw.print(prefix); 197 switch (delivery[i]) { 198 case DELIVERY_PENDING: pw.print("Pending"); break; 199 case DELIVERY_DELIVERED: pw.print("Deliver"); break; 200 case DELIVERY_SKIPPED: pw.print("Skipped"); break; 201 case DELIVERY_TIMEOUT: pw.print("Timeout"); break; 202 default: pw.print("???????"); break; 203 } 204 pw.print(" #"); pw.print(i); pw.print(": "); 205 if (o instanceof BroadcastFilter) { 206 pw.println(o); 207 ((BroadcastFilter) o).dumpBrief(pw, p2); 208 } else if (o instanceof ResolveInfo) { 209 pw.println("(manifest)"); 210 ((ResolveInfo) o).dump(printer, p2, 0); 211 } else { 212 pw.println(o); 213 } 214 } 215 } 216 BroadcastRecord(BroadcastQueue _queue, Intent _intent, ProcessRecord _callerApp, String _callerPackage, int _callingPid, int _callingUid, boolean _callerInstantApp, String _resolvedType, String[] _requiredPermissions, int _appOp, BroadcastOptions _options, List _receivers, IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky, boolean _initialSticky, int _userId)217 BroadcastRecord(BroadcastQueue _queue, 218 Intent _intent, ProcessRecord _callerApp, String _callerPackage, 219 int _callingPid, int _callingUid, boolean _callerInstantApp, String _resolvedType, 220 String[] _requiredPermissions, int _appOp, BroadcastOptions _options, List _receivers, 221 IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, 222 boolean _serialized, boolean _sticky, boolean _initialSticky, int _userId) { 223 if (_intent == null) { 224 throw new NullPointerException("Can't construct with a null intent"); 225 } 226 queue = _queue; 227 intent = _intent; 228 targetComp = _intent.getComponent(); 229 callerApp = _callerApp; 230 callerPackage = _callerPackage; 231 callingPid = _callingPid; 232 callingUid = _callingUid; 233 callerInstantApp = _callerInstantApp; 234 resolvedType = _resolvedType; 235 requiredPermissions = _requiredPermissions; 236 appOp = _appOp; 237 options = _options; 238 receivers = _receivers; 239 delivery = new int[_receivers != null ? _receivers.size() : 0]; 240 resultTo = _resultTo; 241 resultCode = _resultCode; 242 resultData = _resultData; 243 resultExtras = _resultExtras; 244 ordered = _serialized; 245 sticky = _sticky; 246 initialSticky = _initialSticky; 247 userId = _userId; 248 nextReceiver = 0; 249 state = IDLE; 250 } 251 252 /** 253 * Copy constructor which takes a different intent. 254 * Only used by {@link #maybeStripForHistory}. 255 */ BroadcastRecord(BroadcastRecord from, Intent newIntent)256 private BroadcastRecord(BroadcastRecord from, Intent newIntent) { 257 intent = newIntent; 258 targetComp = newIntent.getComponent(); 259 260 callerApp = from.callerApp; 261 callerPackage = from.callerPackage; 262 callingPid = from.callingPid; 263 callingUid = from.callingUid; 264 callerInstantApp = from.callerInstantApp; 265 ordered = from.ordered; 266 sticky = from.sticky; 267 initialSticky = from.initialSticky; 268 userId = from.userId; 269 resolvedType = from.resolvedType; 270 requiredPermissions = from.requiredPermissions; 271 appOp = from.appOp; 272 options = from.options; 273 receivers = from.receivers; 274 delivery = from.delivery; 275 resultTo = from.resultTo; 276 enqueueClockTime = from.enqueueClockTime; 277 dispatchTime = from.dispatchTime; 278 dispatchClockTime = from.dispatchClockTime; 279 receiverTime = from.receiverTime; 280 finishTime = from.finishTime; 281 resultCode = from.resultCode; 282 resultData = from.resultData; 283 resultExtras = from.resultExtras; 284 resultAbort = from.resultAbort; 285 nextReceiver = from.nextReceiver; 286 receiver = from.receiver; 287 state = from.state; 288 anrCount = from.anrCount; 289 manifestCount = from.manifestCount; 290 manifestSkipCount = from.manifestSkipCount; 291 queue = from.queue; 292 } 293 maybeStripForHistory()294 public BroadcastRecord maybeStripForHistory() { 295 if (!intent.canStripForHistory()) { 296 return this; 297 } 298 return new BroadcastRecord(this, intent.maybeStripForHistory()); 299 } 300 cleanupDisabledPackageReceiversLocked( String packageName, Set<String> filterByClasses, int userId, boolean doit)301 boolean cleanupDisabledPackageReceiversLocked( 302 String packageName, Set<String> filterByClasses, int userId, boolean doit) { 303 if ((userId != UserHandle.USER_ALL && this.userId != userId) || receivers == null) { 304 return false; 305 } 306 307 boolean didSomething = false; 308 Object o; 309 for (int i = receivers.size() - 1; i >= 0; i--) { 310 o = receivers.get(i); 311 if (!(o instanceof ResolveInfo)) { 312 continue; 313 } 314 ActivityInfo info = ((ResolveInfo)o).activityInfo; 315 316 final boolean sameComponent = packageName == null 317 || (info.applicationInfo.packageName.equals(packageName) 318 && (filterByClasses == null || filterByClasses.contains(info.name))); 319 if (sameComponent) { 320 if (!doit) { 321 return true; 322 } 323 didSomething = true; 324 receivers.remove(i); 325 if (i < nextReceiver) { 326 nextReceiver--; 327 } 328 } 329 } 330 nextReceiver = Math.min(nextReceiver, receivers.size()); 331 332 return didSomething; 333 } 334 335 @Override toString()336 public String toString() { 337 return "BroadcastRecord{" 338 + Integer.toHexString(System.identityHashCode(this)) 339 + " u" + userId + " " + intent.getAction() + "}"; 340 } 341 writeToProto(ProtoOutputStream proto, long fieldId)342 public void writeToProto(ProtoOutputStream proto, long fieldId) { 343 long token = proto.start(fieldId); 344 proto.write(BroadcastRecordProto.USER_ID, userId); 345 proto.write(BroadcastRecordProto.INTENT_ACTION, intent.getAction()); 346 proto.end(token); 347 } 348 } 349