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