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 final 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 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 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.task.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 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 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 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 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