2 * Copyright (C) 2006 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.am;
19 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
20 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
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.RemoteCallbackList;
32 import android.os.RemoteException;
33 import android.os.TransactionTooLargeException;
34 import android.os.UserHandle;
35 import android.util.ArrayMap;
36 import android.util.Slog;
37 import android.util.TimeUtils;
39 import com.android.internal.os.IResultReceiver;
40 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
42 import java.io.PrintWriter;
43 import java.lang.ref.WeakReference;
44 import java.util.Objects;
46 final class PendingIntentRecord extends IIntentSender.Stub {
47 private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM;
49 final ActivityManagerService owner;
52 final WeakReference<PendingIntentRecord> ref;
54 boolean canceled = false;
55 private ArrayMap<IBinder, Long> whitelistDuration;
56 private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
62 final static class Key {
64 final String packageName;
65 final ActivityRecord activity;
67 final int requestCode;
68 final Intent requestIntent;
69 final String requestResolvedType;
72 String[] allResolvedTypes;
77 private static final int ODD_PRIME_NUMBER = 37;
79 Key(int _t, String _p, ActivityRecord _a, String _w,
80 int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) {
86 requestIntent = _i != null ? _i[_i.length-1] : null;
87 requestResolvedType = _it != null ? _it[_it.length-1] : null;
89 allResolvedTypes = _it;
95 hash = (ODD_PRIME_NUMBER*hash) + _f;
96 hash = (ODD_PRIME_NUMBER*hash) + _r;
97 hash = (ODD_PRIME_NUMBER*hash) + _userId;
99 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
102 hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode();
104 if (requestIntent != null) {
105 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode();
107 if (requestResolvedType != null) {
108 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode();
110 hash = (ODD_PRIME_NUMBER*hash) + (_p != null ? _p.hashCode() : 0);
111 hash = (ODD_PRIME_NUMBER*hash) + _t;
113 //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x"
114 // + Integer.toHexString(hashCode));
117 public boolean equals(Object otherObj) {
118 if (otherObj == null) {
122 Key other = (Key)otherObj;
123 if (type != other.type) {
126 if (userId != other.userId){
129 if (!Objects.equals(packageName, other.packageName)) {
132 if (activity != other.activity) {
135 if (!Objects.equals(who, other.who)) {
138 if (requestCode != other.requestCode) {
141 if (requestIntent != other.requestIntent) {
142 if (requestIntent != null) {
143 if (!requestIntent.filterEquals(other.requestIntent)) {
146 } else if (other.requestIntent != null) {
150 if (!Objects.equals(requestResolvedType, other.requestResolvedType)) {
153 if (flags != other.flags) {
157 } catch (ClassCastException e) {
162 public int hashCode() {
166 public String toString() {
167 return "Key{" + typeName() + " pkg=" + packageName
169 + (requestIntent != null
170 ? requestIntent.toShortString(false, true, false, false) : "<null>")
171 + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
176 case ActivityManager.INTENT_SENDER_ACTIVITY:
177 return "startActivity";
178 case ActivityManager.INTENT_SENDER_BROADCAST:
179 return "broadcastIntent";
180 case ActivityManager.INTENT_SENDER_SERVICE:
181 return "startService";
182 case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
183 return "startForegroundService";
184 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
185 return "activityResult";
187 return Integer.toString(type);
191 PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) {
195 ref = new WeakReference<PendingIntentRecord>(this);
198 void setWhitelistDurationLocked(IBinder whitelistToken, long duration) {
200 if (whitelistDuration == null) {
201 whitelistDuration = new ArrayMap<>();
203 whitelistDuration.put(whitelistToken, duration);
204 } else if (whitelistDuration != null) {
205 whitelistDuration.remove(whitelistToken);
206 if (whitelistDuration.size() <= 0) {
207 whitelistDuration = null;
211 this.stringName = null;
214 public void registerCancelListenerLocked(IResultReceiver receiver) {
215 if (mCancelCallbacks == null) {
216 mCancelCallbacks = new RemoteCallbackList<>();
218 mCancelCallbacks.register(receiver);
221 public void unregisterCancelListenerLocked(IResultReceiver receiver) {
222 mCancelCallbacks.unregister(receiver);
223 if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) {
224 mCancelCallbacks = null;
228 public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() {
229 RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks;
230 mCancelCallbacks = null;
234 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
235 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
236 sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
237 requiredPermission, null, null, 0, 0, 0, options, null);
240 public int sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken,
241 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
242 return sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
243 requiredPermission, null, null, 0, 0, 0, options, null);
246 int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
247 IIntentReceiver finishedReceiver,
248 String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
249 int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
250 if (intent != null) intent.setDefusable(true);
251 if (options != null) options.setDefusable(true);
253 synchronized (owner) {
254 final ActivityContainer activityContainer = (ActivityContainer)container;
255 if (activityContainer != null && activityContainer.mParentActivity != null &&
256 activityContainer.mParentActivity.state
257 != ActivityStack.ActivityState.RESUMED) {
258 // Cannot start a child activity if the parent is not resumed.
259 return ActivityManager.START_CANCELED;
263 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
264 owner.cancelIntentSenderLocked(this, true);
267 Intent finalIntent = key.requestIntent != null
268 ? new Intent(key.requestIntent) : new Intent();
270 final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
272 if (intent != null) {
273 int changes = finalIntent.fillIn(intent, key.flags);
274 if ((changes & Intent.FILL_IN_DATA) == 0) {
275 resolvedType = key.requestResolvedType;
278 resolvedType = key.requestResolvedType;
280 flagsMask &= ~Intent.IMMUTABLE_FLAGS;
281 flagsValues &= flagsMask;
282 finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
284 resolvedType = key.requestResolvedType;
287 final int callingUid = Binder.getCallingUid();
288 final int callingPid = Binder.getCallingPid();
290 final long origId = Binder.clearCallingIdentity();
292 if (whitelistDuration != null) {
293 Long duration = whitelistDuration.get(whitelistToken);
294 if (duration != null) {
295 int procState = owner.getUidState(callingUid);
296 if (!ActivityManager.isProcStateBackground(procState)) {
297 StringBuilder tag = new StringBuilder(64);
298 tag.append("pendingintent:");
299 UserHandle.formatUid(tag, callingUid);
301 if (finalIntent.getAction() != null) {
302 tag.append(finalIntent.getAction());
303 } else if (finalIntent.getComponent() != null) {
304 finalIntent.getComponent().appendShortString(tag);
305 } else if (finalIntent.getData() != null) {
306 tag.append(finalIntent.getData());
308 owner.tempWhitelistForPendingIntentLocked(callingPid,
309 callingUid, uid, duration, tag.toString());
311 Slog.w(TAG, "Not doing whitelist " + this + ": caller state="
317 boolean sendFinish = finishedReceiver != null;
318 int userId = key.userId;
319 if (userId == UserHandle.USER_CURRENT) {
320 userId = owner.mUserController.getCurrentOrTargetUserIdLocked();
324 case ActivityManager.INTENT_SENDER_ACTIVITY:
325 if (options == null) {
326 options = key.options;
327 } else if (key.options != null) {
328 Bundle opts = new Bundle(key.options);
329 opts.putAll(options);
333 if (key.allIntents != null && key.allIntents.length > 1) {
334 Intent[] allIntents = new Intent[key.allIntents.length];
335 String[] allResolvedTypes = new String[key.allIntents.length];
336 System.arraycopy(key.allIntents, 0, allIntents, 0,
337 key.allIntents.length);
338 if (key.allResolvedTypes != null) {
339 System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
340 key.allResolvedTypes.length);
342 allIntents[allIntents.length-1] = finalIntent;
343 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
344 owner.startActivitiesInPackage(uid, key.packageName, allIntents,
345 allResolvedTypes, resultTo, options, userId);
347 owner.startActivityInPackage(uid, key.packageName, finalIntent,
348 resolvedType, resultTo, resultWho, requestCode, 0,
349 options, userId, container, null, "PendingIntentRecord");
351 } catch (RuntimeException e) {
352 Slog.w(TAG, "Unable to send startActivity intent", e);
355 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
356 final ActivityStack stack = key.activity.getStack();
358 stack.sendActivityResultLocked(-1, key.activity, key.who,
359 key.requestCode, code, finalIntent);
362 case ActivityManager.INTENT_SENDER_BROADCAST:
364 // If a completion callback has been requested, require
365 // that the broadcast be delivered synchronously
366 int sent = owner.broadcastIntentInPackage(key.packageName, uid,
367 finalIntent, resolvedType, finishedReceiver, code, null, null,
368 requiredPermission, options, (finishedReceiver != null),
370 if (sent == ActivityManager.BROADCAST_SUCCESS) {
373 } catch (RuntimeException e) {
374 Slog.w(TAG, "Unable to send startActivity intent", e);
377 case ActivityManager.INTENT_SENDER_SERVICE:
378 case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
380 owner.startServiceInPackage(uid, finalIntent, resolvedType,
381 key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
382 key.packageName, userId);
383 } catch (RuntimeException e) {
384 Slog.w(TAG, "Unable to send startService intent", e);
385 } catch (TransactionTooLargeException e) {
386 res = ActivityManager.START_CANCELED;
391 if (sendFinish && res != ActivityManager.START_CANCELED) {
393 finishedReceiver.performReceive(new Intent(finalIntent), 0,
394 null, null, false, false, key.userId);
395 } catch (RemoteException e) {
399 Binder.restoreCallingIdentity(origId);
404 return ActivityManager.START_CANCELED;
408 protected void finalize() throws Throwable {
411 owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
412 ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
419 public void completeFinalize() {
420 synchronized(owner) {
421 WeakReference<PendingIntentRecord> current =
422 owner.mIntentSenderRecords.get(key);
423 if (current == ref) {
424 owner.mIntentSenderRecords.remove(key);
429 void dump(PrintWriter pw, String prefix) {
430 pw.print(prefix); pw.print("uid="); pw.print(uid);
431 pw.print(" packageName="); pw.print(key.packageName);
432 pw.print(" type="); pw.print(key.typeName());
433 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
434 if (key.activity != null || key.who != null) {
435 pw.print(prefix); pw.print("activity="); pw.print(key.activity);
436 pw.print(" who="); pw.println(key.who);
438 if (key.requestCode != 0 || key.requestResolvedType != null) {
439 pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
440 pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
442 if (key.requestIntent != null) {
443 pw.print(prefix); pw.print("requestIntent=");
444 pw.println(key.requestIntent.toShortString(false, true, true, true));
446 if (sent || canceled) {
447 pw.print(prefix); pw.print("sent="); pw.print(sent);
448 pw.print(" canceled="); pw.println(canceled);
450 if (whitelistDuration != null) {
452 pw.print("whitelistDuration=");
453 for (int i = 0; i < whitelistDuration.size(); i++) {
457 pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
459 TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw);
463 if (mCancelCallbacks != null) {
464 pw.print(prefix); pw.println("mCancelCallbacks:");
465 for (int i = 0; i < mCancelCallbacks.getRegisteredCallbackCount(); i++) {
466 pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": ");
467 pw.println(mCancelCallbacks.getRegisteredCallbackItem(i));
472 public String toString() {
473 if (stringName != null) {
476 StringBuilder sb = new StringBuilder(128);
477 sb.append("PendingIntentRecord{");
478 sb.append(Integer.toHexString(System.identityHashCode(this)));
480 sb.append(key.packageName);
482 sb.append(key.typeName());
483 if (whitelistDuration != null) {
484 sb.append( " (whitelist: ");
485 for (int i = 0; i < whitelistDuration.size(); i++) {
489 sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
491 TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb);
496 return stringName = sb.toString();