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 android.app.ActivityManager.START_SUCCESS; 20 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 21 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 22 23 import android.app.ActivityManager; 24 import android.app.ActivityOptions; 25 import android.content.IIntentSender; 26 import android.content.IIntentReceiver; 27 import android.app.PendingIntent; 28 import android.content.Intent; 29 import android.os.Binder; 30 import android.os.Bundle; 31 import android.os.IBinder; 32 import android.os.RemoteCallbackList; 33 import android.os.RemoteException; 34 import android.os.TransactionTooLargeException; 35 import android.os.UserHandle; 36 import android.util.ArrayMap; 37 import android.util.Slog; 38 import android.util.TimeUtils; 39 40 import com.android.internal.os.IResultReceiver; 41 42 import java.io.PrintWriter; 43 import java.lang.ref.WeakReference; 44 import java.util.Objects; 45 46 final class PendingIntentRecord extends IIntentSender.Stub { 47 private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM; 48 49 final ActivityManagerService owner; 50 final Key key; 51 final int uid; 52 final WeakReference<PendingIntentRecord> ref; 53 boolean sent = false; 54 boolean canceled = false; 55 private ArrayMap<IBinder, Long> whitelistDuration; 56 private RemoteCallbackList<IResultReceiver> mCancelCallbacks; 57 58 String stringName; 59 String lastTagPrefix; 60 String lastTag; 61 62 final static class Key { 63 final int type; 64 final String packageName; 65 final ActivityRecord activity; 66 final String who; 67 final int requestCode; 68 final Intent requestIntent; 69 final String requestResolvedType; 70 final SafeActivityOptions options; 71 Intent[] allIntents; 72 String[] allResolvedTypes; 73 final int flags; 74 final int hashCode; 75 final int userId; 76 77 private static final int ODD_PRIME_NUMBER = 37; 78 Key(int _t, String _p, ActivityRecord _a, String _w, int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId)79 Key(int _t, String _p, ActivityRecord _a, String _w, 80 int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId) { 81 type = _t; 82 packageName = _p; 83 activity = _a; 84 who = _w; 85 requestCode = _r; 86 requestIntent = _i != null ? _i[_i.length-1] : null; 87 requestResolvedType = _it != null ? _it[_it.length-1] : null; 88 allIntents = _i; 89 allResolvedTypes = _it; 90 flags = _f; 91 options = _o; 92 userId = _userId; 93 94 int hash = 23; 95 hash = (ODD_PRIME_NUMBER*hash) + _f; 96 hash = (ODD_PRIME_NUMBER*hash) + _r; 97 hash = (ODD_PRIME_NUMBER*hash) + _userId; 98 if (_w != null) { 99 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode(); 100 } 101 if (_a != null) { 102 hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode(); 103 } 104 if (requestIntent != null) { 105 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode(); 106 } 107 if (requestResolvedType != null) { 108 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode(); 109 } 110 hash = (ODD_PRIME_NUMBER*hash) + (_p != null ? _p.hashCode() : 0); 111 hash = (ODD_PRIME_NUMBER*hash) + _t; 112 hashCode = hash; 113 //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x" 114 // + Integer.toHexString(hashCode)); 115 } 116 equals(Object otherObj)117 public boolean equals(Object otherObj) { 118 if (otherObj == null) { 119 return false; 120 } 121 try { 122 Key other = (Key)otherObj; 123 if (type != other.type) { 124 return false; 125 } 126 if (userId != other.userId){ 127 return false; 128 } 129 if (!Objects.equals(packageName, other.packageName)) { 130 return false; 131 } 132 if (activity != other.activity) { 133 return false; 134 } 135 if (!Objects.equals(who, other.who)) { 136 return false; 137 } 138 if (requestCode != other.requestCode) { 139 return false; 140 } 141 if (requestIntent != other.requestIntent) { 142 if (requestIntent != null) { 143 if (!requestIntent.filterEquals(other.requestIntent)) { 144 return false; 145 } 146 } else if (other.requestIntent != null) { 147 return false; 148 } 149 } 150 if (!Objects.equals(requestResolvedType, other.requestResolvedType)) { 151 return false; 152 } 153 if (flags != other.flags) { 154 return false; 155 } 156 return true; 157 } catch (ClassCastException e) { 158 } 159 return false; 160 } 161 hashCode()162 public int hashCode() { 163 return hashCode; 164 } 165 toString()166 public String toString() { 167 return "Key{" + typeName() + " pkg=" + packageName 168 + " intent=" 169 + (requestIntent != null 170 ? requestIntent.toShortString(false, true, false, false) : "<null>") 171 + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}"; 172 } 173 typeName()174 String typeName() { 175 switch (type) { 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"; 186 } 187 return Integer.toString(type); 188 } 189 } 190 PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u)191 PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) { 192 owner = _owner; 193 key = _k; 194 uid = _u; 195 ref = new WeakReference<PendingIntentRecord>(this); 196 } 197 setWhitelistDurationLocked(IBinder whitelistToken, long duration)198 void setWhitelistDurationLocked(IBinder whitelistToken, long duration) { 199 if (duration > 0) { 200 if (whitelistDuration == null) { 201 whitelistDuration = new ArrayMap<>(); 202 } 203 whitelistDuration.put(whitelistToken, duration); 204 } else if (whitelistDuration != null) { 205 whitelistDuration.remove(whitelistToken); 206 if (whitelistDuration.size() <= 0) { 207 whitelistDuration = null; 208 } 209 210 } 211 this.stringName = null; 212 } 213 registerCancelListenerLocked(IResultReceiver receiver)214 public void registerCancelListenerLocked(IResultReceiver receiver) { 215 if (mCancelCallbacks == null) { 216 mCancelCallbacks = new RemoteCallbackList<>(); 217 } 218 mCancelCallbacks.register(receiver); 219 } 220 unregisterCancelListenerLocked(IResultReceiver receiver)221 public void unregisterCancelListenerLocked(IResultReceiver receiver) { 222 if (mCancelCallbacks == null) { 223 return; // Already unregistered or detached. 224 } 225 mCancelCallbacks.unregister(receiver); 226 if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) { 227 mCancelCallbacks = null; 228 } 229 } 230 detachCancelListenersLocked()231 public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() { 232 RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks; 233 mCancelCallbacks = null; 234 return listeners; 235 } 236 send(int code, Intent intent, String resolvedType, IBinder whitelistToken, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)237 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken, 238 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { 239 sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver, 240 requiredPermission, null, null, 0, 0, 0, options); 241 } 242 sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)243 public int sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken, 244 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { 245 return sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver, 246 requiredPermission, null, null, 0, 0, 0, options); 247 } 248 sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options)249 int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken, 250 IIntentReceiver finishedReceiver, 251 String requiredPermission, IBinder resultTo, String resultWho, int requestCode, 252 int flagsMask, int flagsValues, Bundle options) { 253 if (intent != null) intent.setDefusable(true); 254 if (options != null) options.setDefusable(true); 255 256 synchronized (owner) { 257 if (!canceled) { 258 sent = true; 259 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) { 260 owner.cancelIntentSenderLocked(this, true); 261 } 262 263 Intent finalIntent = key.requestIntent != null 264 ? new Intent(key.requestIntent) : new Intent(); 265 266 final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0; 267 if (!immutable) { 268 if (intent != null) { 269 int changes = finalIntent.fillIn(intent, key.flags); 270 if ((changes & Intent.FILL_IN_DATA) == 0) { 271 resolvedType = key.requestResolvedType; 272 } 273 } else { 274 resolvedType = key.requestResolvedType; 275 } 276 flagsMask &= ~Intent.IMMUTABLE_FLAGS; 277 flagsValues &= flagsMask; 278 finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues); 279 } else { 280 resolvedType = key.requestResolvedType; 281 } 282 283 final int callingUid = Binder.getCallingUid(); 284 final int callingPid = Binder.getCallingPid(); 285 286 // Extract options before clearing calling identity 287 SafeActivityOptions mergedOptions = key.options; 288 if (mergedOptions == null) { 289 mergedOptions = SafeActivityOptions.fromBundle(options); 290 } else { 291 mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options)); 292 } 293 294 final long origId = Binder.clearCallingIdentity(); 295 296 if (whitelistDuration != null) { 297 Long duration = whitelistDuration.get(whitelistToken); 298 if (duration != null) { 299 int procState = owner.getUidState(callingUid); 300 if (!ActivityManager.isProcStateBackground(procState)) { 301 StringBuilder tag = new StringBuilder(64); 302 tag.append("pendingintent:"); 303 UserHandle.formatUid(tag, callingUid); 304 tag.append(":"); 305 if (finalIntent.getAction() != null) { 306 tag.append(finalIntent.getAction()); 307 } else if (finalIntent.getComponent() != null) { 308 finalIntent.getComponent().appendShortString(tag); 309 } else if (finalIntent.getData() != null) { 310 tag.append(finalIntent.getData()); 311 } 312 owner.tempWhitelistForPendingIntentLocked(callingPid, 313 callingUid, uid, duration, tag.toString()); 314 } else { 315 Slog.w(TAG, "Not doing whitelist " + this + ": caller state=" 316 + procState); 317 } 318 } 319 } 320 321 boolean sendFinish = finishedReceiver != null; 322 int userId = key.userId; 323 if (userId == UserHandle.USER_CURRENT) { 324 userId = owner.mUserController.getCurrentOrTargetUserId(); 325 } 326 int res = START_SUCCESS; 327 switch (key.type) { 328 case ActivityManager.INTENT_SENDER_ACTIVITY: 329 try { 330 // Note when someone has a pending intent, even from different 331 // users, then there's no need to ensure the calling user matches 332 // the target user, so validateIncomingUser is always false below. 333 334 if (key.allIntents != null && key.allIntents.length > 1) { 335 Intent[] allIntents = new Intent[key.allIntents.length]; 336 String[] allResolvedTypes = new String[key.allIntents.length]; 337 System.arraycopy(key.allIntents, 0, allIntents, 0, 338 key.allIntents.length); 339 if (key.allResolvedTypes != null) { 340 System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0, 341 key.allResolvedTypes.length); 342 } 343 allIntents[allIntents.length-1] = finalIntent; 344 allResolvedTypes[allResolvedTypes.length-1] = resolvedType; 345 346 res = owner.getActivityStartController().startActivitiesInPackage( 347 uid, callingPid, callingUid, key.packageName, allIntents, 348 allResolvedTypes, resultTo, mergedOptions, userId, 349 false /* validateIncomingUser */); 350 } else { 351 res = owner.getActivityStartController().startActivityInPackage(uid, 352 callingPid, callingUid, key.packageName, finalIntent, 353 resolvedType, resultTo, resultWho, requestCode, 0, 354 mergedOptions, userId, null, "PendingIntentRecord", 355 false /* validateIncomingUser */); 356 } 357 } catch (RuntimeException e) { 358 Slog.w(TAG, "Unable to send startActivity intent", e); 359 } 360 break; 361 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT: 362 final ActivityStack stack = key.activity.getStack(); 363 if (stack != null) { 364 stack.sendActivityResultLocked(-1, key.activity, key.who, 365 key.requestCode, code, finalIntent); 366 } 367 break; 368 case ActivityManager.INTENT_SENDER_BROADCAST: 369 try { 370 // If a completion callback has been requested, require 371 // that the broadcast be delivered synchronously 372 int sent = owner.broadcastIntentInPackage(key.packageName, uid, 373 finalIntent, resolvedType, finishedReceiver, code, null, null, 374 requiredPermission, options, (finishedReceiver != null), 375 false, userId); 376 if (sent == ActivityManager.BROADCAST_SUCCESS) { 377 sendFinish = false; 378 } 379 } catch (RuntimeException e) { 380 Slog.w(TAG, "Unable to send startActivity intent", e); 381 } 382 break; 383 case ActivityManager.INTENT_SENDER_SERVICE: 384 case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE: 385 try { 386 owner.startServiceInPackage(uid, finalIntent, resolvedType, 387 key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE, 388 key.packageName, userId); 389 } catch (RuntimeException e) { 390 Slog.w(TAG, "Unable to send startService intent", e); 391 } catch (TransactionTooLargeException e) { 392 res = ActivityManager.START_CANCELED; 393 } 394 break; 395 } 396 397 if (sendFinish && res != ActivityManager.START_CANCELED) { 398 try { 399 finishedReceiver.performReceive(new Intent(finalIntent), 0, 400 null, null, false, false, key.userId); 401 } catch (RemoteException e) { 402 } 403 } 404 405 Binder.restoreCallingIdentity(origId); 406 407 return res; 408 } 409 } 410 return ActivityManager.START_CANCELED; 411 } 412 413 @Override finalize()414 protected void finalize() throws Throwable { 415 try { 416 if (!canceled) { 417 owner.mHandler.sendMessage(owner.mHandler.obtainMessage( 418 ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this)); 419 } 420 } finally { 421 super.finalize(); 422 } 423 } 424 completeFinalize()425 public void completeFinalize() { 426 synchronized(owner) { 427 WeakReference<PendingIntentRecord> current = 428 owner.mIntentSenderRecords.get(key); 429 if (current == ref) { 430 owner.mIntentSenderRecords.remove(key); 431 } 432 } 433 } 434 dump(PrintWriter pw, String prefix)435 void dump(PrintWriter pw, String prefix) { 436 pw.print(prefix); pw.print("uid="); pw.print(uid); 437 pw.print(" packageName="); pw.print(key.packageName); 438 pw.print(" type="); pw.print(key.typeName()); 439 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags)); 440 if (key.activity != null || key.who != null) { 441 pw.print(prefix); pw.print("activity="); pw.print(key.activity); 442 pw.print(" who="); pw.println(key.who); 443 } 444 if (key.requestCode != 0 || key.requestResolvedType != null) { 445 pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode); 446 pw.print(" requestResolvedType="); pw.println(key.requestResolvedType); 447 } 448 if (key.requestIntent != null) { 449 pw.print(prefix); pw.print("requestIntent="); 450 pw.println(key.requestIntent.toShortString(false, true, true, true)); 451 } 452 if (sent || canceled) { 453 pw.print(prefix); pw.print("sent="); pw.print(sent); 454 pw.print(" canceled="); pw.println(canceled); 455 } 456 if (whitelistDuration != null) { 457 pw.print(prefix); 458 pw.print("whitelistDuration="); 459 for (int i = 0; i < whitelistDuration.size(); i++) { 460 if (i != 0) { 461 pw.print(", "); 462 } 463 pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i)))); 464 pw.print(":"); 465 TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw); 466 } 467 pw.println(); 468 } 469 if (mCancelCallbacks != null) { 470 pw.print(prefix); pw.println("mCancelCallbacks:"); 471 for (int i = 0; i < mCancelCallbacks.getRegisteredCallbackCount(); i++) { 472 pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": "); 473 pw.println(mCancelCallbacks.getRegisteredCallbackItem(i)); 474 } 475 } 476 } 477 toString()478 public String toString() { 479 if (stringName != null) { 480 return stringName; 481 } 482 StringBuilder sb = new StringBuilder(128); 483 sb.append("PendingIntentRecord{"); 484 sb.append(Integer.toHexString(System.identityHashCode(this))); 485 sb.append(' '); 486 sb.append(key.packageName); 487 sb.append(' '); 488 sb.append(key.typeName()); 489 if (whitelistDuration != null) { 490 sb.append( " (whitelist: "); 491 for (int i = 0; i < whitelistDuration.size(); i++) { 492 if (i != 0) { 493 sb.append(","); 494 } 495 sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i)))); 496 sb.append(":"); 497 TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb); 498 } 499 sb.append(")"); 500 } 501 sb.append('}'); 502 return stringName = sb.toString(); 503 } 504 } 505