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