• 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.IActivityManager;
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.IBinder;
26 import android.os.RemoteException;
27 import android.util.Slog;
28 
29 import java.io.PrintWriter;
30 import java.lang.ref.WeakReference;
31 
32 class PendingIntentRecord extends IIntentSender.Stub {
33     final ActivityManagerService owner;
34     final Key key;
35     final int uid;
36     final WeakReference<PendingIntentRecord> ref;
37     boolean sent = false;
38     boolean canceled = false;
39 
40     String stringName;
41 
42     final static class Key {
43         final int type;
44         final String packageName;
45         final ActivityRecord activity;
46         final String who;
47         final int requestCode;
48         final Intent requestIntent;
49         final String requestResolvedType;
50         Intent[] allIntents;
51         String[] allResolvedTypes;
52         final int flags;
53         final int hashCode;
54 
55         private static final int ODD_PRIME_NUMBER = 37;
56 
Key(int _t, String _p, ActivityRecord _a, String _w, int _r, Intent[] _i, String[] _it, int _f)57         Key(int _t, String _p, ActivityRecord _a, String _w,
58                 int _r, Intent[] _i, String[] _it, int _f) {
59             type = _t;
60             packageName = _p;
61             activity = _a;
62             who = _w;
63             requestCode = _r;
64             requestIntent = _i != null ? _i[_i.length-1] : null;
65             requestResolvedType = _it != null ? _it[_it.length-1] : null;
66             allIntents = _i;
67             allResolvedTypes = _it;
68             flags = _f;
69 
70             int hash = 23;
71             hash = (ODD_PRIME_NUMBER*hash) + _f;
72             hash = (ODD_PRIME_NUMBER*hash) + _r;
73             if (_w != null) {
74                 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
75             }
76             if (_a != null) {
77                 hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode();
78             }
79             if (requestIntent != null) {
80                 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode();
81             }
82             if (requestResolvedType != null) {
83                 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode();
84             }
85             hash = (ODD_PRIME_NUMBER*hash) + _p.hashCode();
86             hash = (ODD_PRIME_NUMBER*hash) + _t;
87             hashCode = hash;
88             //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x"
89             //        + Integer.toHexString(hashCode));
90         }
91 
equals(Object otherObj)92         public boolean equals(Object otherObj) {
93             if (otherObj == null) {
94                 return false;
95             }
96             try {
97                 Key other = (Key)otherObj;
98                 if (type != other.type) {
99                     return false;
100                 }
101                 if (!packageName.equals(other.packageName)) {
102                     return false;
103                 }
104                 if (activity != other.activity) {
105                     return false;
106                 }
107                 if (who != other.who) {
108                     if (who != null) {
109                         if (!who.equals(other.who)) {
110                             return false;
111                         }
112                     } else if (other.who != null) {
113                         return false;
114                     }
115                 }
116                 if (requestCode != other.requestCode) {
117                     return false;
118                 }
119                 if (requestIntent != other.requestIntent) {
120                     if (requestIntent != null) {
121                         if (!requestIntent.filterEquals(other.requestIntent)) {
122                             return false;
123                         }
124                     } else if (other.requestIntent != null) {
125                         return false;
126                     }
127                 }
128                 if (requestResolvedType != other.requestResolvedType) {
129                     if (requestResolvedType != null) {
130                         if (!requestResolvedType.equals(other.requestResolvedType)) {
131                             return false;
132                         }
133                     } else if (other.requestResolvedType != null) {
134                         return false;
135                     }
136                 }
137                 if (flags != other.flags) {
138                     return false;
139                 }
140                 return true;
141             } catch (ClassCastException e) {
142             }
143             return false;
144         }
145 
hashCode()146         public int hashCode() {
147             return hashCode;
148         }
149 
toString()150         public String toString() {
151             return "Key{" + typeName() + " pkg=" + packageName
152                 + " intent="
153                 + (requestIntent != null
154                         ? requestIntent.toShortString(false, true, false) : "<null>")
155                 + " flags=0x" + Integer.toHexString(flags) + "}";
156         }
157 
typeName()158         String typeName() {
159             switch (type) {
160                 case IActivityManager.INTENT_SENDER_ACTIVITY:
161                     return "startActivity";
162                 case IActivityManager.INTENT_SENDER_BROADCAST:
163                     return "broadcastIntent";
164                 case IActivityManager.INTENT_SENDER_SERVICE:
165                     return "startService";
166                 case IActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
167                     return "activityResult";
168             }
169             return Integer.toString(type);
170         }
171     }
172 
PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u)173     PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) {
174         owner = _owner;
175         key = _k;
176         uid = _u;
177         ref = new WeakReference<PendingIntentRecord>(this);
178     }
179 
send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission)180     public int send(int code, Intent intent, String resolvedType,
181             IIntentReceiver finishedReceiver, String requiredPermission) {
182         return sendInner(code, intent, resolvedType, finishedReceiver,
183                 requiredPermission, null, null, 0, 0, 0);
184     }
185 
sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues)186     int sendInner(int code, Intent intent, String resolvedType,
187             IIntentReceiver finishedReceiver, String requiredPermission,
188             IBinder resultTo, String resultWho, int requestCode,
189             int flagsMask, int flagsValues) {
190         synchronized(owner) {
191             if (!canceled) {
192                 sent = true;
193                 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
194                     owner.cancelIntentSenderLocked(this, true);
195                     canceled = true;
196                 }
197                 Intent finalIntent = key.requestIntent != null
198                         ? new Intent(key.requestIntent) : new Intent();
199                 if (intent != null) {
200                     int changes = finalIntent.fillIn(intent, key.flags);
201                     if ((changes&Intent.FILL_IN_DATA) == 0) {
202                         resolvedType = key.requestResolvedType;
203                     }
204                 } else {
205                     resolvedType = key.requestResolvedType;
206                 }
207                 flagsMask &= ~Intent.IMMUTABLE_FLAGS;
208                 flagsValues &= flagsMask;
209                 finalIntent.setFlags((finalIntent.getFlags()&~flagsMask) | flagsValues);
210 
211                 final long origId = Binder.clearCallingIdentity();
212 
213                 boolean sendFinish = finishedReceiver != null;
214                 switch (key.type) {
215                     case IActivityManager.INTENT_SENDER_ACTIVITY:
216                         try {
217                             if (key.allIntents != null && key.allIntents.length > 1) {
218                                 Intent[] allIntents = new Intent[key.allIntents.length];
219                                 String[] allResolvedTypes = new String[key.allIntents.length];
220                                 System.arraycopy(key.allIntents, 0, allIntents, 0,
221                                         key.allIntents.length);
222                                 if (key.allResolvedTypes != null) {
223                                     System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
224                                             key.allResolvedTypes.length);
225                                 }
226                                 allIntents[allIntents.length-1] = finalIntent;
227                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
228                                 owner.startActivitiesInPackage(uid, allIntents,
229                                         allResolvedTypes, resultTo);
230                             } else {
231                                 owner.startActivityInPackage(uid,
232                                         finalIntent, resolvedType,
233                                         resultTo, resultWho, requestCode, false);
234                             }
235                         } catch (RuntimeException e) {
236                             Slog.w(ActivityManagerService.TAG,
237                                     "Unable to send startActivity intent", e);
238                         }
239                         break;
240                     case IActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
241                         key.activity.stack.sendActivityResultLocked(-1, key.activity,
242                                 key.who, key.requestCode, code, finalIntent);
243                         break;
244                     case IActivityManager.INTENT_SENDER_BROADCAST:
245                         try {
246                             // If a completion callback has been requested, require
247                             // that the broadcast be delivered synchronously
248                             owner.broadcastIntentInPackage(key.packageName, uid,
249                                     finalIntent, resolvedType,
250                                     finishedReceiver, code, null, null,
251                                     requiredPermission, (finishedReceiver != null), false);
252                             sendFinish = false;
253                         } catch (RuntimeException e) {
254                             Slog.w(ActivityManagerService.TAG,
255                                     "Unable to send startActivity intent", e);
256                         }
257                         break;
258                     case IActivityManager.INTENT_SENDER_SERVICE:
259                         try {
260                             owner.startServiceInPackage(uid,
261                                     finalIntent, resolvedType);
262                         } catch (RuntimeException e) {
263                             Slog.w(ActivityManagerService.TAG,
264                                     "Unable to send startService intent", e);
265                         }
266                         break;
267                 }
268 
269                 if (sendFinish) {
270                     try {
271                         finishedReceiver.performReceive(new Intent(finalIntent), 0,
272                                 null, null, false, false);
273                     } catch (RemoteException e) {
274                     }
275                 }
276 
277                 Binder.restoreCallingIdentity(origId);
278 
279                 return 0;
280             }
281         }
282         return IActivityManager.START_CANCELED;
283     }
284 
finalize()285     protected void finalize() throws Throwable {
286         try {
287             if (!canceled) {
288                 owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
289                         ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
290             }
291         } finally {
292             super.finalize();
293         }
294     }
295 
completeFinalize()296     public void completeFinalize() {
297         synchronized(owner) {
298             WeakReference<PendingIntentRecord> current =
299                     owner.mIntentSenderRecords.get(key);
300             if (current == ref) {
301                 owner.mIntentSenderRecords.remove(key);
302             }
303         }
304     }
305 
dump(PrintWriter pw, String prefix)306     void dump(PrintWriter pw, String prefix) {
307         pw.print(prefix); pw.print("uid="); pw.print(uid);
308                 pw.print(" packageName="); pw.print(key.packageName);
309                 pw.print(" type="); pw.print(key.typeName());
310                 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
311         if (key.activity != null || key.who != null) {
312             pw.print(prefix); pw.print("activity="); pw.print(key.activity);
313                     pw.print(" who="); pw.println(key.who);
314         }
315         if (key.requestCode != 0 || key.requestResolvedType != null) {
316             pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
317                     pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
318         }
319         if (key.requestIntent != null) {
320             pw.print(prefix); pw.print("requestIntent=");
321                     pw.println(key.requestIntent.toShortString(false, true, true));
322         }
323         if (sent || canceled) {
324             pw.print(prefix); pw.print("sent="); pw.print(sent);
325                     pw.print(" canceled="); pw.println(canceled);
326         }
327     }
328 
toString()329     public String toString() {
330         if (stringName != null) {
331             return stringName;
332         }
333         StringBuilder sb = new StringBuilder(128);
334         sb.append("PendingIntentRecord{");
335         sb.append(Integer.toHexString(System.identityHashCode(this)));
336         sb.append(' ');
337         sb.append(key.packageName);
338         sb.append(' ');
339         sb.append(key.typeName());
340         sb.append('}');
341         return stringName = sb.toString();
342     }
343 }
344