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