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 Key(int _t, String _p, ActivityRecord _a, String _w, int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId)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 equals(Object otherObj)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 hashCode()159 public int hashCode() { 160 return hashCode; 161 } 162 toString()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 typeName()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 PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u)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 send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission)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 sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options, IActivityContainer container)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 finalize()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 completeFinalize()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 dump(PrintWriter pw, String prefix)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 toString()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