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