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 static android.app.ActivityManager.START_SUCCESS; 20 21 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_LIGHT; 22 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 23 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 24 25 import android.annotation.Nullable; 26 import android.app.ActivityManager; 27 import android.app.ActivityOptions; 28 import android.app.BroadcastOptions; 29 import android.app.PendingIntent; 30 import android.content.IIntentReceiver; 31 import android.content.IIntentSender; 32 import android.content.Intent; 33 import android.os.Binder; 34 import android.os.Bundle; 35 import android.os.IBinder; 36 import android.os.PowerWhitelistManager; 37 import android.os.PowerWhitelistManager.ReasonCode; 38 import android.os.Process; 39 import android.os.RemoteCallbackList; 40 import android.os.RemoteException; 41 import android.os.TransactionTooLargeException; 42 import android.os.UserHandle; 43 import android.util.ArrayMap; 44 import android.util.ArraySet; 45 import android.util.Slog; 46 import android.util.TimeUtils; 47 48 import com.android.internal.os.IResultReceiver; 49 import com.android.internal.util.function.pooled.PooledLambda; 50 import com.android.server.wm.SafeActivityOptions; 51 52 import java.io.PrintWriter; 53 import java.lang.ref.WeakReference; 54 import java.util.Objects; 55 56 public final class PendingIntentRecord extends IIntentSender.Stub { 57 private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM; 58 59 public static final int FLAG_ACTIVITY_SENDER = 1 << 0; 60 public static final int FLAG_BROADCAST_SENDER = 1 << 1; 61 public static final int FLAG_SERVICE_SENDER = 1 << 2; 62 63 final PendingIntentController controller; 64 final Key key; 65 final int uid; 66 public final WeakReference<PendingIntentRecord> ref; 67 boolean sent = false; 68 boolean canceled = false; 69 /** 70 * Map IBinder to duration specified as Pair<Long, Integer>, Long is allowlist duration in 71 * milliseconds, Integer is allowlist type defined at 72 * {@link android.os.PowerExemptionManager.TempAllowListType} 73 */ 74 private ArrayMap<IBinder, TempAllowListDuration> mAllowlistDuration; 75 private RemoteCallbackList<IResultReceiver> mCancelCallbacks; 76 private ArraySet<IBinder> mAllowBgActivityStartsForActivitySender = new ArraySet<>(); 77 private ArraySet<IBinder> mAllowBgActivityStartsForBroadcastSender = new ArraySet<>(); 78 private ArraySet<IBinder> mAllowBgActivityStartsForServiceSender = new ArraySet<>(); 79 80 String stringName; 81 String lastTagPrefix; 82 String lastTag; 83 84 final static class Key { 85 final int type; 86 final String packageName; 87 final String featureId; 88 final IBinder activity; 89 final String who; 90 final int requestCode; 91 final Intent requestIntent; 92 final String requestResolvedType; 93 final SafeActivityOptions options; 94 Intent[] allIntents; 95 String[] allResolvedTypes; 96 final int flags; 97 final int hashCode; 98 final int userId; 99 100 private static final int ODD_PRIME_NUMBER = 37; 101 Key(int _t, String _p, @Nullable String _featureId, IBinder _a, String _w, int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId)102 Key(int _t, String _p, @Nullable String _featureId, IBinder _a, String _w, 103 int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId) { 104 type = _t; 105 packageName = _p; 106 featureId = _featureId; 107 activity = _a; 108 who = _w; 109 requestCode = _r; 110 requestIntent = _i != null ? _i[_i.length-1] : null; 111 requestResolvedType = _it != null ? _it[_it.length-1] : null; 112 allIntents = _i; 113 allResolvedTypes = _it; 114 flags = _f; 115 options = _o; 116 userId = _userId; 117 118 int hash = 23; 119 hash = (ODD_PRIME_NUMBER*hash) + _f; 120 hash = (ODD_PRIME_NUMBER*hash) + _r; 121 hash = (ODD_PRIME_NUMBER*hash) + _userId; 122 if (_w != null) { 123 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode(); 124 } 125 if (_a != null) { 126 hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode(); 127 } 128 if (requestIntent != null) { 129 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode(); 130 } 131 if (requestResolvedType != null) { 132 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode(); 133 } 134 hash = (ODD_PRIME_NUMBER*hash) + (_p != null ? _p.hashCode() : 0); 135 hash = (ODD_PRIME_NUMBER*hash) + _t; 136 hashCode = hash; 137 //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x" 138 // + Integer.toHexString(hashCode)); 139 } 140 141 @Override equals(Object otherObj)142 public boolean equals(Object otherObj) { 143 if (otherObj == null) { 144 return false; 145 } 146 try { 147 Key other = (Key)otherObj; 148 if (type != other.type) { 149 return false; 150 } 151 if (userId != other.userId){ 152 return false; 153 } 154 if (!Objects.equals(packageName, other.packageName)) { 155 return false; 156 } 157 if (!Objects.equals(featureId, other.featureId)) { 158 return false; 159 } 160 if (activity != other.activity) { 161 return false; 162 } 163 if (!Objects.equals(who, other.who)) { 164 return false; 165 } 166 if (requestCode != other.requestCode) { 167 return false; 168 } 169 if (requestIntent != other.requestIntent) { 170 if (requestIntent != null) { 171 if (!requestIntent.filterEquals(other.requestIntent)) { 172 return false; 173 } 174 } else if (other.requestIntent != null) { 175 return false; 176 } 177 } 178 if (!Objects.equals(requestResolvedType, other.requestResolvedType)) { 179 return false; 180 } 181 if (flags != other.flags) { 182 return false; 183 } 184 return true; 185 } catch (ClassCastException e) { 186 } 187 return false; 188 } 189 hashCode()190 public int hashCode() { 191 return hashCode; 192 } 193 toString()194 public String toString() { 195 return "Key{" + typeName() 196 + " pkg=" + packageName + (featureId != null ? "/" + featureId : "") 197 + " intent=" 198 + (requestIntent != null 199 ? requestIntent.toShortString(false, true, false, false) : "<null>") 200 + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}" 201 + " requestCode=" + requestCode; 202 } 203 typeName()204 String typeName() { 205 switch (type) { 206 case ActivityManager.INTENT_SENDER_ACTIVITY: 207 return "startActivity"; 208 case ActivityManager.INTENT_SENDER_BROADCAST: 209 return "broadcastIntent"; 210 case ActivityManager.INTENT_SENDER_SERVICE: 211 return "startService"; 212 case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE: 213 return "startForegroundService"; 214 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT: 215 return "activityResult"; 216 } 217 return Integer.toString(type); 218 } 219 } 220 221 static final class TempAllowListDuration { 222 long duration; 223 int type; 224 @ReasonCode int reasonCode; 225 @Nullable String reason; 226 TempAllowListDuration(long _duration, int _type, @ReasonCode int _reasonCode, String _reason)227 TempAllowListDuration(long _duration, int _type, @ReasonCode int _reasonCode, 228 String _reason) { 229 duration = _duration; 230 type = _type; 231 reasonCode = _reasonCode; 232 reason = _reason; 233 } 234 } 235 PendingIntentRecord(PendingIntentController _controller, Key _k, int _u)236 PendingIntentRecord(PendingIntentController _controller, Key _k, int _u) { 237 controller = _controller; 238 key = _k; 239 uid = _u; 240 ref = new WeakReference<>(this); 241 } 242 setAllowlistDurationLocked(IBinder allowlistToken, long duration, int type, @ReasonCode int reasonCode, @Nullable String reason)243 void setAllowlistDurationLocked(IBinder allowlistToken, long duration, int type, 244 @ReasonCode int reasonCode, @Nullable String reason) { 245 if (duration > 0) { 246 if (mAllowlistDuration == null) { 247 mAllowlistDuration = new ArrayMap<>(); 248 } 249 mAllowlistDuration.put(allowlistToken, 250 new TempAllowListDuration(duration, type, reasonCode, reason)); 251 } else if (mAllowlistDuration != null) { 252 mAllowlistDuration.remove(allowlistToken); 253 if (mAllowlistDuration.size() <= 0) { 254 mAllowlistDuration = null; 255 } 256 } 257 this.stringName = null; 258 } 259 setAllowBgActivityStarts(IBinder token, int flags)260 void setAllowBgActivityStarts(IBinder token, int flags) { 261 if (token == null) return; 262 if ((flags & FLAG_ACTIVITY_SENDER) != 0) { 263 mAllowBgActivityStartsForActivitySender.add(token); 264 } 265 if ((flags & FLAG_BROADCAST_SENDER) != 0) { 266 mAllowBgActivityStartsForBroadcastSender.add(token); 267 } 268 if ((flags & FLAG_SERVICE_SENDER) != 0) { 269 mAllowBgActivityStartsForServiceSender.add(token); 270 } 271 } 272 clearAllowBgActivityStarts(IBinder token)273 void clearAllowBgActivityStarts(IBinder token) { 274 if (token == null) return; 275 mAllowBgActivityStartsForActivitySender.remove(token); 276 mAllowBgActivityStartsForBroadcastSender.remove(token); 277 mAllowBgActivityStartsForServiceSender.remove(token); 278 } 279 registerCancelListenerLocked(IResultReceiver receiver)280 public void registerCancelListenerLocked(IResultReceiver receiver) { 281 if (mCancelCallbacks == null) { 282 mCancelCallbacks = new RemoteCallbackList<>(); 283 } 284 mCancelCallbacks.register(receiver); 285 } 286 unregisterCancelListenerLocked(IResultReceiver receiver)287 public void unregisterCancelListenerLocked(IResultReceiver receiver) { 288 if (mCancelCallbacks == null) { 289 return; // Already unregistered or detached. 290 } 291 mCancelCallbacks.unregister(receiver); 292 if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) { 293 mCancelCallbacks = null; 294 } 295 } 296 detachCancelListenersLocked()297 public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() { 298 RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks; 299 mCancelCallbacks = null; 300 return listeners; 301 } 302 send(int code, Intent intent, String resolvedType, IBinder allowlistToken, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)303 public void send(int code, Intent intent, String resolvedType, IBinder allowlistToken, 304 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { 305 sendInner(code, intent, resolvedType, allowlistToken, finishedReceiver, 306 requiredPermission, null, null, 0, 0, 0, options); 307 } 308 sendWithResult(int code, Intent intent, String resolvedType, IBinder allowlistToken, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)309 public int sendWithResult(int code, Intent intent, String resolvedType, IBinder allowlistToken, 310 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { 311 return sendInner(code, intent, resolvedType, allowlistToken, finishedReceiver, 312 requiredPermission, null, null, 0, 0, 0, options); 313 } 314 315 /** 316 * Return true if the activity options allows PendingIntent to use caller's BAL permission. 317 */ isPendingIntentBalAllowedByPermission( @ullable ActivityOptions activityOptions)318 public static boolean isPendingIntentBalAllowedByPermission( 319 @Nullable ActivityOptions activityOptions) { 320 if (activityOptions == null) { 321 return false; 322 } 323 return activityOptions.isPendingIntentBackgroundActivityLaunchAllowedByPermission(); 324 } 325 isPendingIntentBalAllowedByCaller( @ullable ActivityOptions activityOptions)326 public static boolean isPendingIntentBalAllowedByCaller( 327 @Nullable ActivityOptions activityOptions) { 328 if (activityOptions == null) { 329 return ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT; 330 } 331 return isPendingIntentBalAllowedByCaller(activityOptions.toBundle()); 332 } 333 isPendingIntentBalAllowedByCaller(@ullable Bundle options)334 private static boolean isPendingIntentBalAllowedByCaller(@Nullable Bundle options) { 335 if (options == null) { 336 return ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT; 337 } 338 return options.getBoolean(ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, 339 ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT); 340 } 341 sendInner(int code, Intent intent, String resolvedType, IBinder allowlistToken, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options)342 public int sendInner(int code, Intent intent, String resolvedType, IBinder allowlistToken, 343 IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, 344 String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) { 345 if (intent != null) intent.setDefusable(true); 346 if (options != null) options.setDefusable(true); 347 348 TempAllowListDuration duration = null; 349 Intent finalIntent = null; 350 Intent[] allIntents = null; 351 String[] allResolvedTypes = null; 352 SafeActivityOptions mergedOptions = null; 353 synchronized (controller.mLock) { 354 if (canceled) { 355 return ActivityManager.START_CANCELED; 356 } 357 358 sent = true; 359 if ((key.flags & PendingIntent.FLAG_ONE_SHOT) != 0) { 360 controller.cancelIntentSender(this, true); 361 } 362 363 finalIntent = key.requestIntent != null ? new Intent(key.requestIntent) : new Intent(); 364 365 final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0; 366 if (!immutable) { 367 if (intent != null) { 368 int changes = finalIntent.fillIn(intent, key.flags); 369 if ((changes & Intent.FILL_IN_DATA) == 0) { 370 resolvedType = key.requestResolvedType; 371 } 372 } else { 373 resolvedType = key.requestResolvedType; 374 } 375 flagsMask &= ~Intent.IMMUTABLE_FLAGS; 376 flagsValues &= flagsMask; 377 finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues); 378 } else { 379 resolvedType = key.requestResolvedType; 380 } 381 382 // Apply any launch flags from the ActivityOptions. This is to ensure that the caller 383 // can specify a consistent launch mode even if the PendingIntent is immutable 384 final ActivityOptions opts = ActivityOptions.fromBundle(options); 385 if (opts != null) { 386 finalIntent.addFlags(opts.getPendingIntentLaunchFlags()); 387 } 388 389 // Extract options before clearing calling identity 390 mergedOptions = key.options; 391 if (mergedOptions == null) { 392 mergedOptions = new SafeActivityOptions(opts); 393 } else { 394 mergedOptions.setCallerOptions(opts); 395 } 396 397 if (mAllowlistDuration != null) { 398 duration = mAllowlistDuration.get(allowlistToken); 399 } 400 401 if (key.type == ActivityManager.INTENT_SENDER_ACTIVITY 402 && key.allIntents != null && key.allIntents.length > 1) { 403 // Copy all intents and resolved types while we have the controller lock so we can 404 // use it later when the lock isn't held. 405 allIntents = new Intent[key.allIntents.length]; 406 allResolvedTypes = new String[key.allIntents.length]; 407 System.arraycopy(key.allIntents, 0, allIntents, 0, key.allIntents.length); 408 if (key.allResolvedTypes != null) { 409 System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0, 410 key.allResolvedTypes.length); 411 } 412 allIntents[allIntents.length - 1] = finalIntent; 413 allResolvedTypes[allResolvedTypes.length - 1] = resolvedType; 414 } 415 416 } 417 // We don't hold the controller lock beyond this point as we will be calling into AM and WM. 418 419 final int callingUid = Binder.getCallingUid(); 420 final int callingPid = Binder.getCallingPid(); 421 422 // Only system senders can declare a broadcast to be alarm-originated. We check 423 // this here rather than in the general case handling below to fail before the other 424 // invocation side effects such as allowlisting. 425 if (options != null && callingUid != Process.SYSTEM_UID 426 && key.type == ActivityManager.INTENT_SENDER_BROADCAST) { 427 if (options.containsKey(BroadcastOptions.KEY_ALARM_BROADCAST)) { 428 if (DEBUG_BROADCAST_LIGHT) { 429 Slog.w(TAG, "Non-system caller " + callingUid 430 + " may not flag broadcast as alarm-related"); 431 } 432 throw new SecurityException( 433 "Non-system callers may not flag broadcasts as alarm-related"); 434 } 435 } 436 437 final long origId = Binder.clearCallingIdentity(); 438 439 int res = START_SUCCESS; 440 try { 441 if (duration != null) { 442 StringBuilder tag = new StringBuilder(64); 443 tag.append("setPendingIntentAllowlistDuration,reason:"); 444 tag.append(duration.reason == null ? "" : duration.reason); 445 tag.append(",pendingintent:"); 446 UserHandle.formatUid(tag, callingUid); 447 tag.append(":"); 448 if (finalIntent.getAction() != null) { 449 tag.append(finalIntent.getAction()); 450 } else if (finalIntent.getComponent() != null) { 451 finalIntent.getComponent().appendShortString(tag); 452 } else if (finalIntent.getData() != null) { 453 tag.append(finalIntent.getData().toSafeString()); 454 } 455 controller.mAmInternal.tempAllowlistForPendingIntent(callingPid, callingUid, 456 uid, duration.duration, duration.type, duration.reasonCode, tag.toString()); 457 } else if (key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE 458 && options != null) { 459 // If this is a getForegroundService() type pending intent, use its BroadcastOptions 460 // temp allowlist duration as its pending intent temp allowlist duration. 461 BroadcastOptions brOptions = new BroadcastOptions(options); 462 if (brOptions.getTemporaryAppAllowlistDuration() > 0) { 463 controller.mAmInternal.tempAllowlistForPendingIntent(callingPid, callingUid, 464 uid, brOptions.getTemporaryAppAllowlistDuration(), 465 brOptions.getTemporaryAppAllowlistType(), 466 brOptions.getTemporaryAppAllowlistReasonCode(), 467 brOptions.getTemporaryAppAllowlistReason()); 468 } 469 } 470 471 boolean sendFinish = finishedReceiver != null; 472 int userId = key.userId; 473 if (userId == UserHandle.USER_CURRENT) { 474 userId = controller.mUserController.getCurrentOrTargetUserId(); 475 } 476 // temporarily allow receivers and services to open activities from background if the 477 // PendingIntent.send() caller was foreground at the time of sendInner() call 478 final boolean allowTrampoline = uid != callingUid 479 && controller.mAtmInternal.isUidForeground(callingUid) 480 && isPendingIntentBalAllowedByCaller(options); 481 482 // note: we on purpose don't pass in the information about the PendingIntent's creator, 483 // like pid or ProcessRecord, to the ActivityTaskManagerInternal calls below, because 484 // it's not unusual for the creator's process to not be alive at this time 485 switch (key.type) { 486 case ActivityManager.INTENT_SENDER_ACTIVITY: 487 try { 488 // Note when someone has a pending intent, even from different 489 // users, then there's no need to ensure the calling user matches 490 // the target user, so validateIncomingUser is always false below. 491 492 if (key.allIntents != null && key.allIntents.length > 1) { 493 res = controller.mAtmInternal.startActivitiesInPackage( 494 uid, callingPid, callingUid, key.packageName, key.featureId, 495 allIntents, allResolvedTypes, resultTo, mergedOptions, userId, 496 false /* validateIncomingUser */, 497 this /* originatingPendingIntent */, 498 mAllowBgActivityStartsForActivitySender.contains( 499 allowlistToken)); 500 } else { 501 res = controller.mAtmInternal.startActivityInPackage(uid, callingPid, 502 callingUid, key.packageName, key.featureId, finalIntent, 503 resolvedType, resultTo, resultWho, requestCode, 0, 504 mergedOptions, userId, null, "PendingIntentRecord", 505 false /* validateIncomingUser */, 506 this /* originatingPendingIntent */, 507 mAllowBgActivityStartsForActivitySender.contains( 508 allowlistToken)); 509 } 510 } catch (RuntimeException e) { 511 Slog.w(TAG, "Unable to send startActivity intent", e); 512 } 513 break; 514 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT: 515 controller.mAtmInternal.sendActivityResult(-1, key.activity, key.who, 516 key.requestCode, code, finalIntent); 517 break; 518 case ActivityManager.INTENT_SENDER_BROADCAST: 519 try { 520 final boolean allowedByToken = 521 mAllowBgActivityStartsForBroadcastSender.contains(allowlistToken); 522 final IBinder bgStartsToken = (allowedByToken) ? allowlistToken : null; 523 524 // If a completion callback has been requested, require 525 // that the broadcast be delivered synchronously 526 int sent = controller.mAmInternal.broadcastIntentInPackage(key.packageName, 527 key.featureId, uid, callingUid, callingPid, finalIntent, 528 resolvedType, finishedReceiver, code, null, null, 529 requiredPermission, options, (finishedReceiver != null), false, 530 userId, allowedByToken || allowTrampoline, bgStartsToken, 531 null /* broadcastAllowList */); 532 if (sent == ActivityManager.BROADCAST_SUCCESS) { 533 sendFinish = false; 534 } 535 } catch (RuntimeException e) { 536 Slog.w(TAG, "Unable to send startActivity intent", e); 537 } 538 break; 539 case ActivityManager.INTENT_SENDER_SERVICE: 540 case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE: 541 try { 542 final boolean allowedByToken = 543 mAllowBgActivityStartsForServiceSender.contains(allowlistToken); 544 final IBinder bgStartsToken = (allowedByToken) ? allowlistToken : null; 545 546 controller.mAmInternal.startServiceInPackage(uid, finalIntent, resolvedType, 547 key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE, 548 key.packageName, key.featureId, userId, 549 allowedByToken || allowTrampoline, bgStartsToken); 550 } catch (RuntimeException e) { 551 Slog.w(TAG, "Unable to send startService intent", e); 552 } catch (TransactionTooLargeException e) { 553 res = ActivityManager.START_CANCELED; 554 } 555 break; 556 } 557 558 if (sendFinish && res != ActivityManager.START_CANCELED) { 559 try { 560 finishedReceiver.performReceive(new Intent(finalIntent), 0, 561 null, null, false, false, key.userId); 562 } catch (RemoteException e) { 563 } 564 } 565 } finally { 566 Binder.restoreCallingIdentity(origId); 567 } 568 569 return res; 570 } 571 572 @Override finalize()573 protected void finalize() throws Throwable { 574 try { 575 if (!canceled) { 576 controller.mH.sendMessage(PooledLambda.obtainMessage( 577 PendingIntentRecord::completeFinalize, this)); 578 } 579 } finally { 580 super.finalize(); 581 } 582 } 583 completeFinalize()584 private void completeFinalize() { 585 synchronized(controller.mLock) { 586 WeakReference<PendingIntentRecord> current = controller.mIntentSenderRecords.get(key); 587 if (current == ref) { 588 controller.mIntentSenderRecords.remove(key); 589 controller.decrementUidStatLocked(this); 590 } 591 } 592 } 593 dump(PrintWriter pw, String prefix)594 public void dump(PrintWriter pw, String prefix) { 595 pw.print(prefix); pw.print("uid="); pw.print(uid); 596 pw.print(" packageName="); pw.print(key.packageName); 597 pw.print(" featureId="); pw.print(key.featureId); 598 pw.print(" type="); pw.print(key.typeName()); 599 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags)); 600 if (key.activity != null || key.who != null) { 601 pw.print(prefix); pw.print("activity="); pw.print(key.activity); 602 pw.print(" who="); pw.println(key.who); 603 } 604 if (key.requestCode != 0 || key.requestResolvedType != null) { 605 pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode); 606 pw.print(" requestResolvedType="); pw.println(key.requestResolvedType); 607 } 608 if (key.requestIntent != null) { 609 pw.print(prefix); pw.print("requestIntent="); 610 pw.println(key.requestIntent.toShortString(false, true, true, false)); 611 } 612 if (sent || canceled) { 613 pw.print(prefix); pw.print("sent="); pw.print(sent); 614 pw.print(" canceled="); pw.println(canceled); 615 } 616 if (mAllowlistDuration != null) { 617 pw.print(prefix); 618 pw.print("allowlistDuration="); 619 for (int i = 0; i < mAllowlistDuration.size(); i++) { 620 if (i != 0) { 621 pw.print(", "); 622 } 623 TempAllowListDuration entry = mAllowlistDuration.valueAt(i); 624 pw.print(Integer.toHexString(System.identityHashCode(mAllowlistDuration.keyAt(i)))); 625 pw.print(":"); 626 TimeUtils.formatDuration(entry.duration, pw); 627 pw.print("/"); 628 pw.print(entry.type); 629 pw.print("/"); 630 pw.print(PowerWhitelistManager.reasonCodeToString(entry.reasonCode)); 631 pw.print("/"); 632 pw.print(entry.reason); 633 } 634 pw.println(); 635 } 636 if (mCancelCallbacks != null) { 637 pw.print(prefix); pw.println("mCancelCallbacks:"); 638 for (int i = 0; i < mCancelCallbacks.getRegisteredCallbackCount(); i++) { 639 pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": "); 640 pw.println(mCancelCallbacks.getRegisteredCallbackItem(i)); 641 } 642 } 643 } 644 toString()645 public String toString() { 646 if (stringName != null) { 647 return stringName; 648 } 649 StringBuilder sb = new StringBuilder(128); 650 sb.append("PendingIntentRecord{"); 651 sb.append(Integer.toHexString(System.identityHashCode(this))); 652 sb.append(' '); 653 sb.append(key.packageName); 654 if (key.featureId != null) { 655 sb.append('/'); 656 sb.append(key.featureId); 657 } 658 sb.append(' '); 659 sb.append(key.typeName()); 660 if (mAllowlistDuration != null) { 661 sb.append(" (allowlist: "); 662 for (int i = 0; i < mAllowlistDuration.size(); i++) { 663 if (i != 0) { 664 sb.append(","); 665 } 666 TempAllowListDuration entry = mAllowlistDuration.valueAt(i); 667 sb.append(Integer.toHexString(System.identityHashCode( 668 mAllowlistDuration.keyAt(i)))); 669 sb.append(":"); 670 TimeUtils.formatDuration(entry.duration, sb); 671 sb.append("/"); 672 sb.append(entry.type); 673 sb.append("/"); 674 sb.append(PowerWhitelistManager.reasonCodeToString(entry.reasonCode)); 675 sb.append("/"); 676 sb.append(entry.reason); 677 } 678 sb.append(")"); 679 } 680 sb.append('}'); 681 return stringName = sb.toString(); 682 } 683 } 684