• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.am;
18 
19 import android.app.ActivityManager;
20 import android.content.IIntentSender;
21 import android.content.IIntentReceiver;
22 import android.app.PendingIntent;
23 import android.content.Intent;
24 import android.os.Binder;
25 import android.os.Bundle;
26 import android.os.IBinder;
27 import android.os.RemoteException;
28 import android.os.UserHandle;
29 import android.util.Slog;
30 
31 import java.io.PrintWriter;
32 import java.lang.ref.WeakReference;
33 
34 class PendingIntentRecord extends IIntentSender.Stub {
35     final ActivityManagerService owner;
36     final Key key;
37     final int uid;
38     final WeakReference<PendingIntentRecord> ref;
39     boolean sent = false;
40     boolean canceled = false;
41 
42     String stringName;
43 
44     final static class Key {
45         final int type;
46         final String packageName;
47         final ActivityRecord activity;
48         final String who;
49         final int requestCode;
50         final Intent requestIntent;
51         final String requestResolvedType;
52         final Bundle options;
53         Intent[] allIntents;
54         String[] allResolvedTypes;
55         final int flags;
56         final int hashCode;
57         final int userId;
58 
59         private static final int ODD_PRIME_NUMBER = 37;
60 
Key(int _t, String _p, ActivityRecord _a, String _w, int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId)61         Key(int _t, String _p, ActivityRecord _a, String _w,
62                 int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) {
63             type = _t;
64             packageName = _p;
65             activity = _a;
66             who = _w;
67             requestCode = _r;
68             requestIntent = _i != null ? _i[_i.length-1] : null;
69             requestResolvedType = _it != null ? _it[_it.length-1] : null;
70             allIntents = _i;
71             allResolvedTypes = _it;
72             flags = _f;
73             options = _o;
74             userId = _userId;
75 
76             int hash = 23;
77             hash = (ODD_PRIME_NUMBER*hash) + _f;
78             hash = (ODD_PRIME_NUMBER*hash) + _r;
79             hash = (ODD_PRIME_NUMBER*hash) + _userId;
80             if (_w != null) {
81                 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
82             }
83             if (_a != null) {
84                 hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode();
85             }
86             if (requestIntent != null) {
87                 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode();
88             }
89             if (requestResolvedType != null) {
90                 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode();
91             }
92             hash = (ODD_PRIME_NUMBER*hash) + _p.hashCode();
93             hash = (ODD_PRIME_NUMBER*hash) + _t;
94             hashCode = hash;
95             //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x"
96             //        + Integer.toHexString(hashCode));
97         }
98 
equals(Object otherObj)99         public boolean equals(Object otherObj) {
100             if (otherObj == null) {
101                 return false;
102             }
103             try {
104                 Key other = (Key)otherObj;
105                 if (type != other.type) {
106                     return false;
107                 }
108                 if (userId != other.userId){
109                     return false;
110                 }
111                 if (!packageName.equals(other.packageName)) {
112                     return false;
113                 }
114                 if (activity != other.activity) {
115                     return false;
116                 }
117                 if (who != other.who) {
118                     if (who != null) {
119                         if (!who.equals(other.who)) {
120                             return false;
121                         }
122                     } else if (other.who != null) {
123                         return false;
124                     }
125                 }
126                 if (requestCode != other.requestCode) {
127                     return false;
128                 }
129                 if (requestIntent != other.requestIntent) {
130                     if (requestIntent != null) {
131                         if (!requestIntent.filterEquals(other.requestIntent)) {
132                             return false;
133                         }
134                     } else if (other.requestIntent != null) {
135                         return false;
136                     }
137                 }
138                 if (requestResolvedType != other.requestResolvedType) {
139                     if (requestResolvedType != null) {
140                         if (!requestResolvedType.equals(other.requestResolvedType)) {
141                             return false;
142                         }
143                     } else if (other.requestResolvedType != null) {
144                         return false;
145                     }
146                 }
147                 if (flags != other.flags) {
148                     return false;
149                 }
150                 return true;
151             } catch (ClassCastException e) {
152             }
153             return false;
154         }
155 
hashCode()156         public int hashCode() {
157             return hashCode;
158         }
159 
toString()160         public String toString() {
161             return "Key{" + typeName() + " pkg=" + packageName
162                 + " intent="
163                 + (requestIntent != null
164                         ? requestIntent.toShortString(false, true, false, false) : "<null>")
165                 + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
166         }
167 
typeName()168         String typeName() {
169             switch (type) {
170                 case ActivityManager.INTENT_SENDER_ACTIVITY:
171                     return "startActivity";
172                 case ActivityManager.INTENT_SENDER_BROADCAST:
173                     return "broadcastIntent";
174                 case ActivityManager.INTENT_SENDER_SERVICE:
175                     return "startService";
176                 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
177                     return "activityResult";
178             }
179             return Integer.toString(type);
180         }
181     }
182 
PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u)183     PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) {
184         owner = _owner;
185         key = _k;
186         uid = _u;
187         ref = new WeakReference<PendingIntentRecord>(this);
188     }
189 
send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission)190     public int send(int code, Intent intent, String resolvedType,
191             IIntentReceiver finishedReceiver, String requiredPermission) {
192         return sendInner(code, intent, resolvedType, finishedReceiver,
193                 requiredPermission, null, null, 0, 0, 0, null);
194     }
195 
sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options)196     int sendInner(int code, Intent intent, String resolvedType,
197             IIntentReceiver finishedReceiver, String requiredPermission,
198             IBinder resultTo, String resultWho, int requestCode,
199             int flagsMask, int flagsValues, Bundle options) {
200         synchronized(owner) {
201             if (!canceled) {
202                 sent = true;
203                 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
204                     owner.cancelIntentSenderLocked(this, true);
205                     canceled = true;
206                 }
207                 Intent finalIntent = key.requestIntent != null
208                         ? new Intent(key.requestIntent) : new Intent();
209                 if (intent != null) {
210                     int changes = finalIntent.fillIn(intent, key.flags);
211                     if ((changes&Intent.FILL_IN_DATA) == 0) {
212                         resolvedType = key.requestResolvedType;
213                     }
214                 } else {
215                     resolvedType = key.requestResolvedType;
216                 }
217                 flagsMask &= ~Intent.IMMUTABLE_FLAGS;
218                 flagsValues &= flagsMask;
219                 finalIntent.setFlags((finalIntent.getFlags()&~flagsMask) | flagsValues);
220 
221                 final long origId = Binder.clearCallingIdentity();
222 
223                 boolean sendFinish = finishedReceiver != null;
224                 int userId = key.userId;
225                 if (userId == UserHandle.USER_CURRENT) {
226                     userId = owner.getCurrentUserIdLocked();
227                 }
228                 switch (key.type) {
229                     case ActivityManager.INTENT_SENDER_ACTIVITY:
230                         if (options == null) {
231                             options = key.options;
232                         } else if (key.options != null) {
233                             Bundle opts = new Bundle(key.options);
234                             opts.putAll(options);
235                             options = opts;
236                         }
237                         try {
238                             if (key.allIntents != null && key.allIntents.length > 1) {
239                                 Intent[] allIntents = new Intent[key.allIntents.length];
240                                 String[] allResolvedTypes = new String[key.allIntents.length];
241                                 System.arraycopy(key.allIntents, 0, allIntents, 0,
242                                         key.allIntents.length);
243                                 if (key.allResolvedTypes != null) {
244                                     System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
245                                             key.allResolvedTypes.length);
246                                 }
247                                 allIntents[allIntents.length-1] = finalIntent;
248                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
249                                 owner.startActivitiesInPackage(uid, key.packageName, allIntents,
250                                         allResolvedTypes, resultTo, options, userId);
251                             } else {
252                                 owner.startActivityInPackage(uid, key.packageName, finalIntent,
253                                         resolvedType, resultTo, resultWho, requestCode, 0,
254                                         options, userId);
255                             }
256                         } catch (RuntimeException e) {
257                             Slog.w(ActivityManagerService.TAG,
258                                     "Unable to send startActivity intent", e);
259                         }
260                         break;
261                     case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
262                         key.activity.stack.sendActivityResultLocked(-1, key.activity,
263                                 key.who, key.requestCode, code, finalIntent);
264                         break;
265                     case ActivityManager.INTENT_SENDER_BROADCAST:
266                         try {
267                             // If a completion callback has been requested, require
268                             // that the broadcast be delivered synchronously
269                             owner.broadcastIntentInPackage(key.packageName, uid,
270                                     finalIntent, resolvedType,
271                                     finishedReceiver, code, null, null,
272                                 requiredPermission, (finishedReceiver != null), false, userId);
273                             sendFinish = false;
274                         } catch (RuntimeException e) {
275                             Slog.w(ActivityManagerService.TAG,
276                                     "Unable to send startActivity intent", e);
277                         }
278                         break;
279                     case ActivityManager.INTENT_SENDER_SERVICE:
280                         try {
281                             owner.startServiceInPackage(uid,
282                                     finalIntent, resolvedType, userId);
283                         } catch (RuntimeException e) {
284                             Slog.w(ActivityManagerService.TAG,
285                                     "Unable to send startService intent", e);
286                         }
287                         break;
288                 }
289 
290                 if (sendFinish) {
291                     try {
292                         finishedReceiver.performReceive(new Intent(finalIntent), 0,
293                                 null, null, false, false, key.userId);
294                     } catch (RemoteException e) {
295                     }
296                 }
297 
298                 Binder.restoreCallingIdentity(origId);
299 
300                 return 0;
301             }
302         }
303         return ActivityManager.START_CANCELED;
304     }
305 
finalize()306     protected void finalize() throws Throwable {
307         try {
308             if (!canceled) {
309                 owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
310                         ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
311             }
312         } finally {
313             super.finalize();
314         }
315     }
316 
completeFinalize()317     public void completeFinalize() {
318         synchronized(owner) {
319             WeakReference<PendingIntentRecord> current =
320                     owner.mIntentSenderRecords.get(key);
321             if (current == ref) {
322                 owner.mIntentSenderRecords.remove(key);
323             }
324         }
325     }
326 
dump(PrintWriter pw, String prefix)327     void dump(PrintWriter pw, String prefix) {
328         pw.print(prefix); pw.print("uid="); pw.print(uid);
329                 pw.print(" packageName="); pw.print(key.packageName);
330                 pw.print(" type="); pw.print(key.typeName());
331                 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
332         if (key.activity != null || key.who != null) {
333             pw.print(prefix); pw.print("activity="); pw.print(key.activity);
334                     pw.print(" who="); pw.println(key.who);
335         }
336         if (key.requestCode != 0 || key.requestResolvedType != null) {
337             pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
338                     pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
339         }
340         if (key.requestIntent != null) {
341             pw.print(prefix); pw.print("requestIntent=");
342                     pw.println(key.requestIntent.toShortString(false, true, true, true));
343         }
344         if (sent || canceled) {
345             pw.print(prefix); pw.print("sent="); pw.print(sent);
346                     pw.print(" canceled="); pw.println(canceled);
347         }
348     }
349 
toString()350     public String toString() {
351         if (stringName != null) {
352             return stringName;
353         }
354         StringBuilder sb = new StringBuilder(128);
355         sb.append("PendingIntentRecord{");
356         sb.append(Integer.toHexString(System.identityHashCode(this)));
357         sb.append(' ');
358         sb.append(key.packageName);
359         sb.append(' ');
360         sb.append(key.typeName());
361         sb.append('}');
362         return stringName = sb.toString();
363     }
364 }
365