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