blob: 8ab71dd2c2a315b0d5e4f29ae1427398148219ae [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package com.android.server.am;
18
Dianne Hackborna4972e92012-03-14 10:38:05 -070019import android.app.ActivityManager;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070020import android.content.IIntentSender;
21import android.content.IIntentReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.app.PendingIntent;
23import android.content.Intent;
24import android.os.Binder;
Dianne Hackborna4972e92012-03-14 10:38:05 -070025import android.os.Bundle;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070026import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.os.RemoteException;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -070028import android.os.UserHandle;
Joe Onorato8a9b2202010-02-26 18:56:32 -080029import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
31import java.io.PrintWriter;
32import java.lang.ref.WeakReference;
33
34class 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
Dianne Hackborn1d442e02009-04-20 18:14:05 -070042 String stringName;
43
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044 final static class Key {
45 final int type;
46 final String packageName;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070047 final ActivityRecord activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 final String who;
49 final int requestCode;
50 final Intent requestIntent;
51 final String requestResolvedType;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -070052 final Bundle options;
Dianne Hackborn621e17d2010-11-22 15:59:56 -080053 Intent[] allIntents;
54 String[] allResolvedTypes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 final int flags;
56 final int hashCode;
Amith Yamasani4ea60692012-08-28 14:34:53 -070057 final int userId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59 private static final int ODD_PRIME_NUMBER = 37;
60
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070061 Key(int _t, String _p, ActivityRecord _a, String _w,
Amith Yamasani4ea60692012-08-28 14:34:53 -070062 int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 type = _t;
64 packageName = _p;
65 activity = _a;
66 who = _w;
67 requestCode = _r;
Dianne Hackborn621e17d2010-11-22 15:59:56 -080068 requestIntent = _i != null ? _i[_i.length-1] : null;
69 requestResolvedType = _it != null ? _it[_it.length-1] : null;
70 allIntents = _i;
71 allResolvedTypes = _it;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 flags = _f;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -070073 options = _o;
Amith Yamasani4ea60692012-08-28 14:34:53 -070074 userId = _userId;
75
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 int hash = 23;
77 hash = (ODD_PRIME_NUMBER*hash) + _f;
78 hash = (ODD_PRIME_NUMBER*hash) + _r;
Amith Yamasani4ea60692012-08-28 14:34:53 -070079 hash = (ODD_PRIME_NUMBER*hash) + _userId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 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 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -080086 if (requestIntent != null) {
87 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -080089 if (requestResolvedType != null) {
90 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 }
92 hash = (ODD_PRIME_NUMBER*hash) + _p.hashCode();
93 hash = (ODD_PRIME_NUMBER*hash) + _t;
94 hashCode = hash;
Joe Onorato8a9b2202010-02-26 18:56:32 -080095 //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 // + Integer.toHexString(hashCode));
97 }
98
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 }
Amith Yamasani4ea60692012-08-28 14:34:53 -0700108 if (userId != other.userId){
109 return false;
110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 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
156 public int hashCode() {
157 return hashCode;
158 }
159
160 public String toString() {
161 return "Key{" + typeName() + " pkg=" + packageName
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800162 + " intent="
Dianne Hackborn90c52de2011-09-23 12:57:44 -0700163 + (requestIntent != null
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800164 ? requestIntent.toShortString(false, true, false, false) : "<null>")
Amith Yamasani4ea60692012-08-28 14:34:53 -0700165 + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 }
167
168 String typeName() {
169 switch (type) {
Dianne Hackborna4972e92012-03-14 10:38:05 -0700170 case ActivityManager.INTENT_SENDER_ACTIVITY:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 return "startActivity";
Dianne Hackborna4972e92012-03-14 10:38:05 -0700172 case ActivityManager.INTENT_SENDER_BROADCAST:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 return "broadcastIntent";
Dianne Hackborna4972e92012-03-14 10:38:05 -0700174 case ActivityManager.INTENT_SENDER_SERVICE:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 return "startService";
Dianne Hackborna4972e92012-03-14 10:38:05 -0700176 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 return "activityResult";
178 }
179 return Integer.toString(type);
180 }
181 }
182
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
190 public int send(int code, Intent intent, String resolvedType,
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700191 IIntentReceiver finishedReceiver, String requiredPermission) {
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700192 return sendInner(code, intent, resolvedType, finishedReceiver,
Dianne Hackborna4972e92012-03-14 10:38:05 -0700193 requiredPermission, null, null, 0, 0, 0, null);
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700194 }
195
196 int sendInner(int code, Intent intent, String resolvedType,
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700197 IIntentReceiver finishedReceiver, String requiredPermission,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700198 IBinder resultTo, String resultWho, int requestCode,
Dianne Hackborna4972e92012-03-14 10:38:05 -0700199 int flagsMask, int flagsValues, Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 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 }
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700217 flagsMask &= ~Intent.IMMUTABLE_FLAGS;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700218 flagsValues &= flagsMask;
219 finalIntent.setFlags((finalIntent.getFlags()&~flagsMask) | flagsValues);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220
221 final long origId = Binder.clearCallingIdentity();
222
223 boolean sendFinish = finishedReceiver != null;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700224 int userId = key.userId;
225 if (userId == UserHandle.USER_CURRENT) {
226 userId = owner.getCurrentUserIdLocked();
227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 switch (key.type) {
Dianne Hackborna4972e92012-03-14 10:38:05 -0700229 case ActivityManager.INTENT_SENDER_ACTIVITY:
Dianne Hackborn7a2195c2012-03-19 17:38:00 -0700230 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 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 try {
Dianne Hackborn621e17d2010-11-22 15:59:56 -0800238 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;
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800249 owner.startActivitiesInPackage(uid, key.packageName, allIntents,
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700250 allResolvedTypes, resultTo, options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -0800251 } else {
Dianne Hackbornf265ea92013-01-31 15:00:51 -0800252 owner.startActivityInPackage(uid, key.packageName, finalIntent,
253 resolvedType, resultTo, resultWho, requestCode, 0,
254 options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -0800255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800257 Slog.w(ActivityManagerService.TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 "Unable to send startActivity intent", e);
259 }
260 break;
Dianne Hackborna4972e92012-03-14 10:38:05 -0700261 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700262 key.activity.stack.sendActivityResultLocked(-1, key.activity,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 key.who, key.requestCode, code, finalIntent);
264 break;
Dianne Hackborna4972e92012-03-14 10:38:05 -0700265 case ActivityManager.INTENT_SENDER_BROADCAST:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 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,
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700271 finishedReceiver, code, null, null,
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700272 requiredPermission, (finishedReceiver != null), false, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 sendFinish = false;
274 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800275 Slog.w(ActivityManagerService.TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 "Unable to send startActivity intent", e);
277 }
278 break;
Dianne Hackborna4972e92012-03-14 10:38:05 -0700279 case ActivityManager.INTENT_SENDER_SERVICE:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 try {
281 owner.startServiceInPackage(uid,
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700282 finalIntent, resolvedType, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800284 Slog.w(ActivityManagerService.TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 "Unable to send startService intent", e);
286 }
287 break;
288 }
289
290 if (sendFinish) {
291 try {
292 finishedReceiver.performReceive(new Intent(finalIntent), 0,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700293 null, null, false, false, key.userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 } catch (RemoteException e) {
295 }
296 }
297
298 Binder.restoreCallingIdentity(origId);
299
300 return 0;
301 }
302 }
Dianne Hackborna4972e92012-03-14 10:38:05 -0700303 return ActivityManager.START_CANCELED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 }
305
306 protected void finalize() throws Throwable {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800307 try {
308 if (!canceled) {
309 owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
310 ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800312 } finally {
313 super.finalize();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 }
315 }
316
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800317 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700328 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 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800340 if (key.requestIntent != null) {
341 pw.print(prefix); pw.print("requestIntent=");
Dianne Hackborn21c241e2012-03-08 13:57:23 -0800342 pw.println(key.requestIntent.toShortString(false, true, true, true));
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800343 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700344 if (sent || canceled) {
345 pw.print(prefix); pw.print("sent="); pw.print(sent);
346 pw.print(" canceled="); pw.println(canceled);
347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 }
349
350 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700351 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();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 }
364}