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.RemoteException; 32 import android.os.TransactionTooLargeException; 33 import android.os.UserHandle; 34 import android.util.Slog; 35 36 import com.android.server.am.ActivityStackSupervisor.ActivityContainer; 37 38 import java.io.PrintWriter; 39 import java.lang.ref.WeakReference; 40 41 final class PendingIntentRecord extends IIntentSender.Stub { 42 private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM; 43 44 final ActivityManagerService owner; 45 final Key key; 46 final int uid; 47 final WeakReference<PendingIntentRecord> ref; 48 boolean sent = false; 49 boolean canceled = false; 50 51 String stringName; 52 String lastTagPrefix; 53 String lastTag; 54 55 final static class Key { 56 final int type; 57 final String packageName; 58 final ActivityRecord activity; 59 final String who; 60 final int requestCode; 61 final Intent requestIntent; 62 final String requestResolvedType; 63 final Bundle options; 64 Intent[] allIntents; 65 String[] allResolvedTypes; 66 final int flags; 67 final int hashCode; 68 final int userId; 69 70 private static final int ODD_PRIME_NUMBER = 37; 71 Key(int _t, String _p, ActivityRecord _a, String _w, int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId)72 Key(int _t, String _p, ActivityRecord _a, String _w, 73 int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) { 74 type = _t; 75 packageName = _p; 76 activity = _a; 77 who = _w; 78 requestCode = _r; 79 requestIntent = _i != null ? _i[_i.length-1] : null; 80 requestResolvedType = _it != null ? _it[_it.length-1] : null; 81 allIntents = _i; 82 allResolvedTypes = _it; 83 flags = _f; 84 options = _o; 85 userId = _userId; 86 87 int hash = 23; 88 hash = (ODD_PRIME_NUMBER*hash) + _f; 89 hash = (ODD_PRIME_NUMBER*hash) + _r; 90 hash = (ODD_PRIME_NUMBER*hash) + _userId; 91 if (_w != null) { 92 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode(); 93 } 94 if (_a != null) { 95 hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode(); 96 } 97 if (requestIntent != null) { 98 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode(); 99 } 100 if (requestResolvedType != null) { 101 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode(); 102 } 103 hash = (ODD_PRIME_NUMBER*hash) + _p.hashCode(); 104 hash = (ODD_PRIME_NUMBER*hash) + _t; 105 hashCode = hash; 106 //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x" 107 // + Integer.toHexString(hashCode)); 108 } 109 equals(Object otherObj)110 public boolean equals(Object otherObj) { 111 if (otherObj == null) { 112 return false; 113 } 114 try { 115 Key other = (Key)otherObj; 116 if (type != other.type) { 117 return false; 118 } 119 if (userId != other.userId){ 120 return false; 121 } 122 if (!packageName.equals(other.packageName)) { 123 return false; 124 } 125 if (activity != other.activity) { 126 return false; 127 } 128 if (who != other.who) { 129 if (who != null) { 130 if (!who.equals(other.who)) { 131 return false; 132 } 133 } else if (other.who != null) { 134 return false; 135 } 136 } 137 if (requestCode != other.requestCode) { 138 return false; 139 } 140 if (requestIntent != other.requestIntent) { 141 if (requestIntent != null) { 142 if (!requestIntent.filterEquals(other.requestIntent)) { 143 return false; 144 } 145 } else if (other.requestIntent != null) { 146 return false; 147 } 148 } 149 if (requestResolvedType != other.requestResolvedType) { 150 if (requestResolvedType != null) { 151 if (!requestResolvedType.equals(other.requestResolvedType)) { 152 return false; 153 } 154 } else if (other.requestResolvedType != null) { 155 return false; 156 } 157 } 158 if (flags != other.flags) { 159 return false; 160 } 161 return true; 162 } catch (ClassCastException e) { 163 } 164 return false; 165 } 166 hashCode()167 public int hashCode() { 168 return hashCode; 169 } 170 toString()171 public String toString() { 172 return "Key{" + typeName() + " pkg=" + packageName 173 + " intent=" 174 + (requestIntent != null 175 ? requestIntent.toShortString(false, true, false, false) : "<null>") 176 + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}"; 177 } 178 typeName()179 String typeName() { 180 switch (type) { 181 case ActivityManager.INTENT_SENDER_ACTIVITY: 182 return "startActivity"; 183 case ActivityManager.INTENT_SENDER_BROADCAST: 184 return "broadcastIntent"; 185 case ActivityManager.INTENT_SENDER_SERVICE: 186 return "startService"; 187 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT: 188 return "activityResult"; 189 } 190 return Integer.toString(type); 191 } 192 } 193 PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u)194 PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) { 195 owner = _owner; 196 key = _k; 197 uid = _u; 198 ref = new WeakReference<PendingIntentRecord>(this); 199 } 200 send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)201 public int send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, 202 String requiredPermission, Bundle options) throws TransactionTooLargeException { 203 return sendInner(code, intent, resolvedType, finishedReceiver, 204 requiredPermission, null, null, 0, 0, 0, options, null); 205 } 206 sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options, IActivityContainer container)207 int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, 208 String requiredPermission, IBinder resultTo, String resultWho, int requestCode, 209 int flagsMask, int flagsValues, Bundle options, IActivityContainer container) 210 throws TransactionTooLargeException { 211 synchronized(owner) { 212 final ActivityContainer activityContainer = (ActivityContainer)container; 213 if (activityContainer != null && activityContainer.mParentActivity != null && 214 activityContainer.mParentActivity.state 215 != ActivityStack.ActivityState.RESUMED) { 216 // Cannot start a child activity if the parent is not resumed. 217 return ActivityManager.START_CANCELED; 218 } 219 if (!canceled) { 220 sent = true; 221 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) { 222 owner.cancelIntentSenderLocked(this, true); 223 canceled = true; 224 } 225 226 Intent finalIntent = key.requestIntent != null 227 ? new Intent(key.requestIntent) : new Intent(); 228 229 final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0; 230 if (!immutable) { 231 if (intent != null) { 232 int changes = finalIntent.fillIn(intent, key.flags); 233 if ((changes & Intent.FILL_IN_DATA) == 0) { 234 resolvedType = key.requestResolvedType; 235 } 236 } else { 237 resolvedType = key.requestResolvedType; 238 } 239 flagsMask &= ~Intent.IMMUTABLE_FLAGS; 240 flagsValues &= flagsMask; 241 finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues); 242 } else { 243 resolvedType = key.requestResolvedType; 244 } 245 246 final long origId = Binder.clearCallingIdentity(); 247 248 boolean sendFinish = finishedReceiver != null; 249 int userId = key.userId; 250 if (userId == UserHandle.USER_CURRENT) { 251 userId = owner.getCurrentUserIdLocked(); 252 } 253 switch (key.type) { 254 case ActivityManager.INTENT_SENDER_ACTIVITY: 255 if (options == null) { 256 options = key.options; 257 } else if (key.options != null) { 258 Bundle opts = new Bundle(key.options); 259 opts.putAll(options); 260 options = opts; 261 } 262 try { 263 if (key.allIntents != null && key.allIntents.length > 1) { 264 Intent[] allIntents = new Intent[key.allIntents.length]; 265 String[] allResolvedTypes = new String[key.allIntents.length]; 266 System.arraycopy(key.allIntents, 0, allIntents, 0, 267 key.allIntents.length); 268 if (key.allResolvedTypes != null) { 269 System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0, 270 key.allResolvedTypes.length); 271 } 272 allIntents[allIntents.length-1] = finalIntent; 273 allResolvedTypes[allResolvedTypes.length-1] = resolvedType; 274 owner.startActivitiesInPackage(uid, key.packageName, allIntents, 275 allResolvedTypes, resultTo, options, userId); 276 } else { 277 owner.startActivityInPackage(uid, key.packageName, finalIntent, 278 resolvedType, resultTo, resultWho, requestCode, 0, 279 options, userId, container, null); 280 } 281 } catch (RuntimeException e) { 282 Slog.w(TAG, "Unable to send startActivity intent", e); 283 } 284 break; 285 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT: 286 if (key.activity.task.stack != null) { 287 key.activity.task.stack.sendActivityResultLocked(-1, key.activity, 288 key.who, key.requestCode, code, finalIntent); 289 } 290 break; 291 case ActivityManager.INTENT_SENDER_BROADCAST: 292 try { 293 // If a completion callback has been requested, require 294 // that the broadcast be delivered synchronously 295 int sent = owner.broadcastIntentInPackage(key.packageName, uid, 296 finalIntent, resolvedType, finishedReceiver, code, null, null, 297 requiredPermission, options, (finishedReceiver != null), 298 false, userId); 299 if (sent == ActivityManager.BROADCAST_SUCCESS) { 300 sendFinish = false; 301 } 302 } catch (RuntimeException e) { 303 Slog.w(TAG, "Unable to send startActivity intent", e); 304 } 305 break; 306 case ActivityManager.INTENT_SENDER_SERVICE: 307 try { 308 owner.startServiceInPackage(uid, finalIntent, 309 resolvedType, key.packageName, userId); 310 } catch (RuntimeException e) { 311 Slog.w(TAG, "Unable to send startService intent", e); 312 } 313 break; 314 } 315 316 if (sendFinish) { 317 try { 318 finishedReceiver.performReceive(new Intent(finalIntent), 0, 319 null, null, false, false, key.userId); 320 } catch (RemoteException e) { 321 } 322 } 323 324 Binder.restoreCallingIdentity(origId); 325 326 return 0; 327 } 328 } 329 return ActivityManager.START_CANCELED; 330 } 331 332 @Override finalize()333 protected void finalize() throws Throwable { 334 try { 335 if (!canceled) { 336 owner.mHandler.sendMessage(owner.mHandler.obtainMessage( 337 ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this)); 338 } 339 } finally { 340 super.finalize(); 341 } 342 } 343 completeFinalize()344 public void completeFinalize() { 345 synchronized(owner) { 346 WeakReference<PendingIntentRecord> current = 347 owner.mIntentSenderRecords.get(key); 348 if (current == ref) { 349 owner.mIntentSenderRecords.remove(key); 350 } 351 } 352 } 353 dump(PrintWriter pw, String prefix)354 void dump(PrintWriter pw, String prefix) { 355 pw.print(prefix); pw.print("uid="); pw.print(uid); 356 pw.print(" packageName="); pw.print(key.packageName); 357 pw.print(" type="); pw.print(key.typeName()); 358 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags)); 359 if (key.activity != null || key.who != null) { 360 pw.print(prefix); pw.print("activity="); pw.print(key.activity); 361 pw.print(" who="); pw.println(key.who); 362 } 363 if (key.requestCode != 0 || key.requestResolvedType != null) { 364 pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode); 365 pw.print(" requestResolvedType="); pw.println(key.requestResolvedType); 366 } 367 if (key.requestIntent != null) { 368 pw.print(prefix); pw.print("requestIntent="); 369 pw.println(key.requestIntent.toShortString(false, true, true, true)); 370 } 371 if (sent || canceled) { 372 pw.print(prefix); pw.print("sent="); pw.print(sent); 373 pw.print(" canceled="); pw.println(canceled); 374 } 375 } 376 toString()377 public String toString() { 378 if (stringName != null) { 379 return stringName; 380 } 381 StringBuilder sb = new StringBuilder(128); 382 sb.append("PendingIntentRecord{"); 383 sb.append(Integer.toHexString(System.identityHashCode(this))); 384 sb.append(' '); 385 sb.append(key.packageName); 386 sb.append(' '); 387 sb.append(key.typeName()); 388 sb.append('}'); 389 return stringName = sb.toString(); 390 } 391 } 392