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