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