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