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