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 android.app.ActivityManager; 20 import android.content.IIntentSender; 21 import android.content.IIntentReceiver; 22 import android.app.PendingIntent; 23 import android.content.Intent; 24 import android.os.Binder; 25 import android.os.Bundle; 26 import android.os.IBinder; 27 import android.os.RemoteException; 28 import android.os.UserHandle; 29 import android.util.Slog; 30 31 import java.io.PrintWriter; 32 import java.lang.ref.WeakReference; 33 34 class 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 Key(int _t, String _p, ActivityRecord _a, String _w, int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId)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 equals(Object otherObj)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 hashCode()156 public int hashCode() { 157 return hashCode; 158 } 159 toString()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 typeName()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 PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u)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 send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission)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 sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options)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 int userId = key.userId; 225 if (userId == UserHandle.USER_CURRENT) { 226 userId = owner.getCurrentUserIdLocked(); 227 } 228 switch (key.type) { 229 case ActivityManager.INTENT_SENDER_ACTIVITY: 230 if (options == null) { 231 options = key.options; 232 } else if (key.options != null) { 233 Bundle opts = new Bundle(key.options); 234 opts.putAll(options); 235 options = opts; 236 } 237 try { 238 if (key.allIntents != null && key.allIntents.length > 1) { 239 Intent[] allIntents = new Intent[key.allIntents.length]; 240 String[] allResolvedTypes = new String[key.allIntents.length]; 241 System.arraycopy(key.allIntents, 0, allIntents, 0, 242 key.allIntents.length); 243 if (key.allResolvedTypes != null) { 244 System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0, 245 key.allResolvedTypes.length); 246 } 247 allIntents[allIntents.length-1] = finalIntent; 248 allResolvedTypes[allResolvedTypes.length-1] = resolvedType; 249 owner.startActivitiesInPackage(uid, key.packageName, allIntents, 250 allResolvedTypes, resultTo, options, userId); 251 } else { 252 owner.startActivityInPackage(uid, key.packageName, finalIntent, 253 resolvedType, resultTo, resultWho, requestCode, 0, 254 options, userId); 255 } 256 } catch (RuntimeException e) { 257 Slog.w(ActivityManagerService.TAG, 258 "Unable to send startActivity intent", e); 259 } 260 break; 261 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT: 262 key.activity.stack.sendActivityResultLocked(-1, key.activity, 263 key.who, key.requestCode, code, finalIntent); 264 break; 265 case ActivityManager.INTENT_SENDER_BROADCAST: 266 try { 267 // If a completion callback has been requested, require 268 // that the broadcast be delivered synchronously 269 owner.broadcastIntentInPackage(key.packageName, uid, 270 finalIntent, resolvedType, 271 finishedReceiver, code, null, null, 272 requiredPermission, (finishedReceiver != null), false, userId); 273 sendFinish = false; 274 } catch (RuntimeException e) { 275 Slog.w(ActivityManagerService.TAG, 276 "Unable to send startActivity intent", e); 277 } 278 break; 279 case ActivityManager.INTENT_SENDER_SERVICE: 280 try { 281 owner.startServiceInPackage(uid, 282 finalIntent, resolvedType, userId); 283 } catch (RuntimeException e) { 284 Slog.w(ActivityManagerService.TAG, 285 "Unable to send startService intent", e); 286 } 287 break; 288 } 289 290 if (sendFinish) { 291 try { 292 finishedReceiver.performReceive(new Intent(finalIntent), 0, 293 null, null, false, false, key.userId); 294 } catch (RemoteException e) { 295 } 296 } 297 298 Binder.restoreCallingIdentity(origId); 299 300 return 0; 301 } 302 } 303 return ActivityManager.START_CANCELED; 304 } 305 finalize()306 protected void finalize() throws Throwable { 307 try { 308 if (!canceled) { 309 owner.mHandler.sendMessage(owner.mHandler.obtainMessage( 310 ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this)); 311 } 312 } finally { 313 super.finalize(); 314 } 315 } 316 completeFinalize()317 public void completeFinalize() { 318 synchronized(owner) { 319 WeakReference<PendingIntentRecord> current = 320 owner.mIntentSenderRecords.get(key); 321 if (current == ref) { 322 owner.mIntentSenderRecords.remove(key); 323 } 324 } 325 } 326 dump(PrintWriter pw, String prefix)327 void dump(PrintWriter pw, String prefix) { 328 pw.print(prefix); pw.print("uid="); pw.print(uid); 329 pw.print(" packageName="); pw.print(key.packageName); 330 pw.print(" type="); pw.print(key.typeName()); 331 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags)); 332 if (key.activity != null || key.who != null) { 333 pw.print(prefix); pw.print("activity="); pw.print(key.activity); 334 pw.print(" who="); pw.println(key.who); 335 } 336 if (key.requestCode != 0 || key.requestResolvedType != null) { 337 pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode); 338 pw.print(" requestResolvedType="); pw.println(key.requestResolvedType); 339 } 340 if (key.requestIntent != null) { 341 pw.print(prefix); pw.print("requestIntent="); 342 pw.println(key.requestIntent.toShortString(false, true, true, true)); 343 } 344 if (sent || canceled) { 345 pw.print(prefix); pw.print("sent="); pw.print(sent); 346 pw.print(" canceled="); pw.println(canceled); 347 } 348 } 349 toString()350 public String toString() { 351 if (stringName != null) { 352 return stringName; 353 } 354 StringBuilder sb = new StringBuilder(128); 355 sb.append("PendingIntentRecord{"); 356 sb.append(Integer.toHexString(System.identityHashCode(this))); 357 sb.append(' '); 358 sb.append(key.packageName); 359 sb.append(' '); 360 sb.append(key.typeName()); 361 sb.append('}'); 362 return stringName = sb.toString(); 363 } 364 } 365