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.app.IActivityContainer; 21 import android.content.IIntentSender; 22 import android.content.IIntentReceiver; 23 import android.app.PendingIntent; 24 import android.content.Intent; 25 import android.os.Binder; 26 import android.os.Bundle; 27 import android.os.IBinder; 28 import android.os.RemoteException; 29 import android.os.UserHandle; 30 import android.util.Slog; 31 32 import java.io.PrintWriter; 33 import java.lang.ref.WeakReference; 34 35 final 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 int sent = owner.broadcastIntentInPackage(key.packageName, uid, 273 finalIntent, resolvedType, 274 finishedReceiver, code, null, null, 275 requiredPermission, (finishedReceiver != null), false, userId); 276 if (sent == ActivityManager.BROADCAST_SUCCESS) { 277 sendFinish = false; 278 } 279 } catch (RuntimeException e) { 280 Slog.w(ActivityManagerService.TAG, 281 "Unable to send startActivity intent", e); 282 } 283 break; 284 case ActivityManager.INTENT_SENDER_SERVICE: 285 try { 286 owner.startServiceInPackage(uid, 287 finalIntent, resolvedType, userId); 288 } catch (RuntimeException e) { 289 Slog.w(ActivityManagerService.TAG, 290 "Unable to send startService intent", e); 291 } 292 break; 293 } 294 295 if (sendFinish) { 296 try { 297 finishedReceiver.performReceive(new Intent(finalIntent), 0, 298 null, null, false, false, key.userId); 299 } catch (RemoteException e) { 300 } 301 } 302 303 Binder.restoreCallingIdentity(origId); 304 305 return 0; 306 } 307 } 308 return ActivityManager.START_CANCELED; 309 } 310 311 @Override 312 protected void finalize() throws Throwable { 313 try { 314 if (!canceled) { 315 owner.mHandler.sendMessage(owner.mHandler.obtainMessage( 316 ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this)); 317 } 318 } finally { 319 super.finalize(); 320 } 321 } 322 323 public void completeFinalize() { 324 synchronized(owner) { 325 WeakReference<PendingIntentRecord> current = 326 owner.mIntentSenderRecords.get(key); 327 if (current == ref) { 328 owner.mIntentSenderRecords.remove(key); 329 } 330 } 331 } 332 333 void dump(PrintWriter pw, String prefix) { 334 pw.print(prefix); pw.print("uid="); pw.print(uid); 335 pw.print(" packageName="); pw.print(key.packageName); 336 pw.print(" type="); pw.print(key.typeName()); 337 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags)); 338 if (key.activity != null || key.who != null) { 339 pw.print(prefix); pw.print("activity="); pw.print(key.activity); 340 pw.print(" who="); pw.println(key.who); 341 } 342 if (key.requestCode != 0 || key.requestResolvedType != null) { 343 pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode); 344 pw.print(" requestResolvedType="); pw.println(key.requestResolvedType); 345 } 346 if (key.requestIntent != null) { 347 pw.print(prefix); pw.print("requestIntent="); 348 pw.println(key.requestIntent.toShortString(false, true, true, true)); 349 } 350 if (sent || canceled) { 351 pw.print(prefix); pw.print("sent="); pw.print(sent); 352 pw.print(" canceled="); pw.println(canceled); 353 } 354 } 355 356 public String toString() { 357 if (stringName != null) { 358 return stringName; 359 } 360 StringBuilder sb = new StringBuilder(128); 361 sb.append("PendingIntentRecord{"); 362 sb.append(Integer.toHexString(System.identityHashCode(this))); 363 sb.append(' '); 364 sb.append(key.packageName); 365 sb.append(' '); 366 sb.append(key.typeName()); 367 sb.append('}'); 368 return stringName = sb.toString(); 369 } 370 } 371