OSDN Git Service

[RESTRICT AUTOMERGE] Pass correct realCallingUid to startActivity() if provided by...
[android-x86/frameworks-base.git] / services / core / java / com / android / server / am / PendingIntentRecord.java
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.Slog;
38 import android.util.TimeUtils;
39
40 import com.android.internal.os.IResultReceiver;
41
42 import java.io.PrintWriter;
43 import java.lang.ref.WeakReference;
44 import java.util.Objects;
45
46 final class PendingIntentRecord extends IIntentSender.Stub {
47     private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM;
48
49     final ActivityManagerService owner;
50     final Key key;
51     final int uid;
52     final WeakReference<PendingIntentRecord> ref;
53     boolean sent = false;
54     boolean canceled = false;
55     private ArrayMap<IBinder, Long> whitelistDuration;
56     private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
57
58     String stringName;
59     String lastTagPrefix;
60     String lastTag;
61
62     final static class Key {
63         final int type;
64         final String packageName;
65         final ActivityRecord activity;
66         final String who;
67         final int requestCode;
68         final Intent requestIntent;
69         final String requestResolvedType;
70         final SafeActivityOptions options;
71         Intent[] allIntents;
72         String[] allResolvedTypes;
73         final int flags;
74         final int hashCode;
75         final int userId;
76
77         private static final int ODD_PRIME_NUMBER = 37;
78
79         Key(int _t, String _p, ActivityRecord _a, String _w,
80                 int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId) {
81             type = _t;
82             packageName = _p;
83             activity = _a;
84             who = _w;
85             requestCode = _r;
86             requestIntent = _i != null ? _i[_i.length-1] : null;
87             requestResolvedType = _it != null ? _it[_it.length-1] : null;
88             allIntents = _i;
89             allResolvedTypes = _it;
90             flags = _f;
91             options = _o;
92             userId = _userId;
93
94             int hash = 23;
95             hash = (ODD_PRIME_NUMBER*hash) + _f;
96             hash = (ODD_PRIME_NUMBER*hash) + _r;
97             hash = (ODD_PRIME_NUMBER*hash) + _userId;
98             if (_w != null) {
99                 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
100             }
101             if (_a != null) {
102                 hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode();
103             }
104             if (requestIntent != null) {
105                 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode();
106             }
107             if (requestResolvedType != null) {
108                 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode();
109             }
110             hash = (ODD_PRIME_NUMBER*hash) + (_p != null ? _p.hashCode() : 0);
111             hash = (ODD_PRIME_NUMBER*hash) + _t;
112             hashCode = hash;
113             //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x"
114             //        + Integer.toHexString(hashCode));
115         }
116
117         public boolean equals(Object otherObj) {
118             if (otherObj == null) {
119                 return false;
120             }
121             try {
122                 Key other = (Key)otherObj;
123                 if (type != other.type) {
124                     return false;
125                 }
126                 if (userId != other.userId){
127                     return false;
128                 }
129                 if (!Objects.equals(packageName, other.packageName)) {
130                     return false;
131                 }
132                 if (activity != other.activity) {
133                     return false;
134                 }
135                 if (!Objects.equals(who, other.who)) {
136                     return false;
137                 }
138                 if (requestCode != other.requestCode) {
139                     return false;
140                 }
141                 if (requestIntent != other.requestIntent) {
142                     if (requestIntent != null) {
143                         if (!requestIntent.filterEquals(other.requestIntent)) {
144                             return false;
145                         }
146                     } else if (other.requestIntent != null) {
147                         return false;
148                     }
149                 }
150                 if (!Objects.equals(requestResolvedType, other.requestResolvedType)) {
151                     return false;
152                 }
153                 if (flags != other.flags) {
154                     return false;
155                 }
156                 return true;
157             } catch (ClassCastException e) {
158             }
159             return false;
160         }
161
162         public int hashCode() {
163             return hashCode;
164         }
165
166         public String toString() {
167             return "Key{" + typeName() + " pkg=" + packageName
168                 + " intent="
169                 + (requestIntent != null
170                         ? requestIntent.toShortString(false, true, false, false) : "<null>")
171                 + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
172         }
173
174         String typeName() {
175             switch (type) {
176                 case ActivityManager.INTENT_SENDER_ACTIVITY:
177                     return "startActivity";
178                 case ActivityManager.INTENT_SENDER_BROADCAST:
179                     return "broadcastIntent";
180                 case ActivityManager.INTENT_SENDER_SERVICE:
181                     return "startService";
182                 case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
183                     return "startForegroundService";
184                 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
185                     return "activityResult";
186             }
187             return Integer.toString(type);
188         }
189     }
190
191     PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) {
192         owner = _owner;
193         key = _k;
194         uid = _u;
195         ref = new WeakReference<PendingIntentRecord>(this);
196     }
197
198     void setWhitelistDurationLocked(IBinder whitelistToken, long duration) {
199         if (duration > 0) {
200             if (whitelistDuration == null) {
201                 whitelistDuration = new ArrayMap<>();
202             }
203             whitelistDuration.put(whitelistToken, duration);
204         } else if (whitelistDuration != null) {
205             whitelistDuration.remove(whitelistToken);
206             if (whitelistDuration.size() <= 0) {
207                 whitelistDuration = null;
208             }
209
210         }
211         this.stringName = null;
212     }
213
214     public void registerCancelListenerLocked(IResultReceiver receiver) {
215         if (mCancelCallbacks == null) {
216             mCancelCallbacks = new RemoteCallbackList<>();
217         }
218         mCancelCallbacks.register(receiver);
219     }
220
221     public void unregisterCancelListenerLocked(IResultReceiver receiver) {
222         if (mCancelCallbacks == null) {
223             return; // Already unregistered or detached.
224         }
225         mCancelCallbacks.unregister(receiver);
226         if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) {
227             mCancelCallbacks = null;
228         }
229     }
230
231     public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() {
232         RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks;
233         mCancelCallbacks = null;
234         return listeners;
235     }
236
237     public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
238             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
239         sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
240                 requiredPermission, null, null, 0, 0, 0, options);
241     }
242
243     public int sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken,
244             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
245         return sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
246                 requiredPermission, null, null, 0, 0, 0, options);
247     }
248
249     int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
250             IIntentReceiver finishedReceiver,
251             String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
252             int flagsMask, int flagsValues, Bundle options) {
253         if (intent != null) intent.setDefusable(true);
254         if (options != null) options.setDefusable(true);
255
256         synchronized (owner) {
257             if (!canceled) {
258                 sent = true;
259                 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
260                     owner.cancelIntentSenderLocked(this, true);
261                 }
262
263                 Intent finalIntent = key.requestIntent != null
264                         ? new Intent(key.requestIntent) : new Intent();
265
266                 final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
267                 if (!immutable) {
268                     if (intent != null) {
269                         int changes = finalIntent.fillIn(intent, key.flags);
270                         if ((changes & Intent.FILL_IN_DATA) == 0) {
271                             resolvedType = key.requestResolvedType;
272                         }
273                     } else {
274                         resolvedType = key.requestResolvedType;
275                     }
276                     flagsMask &= ~Intent.IMMUTABLE_FLAGS;
277                     flagsValues &= flagsMask;
278                     finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
279                 } else {
280                     resolvedType = key.requestResolvedType;
281                 }
282
283                 final int callingUid = Binder.getCallingUid();
284                 final int callingPid = Binder.getCallingPid();
285
286                 // Extract options before clearing calling identity
287                 SafeActivityOptions mergedOptions = key.options;
288                 if (mergedOptions == null) {
289                     mergedOptions = SafeActivityOptions.fromBundle(options);
290                 } else {
291                     mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options));
292                 }
293
294                 final long origId = Binder.clearCallingIdentity();
295
296                 if (whitelistDuration != null) {
297                     Long duration = whitelistDuration.get(whitelistToken);
298                     if (duration != null) {
299                         int procState = owner.getUidState(callingUid);
300                         if (!ActivityManager.isProcStateBackground(procState)) {
301                             StringBuilder tag = new StringBuilder(64);
302                             tag.append("pendingintent:");
303                             UserHandle.formatUid(tag, callingUid);
304                             tag.append(":");
305                             if (finalIntent.getAction() != null) {
306                                 tag.append(finalIntent.getAction());
307                             } else if (finalIntent.getComponent() != null) {
308                                 finalIntent.getComponent().appendShortString(tag);
309                             } else if (finalIntent.getData() != null) {
310                                 tag.append(finalIntent.getData().toSafeString());
311                             }
312                             owner.tempWhitelistForPendingIntentLocked(callingPid,
313                                     callingUid, uid, duration, tag.toString());
314                         } else {
315                             Slog.w(TAG, "Not doing whitelist " + this + ": caller state="
316                                     + procState);
317                         }
318                     }
319                 }
320
321                 boolean sendFinish = finishedReceiver != null;
322                 int userId = key.userId;
323                 if (userId == UserHandle.USER_CURRENT) {
324                     userId = owner.mUserController.getCurrentOrTargetUserId();
325                 }
326                 int res = START_SUCCESS;
327                 switch (key.type) {
328                     case ActivityManager.INTENT_SENDER_ACTIVITY:
329                         try {
330                             // Note when someone has a pending intent, even from different
331                             // users, then there's no need to ensure the calling user matches
332                             // the target user, so validateIncomingUser is always false below.
333
334                             if (key.allIntents != null && key.allIntents.length > 1) {
335                                 Intent[] allIntents = new Intent[key.allIntents.length];
336                                 String[] allResolvedTypes = new String[key.allIntents.length];
337                                 System.arraycopy(key.allIntents, 0, allIntents, 0,
338                                         key.allIntents.length);
339                                 if (key.allResolvedTypes != null) {
340                                     System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
341                                             key.allResolvedTypes.length);
342                                 }
343                                 allIntents[allIntents.length-1] = finalIntent;
344                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
345
346                                 res = owner.getActivityStartController().startActivitiesInPackage(
347                                         uid, callingPid, callingUid, key.packageName, allIntents,
348                                         allResolvedTypes, resultTo, mergedOptions, userId,
349                                         false /* validateIncomingUser */,
350                                         this /* originatingPendingIntent */);
351                             } else {
352                                 res = owner.getActivityStartController().startActivityInPackage(uid,
353                                         callingPid, callingUid, key.packageName, finalIntent,
354                                         resolvedType, resultTo, resultWho, requestCode, 0,
355                                         mergedOptions, userId, null, "PendingIntentRecord",
356                                         false /* validateIncomingUser */,
357                                         this /* originatingPendingIntent */);
358                             }
359                         } catch (RuntimeException e) {
360                             Slog.w(TAG, "Unable to send startActivity intent", e);
361                         }
362                         break;
363                     case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
364                         final ActivityStack stack = key.activity.getStack();
365                         if (stack != null) {
366                             stack.sendActivityResultLocked(-1, key.activity, key.who,
367                                     key.requestCode, code, finalIntent);
368                         }
369                         break;
370                     case ActivityManager.INTENT_SENDER_BROADCAST:
371                         try {
372                             // If a completion callback has been requested, require
373                             // that the broadcast be delivered synchronously
374                             int sent = owner.broadcastIntentInPackage(key.packageName, uid,
375                                     finalIntent, resolvedType, finishedReceiver, code, null, null,
376                                     requiredPermission, options, (finishedReceiver != null),
377                                     false, userId);
378                             if (sent == ActivityManager.BROADCAST_SUCCESS) {
379                                 sendFinish = false;
380                             }
381                         } catch (RuntimeException e) {
382                             Slog.w(TAG, "Unable to send startActivity intent", e);
383                         }
384                         break;
385                     case ActivityManager.INTENT_SENDER_SERVICE:
386                     case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
387                         try {
388                             owner.startServiceInPackage(uid, finalIntent, resolvedType,
389                                     key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
390                                     key.packageName, userId);
391                         } catch (RuntimeException e) {
392                             Slog.w(TAG, "Unable to send startService intent", e);
393                         } catch (TransactionTooLargeException e) {
394                             res = ActivityManager.START_CANCELED;
395                         }
396                         break;
397                 }
398
399                 if (sendFinish && res != ActivityManager.START_CANCELED) {
400                     try {
401                         finishedReceiver.performReceive(new Intent(finalIntent), 0,
402                                 null, null, false, false, key.userId);
403                     } catch (RemoteException e) {
404                     }
405                 }
406
407                 Binder.restoreCallingIdentity(origId);
408
409                 return res;
410             }
411         }
412         return ActivityManager.START_CANCELED;
413     }
414
415     @Override
416     protected void finalize() throws Throwable {
417         try {
418             if (!canceled) {
419                 owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
420                         ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
421             }
422         } finally {
423             super.finalize();
424         }
425     }
426
427     public void completeFinalize() {
428         synchronized(owner) {
429             WeakReference<PendingIntentRecord> current =
430                     owner.mIntentSenderRecords.get(key);
431             if (current == ref) {
432                 owner.mIntentSenderRecords.remove(key);
433             }
434         }
435     }
436
437     void dump(PrintWriter pw, String prefix) {
438         pw.print(prefix); pw.print("uid="); pw.print(uid);
439                 pw.print(" packageName="); pw.print(key.packageName);
440                 pw.print(" type="); pw.print(key.typeName());
441                 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
442         if (key.activity != null || key.who != null) {
443             pw.print(prefix); pw.print("activity="); pw.print(key.activity);
444                     pw.print(" who="); pw.println(key.who);
445         }
446         if (key.requestCode != 0 || key.requestResolvedType != null) {
447             pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
448                     pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
449         }
450         if (key.requestIntent != null) {
451             pw.print(prefix); pw.print("requestIntent=");
452                     pw.println(key.requestIntent.toShortString(false, true, true, true));
453         }
454         if (sent || canceled) {
455             pw.print(prefix); pw.print("sent="); pw.print(sent);
456                     pw.print(" canceled="); pw.println(canceled);
457         }
458         if (whitelistDuration != null) {
459             pw.print(prefix);
460             pw.print("whitelistDuration=");
461             for (int i = 0; i < whitelistDuration.size(); i++) {
462                 if (i != 0) {
463                     pw.print(", ");
464                 }
465                 pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
466                 pw.print(":");
467                 TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw);
468             }
469             pw.println();
470         }
471         if (mCancelCallbacks != null) {
472             pw.print(prefix); pw.println("mCancelCallbacks:");
473             for (int i = 0; i < mCancelCallbacks.getRegisteredCallbackCount(); i++) {
474                 pw.print(prefix); pw.print("  #"); pw.print(i); pw.print(": ");
475                 pw.println(mCancelCallbacks.getRegisteredCallbackItem(i));
476             }
477         }
478     }
479
480     public String toString() {
481         if (stringName != null) {
482             return stringName;
483         }
484         StringBuilder sb = new StringBuilder(128);
485         sb.append("PendingIntentRecord{");
486         sb.append(Integer.toHexString(System.identityHashCode(this)));
487         sb.append(' ');
488         sb.append(key.packageName);
489         sb.append(' ');
490         sb.append(key.typeName());
491         if (whitelistDuration != null) {
492             sb.append( " (whitelist: ");
493             for (int i = 0; i < whitelistDuration.size(); i++) {
494                 if (i != 0) {
495                     sb.append(",");
496                 }
497                 sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
498                 sb.append(":");
499                 TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb);
500             }
501             sb.append(")");
502         }
503         sb.append('}');
504         return stringName = sb.toString();
505     }
506 }