OSDN Git Service

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