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 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, allIntents, 250 allResolvedTypes, resultTo, options, userId); 251 } else { 252 owner.startActivityInPackage(uid, finalIntent, resolvedType, 253 resultTo, resultWho, requestCode, 0, options, userId); 254 } 255 } catch (RuntimeException e) { 256 Slog.w(ActivityManagerService.TAG, 257 "Unable to send startActivity intent", e); 258 } 259 break; 260 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT: 261 key.activity.stack.sendActivityResultLocked(-1, key.activity, 262 key.who, key.requestCode, code, finalIntent); 263 break; 264 case ActivityManager.INTENT_SENDER_BROADCAST: 265 try { 266 // If a completion callback has been requested, require 267 // that the broadcast be delivered synchronously 268 owner.broadcastIntentInPackage(key.packageName, uid, 269 finalIntent, resolvedType, 270 finishedReceiver, code, null, null, 271 requiredPermission, (finishedReceiver != null), false, userId); 272 sendFinish = false; 273 } catch (RuntimeException e) { 274 Slog.w(ActivityManagerService.TAG, 275 "Unable to send startActivity intent", e); 276 } 277 break; 278 case ActivityManager.INTENT_SENDER_SERVICE: 279 try { 280 owner.startServiceInPackage(uid, 281 finalIntent, resolvedType, userId); 282 } catch (RuntimeException e) { 283 Slog.w(ActivityManagerService.TAG, 284 "Unable to send startService intent", e); 285 } 286 break; 287 } 288 289 if (sendFinish) { 290 try { 291 finishedReceiver.performReceive(new Intent(finalIntent), 0, 292 null, null, false, false, key.userId); 293 } catch (RemoteException e) { 294 } 295 } 296 297 Binder.restoreCallingIdentity(origId); 298 299 return 0; 300 } 301 } 302 return ActivityManager.START_CANCELED; 303 } 304 305 protected void finalize() throws Throwable { 306 try { 307 if (!canceled) { 308 owner.mHandler.sendMessage(owner.mHandler.obtainMessage( 309 ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this)); 310 } 311 } finally { 312 super.finalize(); 313 } 314 } 315 316 public void completeFinalize() { 317 synchronized(owner) { 318 WeakReference<PendingIntentRecord> current = 319 owner.mIntentSenderRecords.get(key); 320 if (current == ref) { 321 owner.mIntentSenderRecords.remove(key); 322 } 323 } 324 } 325 326 void dump(PrintWriter pw, String prefix) { 327 pw.print(prefix); pw.print("uid="); pw.print(uid); 328 pw.print(" packageName="); pw.print(key.packageName); 329 pw.print(" type="); pw.print(key.typeName()); 330 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags)); 331 if (key.activity != null || key.who != null) { 332 pw.print(prefix); pw.print("activity="); pw.print(key.activity); 333 pw.print(" who="); pw.println(key.who); 334 } 335 if (key.requestCode != 0 || key.requestResolvedType != null) { 336 pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode); 337 pw.print(" requestResolvedType="); pw.println(key.requestResolvedType); 338 } 339 if (key.requestIntent != null) { 340 pw.print(prefix); pw.print("requestIntent="); 341 pw.println(key.requestIntent.toShortString(false, true, true, true)); 342 } 343 if (sent || canceled) { 344 pw.print(prefix); pw.print("sent="); pw.print(sent); 345 pw.print(" canceled="); pw.println(canceled); 346 } 347 } 348 349 public String toString() { 350 if (stringName != null) { 351 return stringName; 352 } 353 StringBuilder sb = new StringBuilder(128); 354 sb.append("PendingIntentRecord{"); 355 sb.append(Integer.toHexString(System.identityHashCode(this))); 356 sb.append(' '); 357 sb.append(key.packageName); 358 sb.append(' '); 359 sb.append(key.typeName()); 360 sb.append('}'); 361 return stringName = sb.toString(); 362 } 363} 364