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