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