• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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