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.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; 38 39 import com.android.internal.os.IResultReceiver; 40 import com.android.server.am.ActivityStackSupervisor.ActivityContainer; 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 Bundle 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, Bundle _o, int _userId)79 Key(int _t, String _p, ActivityRecord _a, String _w, 80 int _r, Intent[] _i, String[] _it, int _f, Bundle _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 mCancelCallbacks.unregister(receiver); 223 if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) { 224 mCancelCallbacks = null; 225 } 226 } 227 detachCancelListenersLocked()228 public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() { 229 RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks; 230 mCancelCallbacks = null; 231 return listeners; 232 } 233 send(int code, Intent intent, String resolvedType, IBinder whitelistToken, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)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); 238 } 239 sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)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); 244 } 245 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, IActivityContainer container)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); 252 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; 260 } 261 if (!canceled) { 262 sent = true; 263 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) { 264 owner.cancelIntentSenderLocked(this, true); 265 } 266 267 Intent finalIntent = key.requestIntent != null 268 ? new Intent(key.requestIntent) : new Intent(); 269 270 final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0; 271 if (!immutable) { 272 if (intent != null) { 273 int changes = finalIntent.fillIn(intent, key.flags); 274 if ((changes & Intent.FILL_IN_DATA) == 0) { 275 resolvedType = key.requestResolvedType; 276 } 277 } else { 278 resolvedType = key.requestResolvedType; 279 } 280 flagsMask &= ~Intent.IMMUTABLE_FLAGS; 281 flagsValues &= flagsMask; 282 finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues); 283 } else { 284 resolvedType = key.requestResolvedType; 285 } 286 287 final int callingUid = Binder.getCallingUid(); 288 final int callingPid = Binder.getCallingPid(); 289 290 final long origId = Binder.clearCallingIdentity(); 291 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); 300 tag.append(":"); 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()); 307 } 308 owner.tempWhitelistForPendingIntentLocked(callingPid, 309 callingUid, uid, duration, tag.toString()); 310 } else { 311 Slog.w(TAG, "Not doing whitelist " + this + ": caller state=" 312 + procState); 313 } 314 } 315 } 316 317 boolean sendFinish = finishedReceiver != null; 318 int userId = key.userId; 319 if (userId == UserHandle.USER_CURRENT) { 320 userId = owner.mUserController.getCurrentOrTargetUserIdLocked(); 321 } 322 int res = 0; 323 switch (key.type) { 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); 330 options = opts; 331 } 332 try { 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); 341 } 342 allIntents[allIntents.length-1] = finalIntent; 343 allResolvedTypes[allResolvedTypes.length-1] = resolvedType; 344 owner.startActivitiesInPackage(uid, key.packageName, allIntents, 345 allResolvedTypes, resultTo, options, userId); 346 } else { 347 owner.startActivityInPackage(uid, key.packageName, finalIntent, 348 resolvedType, resultTo, resultWho, requestCode, 0, 349 options, userId, container, null, "PendingIntentRecord"); 350 } 351 } catch (RuntimeException e) { 352 Slog.w(TAG, "Unable to send startActivity intent", e); 353 } 354 break; 355 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT: 356 final ActivityStack stack = key.activity.getStack(); 357 if (stack != null) { 358 stack.sendActivityResultLocked(-1, key.activity, key.who, 359 key.requestCode, code, finalIntent); 360 } 361 break; 362 case ActivityManager.INTENT_SENDER_BROADCAST: 363 try { 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), 369 false, userId); 370 if (sent == ActivityManager.BROADCAST_SUCCESS) { 371 sendFinish = false; 372 } 373 } catch (RuntimeException e) { 374 Slog.w(TAG, "Unable to send startActivity intent", e); 375 } 376 break; 377 case ActivityManager.INTENT_SENDER_SERVICE: 378 case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE: 379 try { 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; 387 } 388 break; 389 } 390 391 if (sendFinish && res != ActivityManager.START_CANCELED) { 392 try { 393 finishedReceiver.performReceive(new Intent(finalIntent), 0, 394 null, null, false, false, key.userId); 395 } catch (RemoteException e) { 396 } 397 } 398 399 Binder.restoreCallingIdentity(origId); 400 401 return res; 402 } 403 } 404 return ActivityManager.START_CANCELED; 405 } 406 407 @Override finalize()408 protected void finalize() throws Throwable { 409 try { 410 if (!canceled) { 411 owner.mHandler.sendMessage(owner.mHandler.obtainMessage( 412 ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this)); 413 } 414 } finally { 415 super.finalize(); 416 } 417 } 418 completeFinalize()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); 425 } 426 } 427 } 428 dump(PrintWriter pw, String prefix)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); 437 } 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); 441 } 442 if (key.requestIntent != null) { 443 pw.print(prefix); pw.print("requestIntent="); 444 pw.println(key.requestIntent.toShortString(false, true, true, true)); 445 } 446 if (sent || canceled) { 447 pw.print(prefix); pw.print("sent="); pw.print(sent); 448 pw.print(" canceled="); pw.println(canceled); 449 } 450 if (whitelistDuration != null) { 451 pw.print(prefix); 452 pw.print("whitelistDuration="); 453 for (int i = 0; i < whitelistDuration.size(); i++) { 454 if (i != 0) { 455 pw.print(", "); 456 } 457 pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i)))); 458 pw.print(":"); 459 TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw); 460 } 461 pw.println(); 462 } 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)); 468 } 469 } 470 } 471 toString()472 public String toString() { 473 if (stringName != null) { 474 return stringName; 475 } 476 StringBuilder sb = new StringBuilder(128); 477 sb.append("PendingIntentRecord{"); 478 sb.append(Integer.toHexString(System.identityHashCode(this))); 479 sb.append(' '); 480 sb.append(key.packageName); 481 sb.append(' '); 482 sb.append(key.typeName()); 483 if (whitelistDuration != null) { 484 sb.append( " (whitelist: "); 485 for (int i = 0; i < whitelistDuration.size(); i++) { 486 if (i != 0) { 487 sb.append(","); 488 } 489 sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i)))); 490 sb.append(":"); 491 TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb); 492 } 493 sb.append(")"); 494 } 495 sb.append('}'); 496 return stringName = sb.toString(); 497 } 498 } 499