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 android.content; 18 19 import android.app.ActivityManager; 20 import android.os.Bundle; 21 import android.os.RemoteException; 22 import android.os.Handler; 23 import android.os.IBinder; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.os.UserHandle; 27 import android.util.AndroidException; 28 29 30 /** 31 * A description of an Intent and target action to perform with it. 32 * The returned object can be 33 * handed to other applications so that they can perform the action you 34 * described on your behalf at a later time. 35 * 36 * <p>By giving a IntentSender to another application, 37 * you are granting it the right to perform the operation you have specified 38 * as if the other application was yourself (with the same permissions and 39 * identity). As such, you should be careful about how you build the IntentSender: 40 * often, for example, the base Intent you supply will have the component 41 * name explicitly set to one of your own components, to ensure it is ultimately 42 * sent there and nowhere else. 43 * 44 * <p>A IntentSender itself is simply a reference to a token maintained by 45 * the system describing the original data used to retrieve it. This means 46 * that, even if its owning application's process is killed, the 47 * IntentSender itself will remain usable from other processes that 48 * have been given it. If the creating application later re-retrieves the 49 * same kind of IntentSender (same operation, same Intent action, data, 50 * categories, and components, and same flags), it will receive a IntentSender 51 * representing the same token if that is still valid. 52 * 53 * <p>Instances of this class can not be made directly, but rather must be 54 * created from an existing {@link android.app.PendingIntent} with 55 * {@link android.app.PendingIntent#getIntentSender() PendingIntent.getIntentSender()}. 56 */ 57 public class IntentSender implements Parcelable { 58 private final IIntentSender mTarget; 59 IBinder mWhitelistToken; 60 61 /** 62 * Exception thrown when trying to send through a PendingIntent that 63 * has been canceled or is otherwise no longer able to execute the request. 64 */ 65 public static class SendIntentException extends AndroidException { 66 public SendIntentException() { 67 } 68 69 public SendIntentException(String name) { 70 super(name); 71 } 72 73 public SendIntentException(Exception cause) { 74 super(cause); 75 } 76 } 77 78 /** 79 * Callback interface for discovering when a send operation has 80 * completed. Primarily for use with a IntentSender that is 81 * performing a broadcast, this provides the same information as 82 * calling {@link Context#sendOrderedBroadcast(Intent, String, 83 * android.content.BroadcastReceiver, Handler, int, String, Bundle) 84 * Context.sendBroadcast()} with a final BroadcastReceiver. 85 */ 86 public interface OnFinished { 87 /** 88 * Called when a send operation as completed. 89 * 90 * @param IntentSender The IntentSender this operation was sent through. 91 * @param intent The original Intent that was sent. 92 * @param resultCode The final result code determined by the send. 93 * @param resultData The final data collected by a broadcast. 94 * @param resultExtras The final extras collected by a broadcast. 95 */ 96 void onSendFinished(IntentSender IntentSender, Intent intent, 97 int resultCode, String resultData, Bundle resultExtras); 98 } 99 100 private static class FinishedDispatcher extends IIntentReceiver.Stub 101 implements Runnable { 102 private final IntentSender mIntentSender; 103 private final OnFinished mWho; 104 private final Handler mHandler; 105 private Intent mIntent; 106 private int mResultCode; 107 private String mResultData; 108 private Bundle mResultExtras; 109 FinishedDispatcher(IntentSender pi, OnFinished who, Handler handler) { 110 mIntentSender = pi; 111 mWho = who; 112 mHandler = handler; 113 } 114 public void performReceive(Intent intent, int resultCode, String data, 115 Bundle extras, boolean serialized, boolean sticky, int sendingUser) { 116 mIntent = intent; 117 mResultCode = resultCode; 118 mResultData = data; 119 mResultExtras = extras; 120 if (mHandler == null) { 121 run(); 122 } else { 123 mHandler.post(this); 124 } 125 } 126 public void run() { 127 mWho.onSendFinished(mIntentSender, mIntent, mResultCode, 128 mResultData, mResultExtras); 129 } 130 } 131 132 /** 133 * Perform the operation associated with this IntentSender, allowing the 134 * caller to specify information about the Intent to use and be notified 135 * when the send has completed. 136 * 137 * @param context The Context of the caller. This may be null if 138 * <var>intent</var> is also null. 139 * @param code Result code to supply back to the IntentSender's target. 140 * @param intent Additional Intent data. See {@link Intent#fillIn 141 * Intent.fillIn()} for information on how this is applied to the 142 * original Intent. Use null to not modify the original Intent. 143 * @param onFinished The object to call back on when the send has 144 * completed, or null for no callback. 145 * @param handler Handler identifying the thread on which the callback 146 * should happen. If null, the callback will happen from the thread 147 * pool of the process. 148 * 149 * 150 * @throws SendIntentException Throws CanceledIntentException if the IntentSender 151 * is no longer allowing more intents to be sent through it. 152 */ 153 public void sendIntent(Context context, int code, Intent intent, 154 OnFinished onFinished, Handler handler) throws SendIntentException { 155 sendIntent(context, code, intent, onFinished, handler, null); 156 } 157 158 /** 159 * Perform the operation associated with this IntentSender, allowing the 160 * caller to specify information about the Intent to use and be notified 161 * when the send has completed. 162 * 163 * @param context The Context of the caller. This may be null if 164 * <var>intent</var> is also null. 165 * @param code Result code to supply back to the IntentSender's target. 166 * @param intent Additional Intent data. See {@link Intent#fillIn 167 * Intent.fillIn()} for information on how this is applied to the 168 * original Intent. Use null to not modify the original Intent. 169 * @param onFinished The object to call back on when the send has 170 * completed, or null for no callback. 171 * @param handler Handler identifying the thread on which the callback 172 * should happen. If null, the callback will happen from the thread 173 * pool of the process. 174 * @param requiredPermission Name of permission that a recipient of the PendingIntent 175 * is required to hold. This is only valid for broadcast intents, and 176 * corresponds to the permission argument in 177 * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}. 178 * If null, no permission is required. 179 * 180 * 181 * @throws SendIntentException Throws CanceledIntentException if the IntentSender 182 * is no longer allowing more intents to be sent through it. 183 */ 184 public void sendIntent(Context context, int code, Intent intent, 185 OnFinished onFinished, Handler handler, String requiredPermission) 186 throws SendIntentException { 187 try { 188 String resolvedType = intent != null ? 189 intent.resolveTypeIfNeeded(context.getContentResolver()) 190 : null; 191 int res = ActivityManager.getService().sendIntentSender(mTarget, mWhitelistToken, 192 code, intent, resolvedType, 193 onFinished != null 194 ? new FinishedDispatcher(this, onFinished, handler) 195 : null, 196 requiredPermission, null); 197 if (res < 0) { 198 throw new SendIntentException(); 199 } 200 } catch (RemoteException e) { 201 throw new SendIntentException(); 202 } 203 } 204 205 /** 206 * @deprecated Renamed to {@link #getCreatorPackage()}. 207 */ 208 @Deprecated 209 public String getTargetPackage() { 210 try { 211 return ActivityManager.getService() 212 .getPackageForIntentSender(mTarget); 213 } catch (RemoteException e) { 214 // Should never happen. 215 return null; 216 } 217 } 218 219 /** 220 * Return the package name of the application that created this 221 * IntentSender, that is the identity under which you will actually be 222 * sending the Intent. The returned string is supplied by the system, so 223 * that an application can not spoof its package. 224 * 225 * @return The package name of the PendingIntent, or null if there is 226 * none associated with it. 227 */ 228 public String getCreatorPackage() { 229 try { 230 return ActivityManager.getService() 231 .getPackageForIntentSender(mTarget); 232 } catch (RemoteException e) { 233 // Should never happen. 234 return null; 235 } 236 } 237 238 /** 239 * Return the uid of the application that created this 240 * PendingIntent, that is the identity under which you will actually be 241 * sending the Intent. The returned integer is supplied by the system, so 242 * that an application can not spoof its uid. 243 * 244 * @return The uid of the PendingIntent, or -1 if there is 245 * none associated with it. 246 */ 247 public int getCreatorUid() { 248 try { 249 return ActivityManager.getService() 250 .getUidForIntentSender(mTarget); 251 } catch (RemoteException e) { 252 // Should never happen. 253 return -1; 254 } 255 } 256 257 /** 258 * Return the user handle of the application that created this 259 * PendingIntent, that is the user under which you will actually be 260 * sending the Intent. The returned UserHandle is supplied by the system, so 261 * that an application can not spoof its user. See 262 * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for 263 * more explanation of user handles. 264 * 265 * @return The user handle of the PendingIntent, or null if there is 266 * none associated with it. 267 */ 268 public UserHandle getCreatorUserHandle() { 269 try { 270 int uid = ActivityManager.getService() 271 .getUidForIntentSender(mTarget); 272 return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null; 273 } catch (RemoteException e) { 274 // Should never happen. 275 return null; 276 } 277 } 278 279 /** 280 * Comparison operator on two IntentSender objects, such that true 281 * is returned then they both represent the same operation from the 282 * same package. 283 */ 284 @Override 285 public boolean equals(Object otherObj) { 286 if (otherObj instanceof IntentSender) { 287 return mTarget.asBinder().equals(((IntentSender)otherObj) 288 .mTarget.asBinder()); 289 } 290 return false; 291 } 292 293 @Override 294 public int hashCode() { 295 return mTarget.asBinder().hashCode(); 296 } 297 298 @Override 299 public String toString() { 300 StringBuilder sb = new StringBuilder(128); 301 sb.append("IntentSender{"); 302 sb.append(Integer.toHexString(System.identityHashCode(this))); 303 sb.append(": "); 304 sb.append(mTarget != null ? mTarget.asBinder() : null); 305 sb.append('}'); 306 return sb.toString(); 307 } 308 309 public int describeContents() { 310 return 0; 311 } 312 313 public void writeToParcel(Parcel out, int flags) { 314 out.writeStrongBinder(mTarget.asBinder()); 315 } 316 317 public static final Parcelable.Creator<IntentSender> CREATOR 318 = new Parcelable.Creator<IntentSender>() { 319 public IntentSender createFromParcel(Parcel in) { 320 IBinder target = in.readStrongBinder(); 321 return target != null ? new IntentSender(target) : null; 322 } 323 324 public IntentSender[] newArray(int size) { 325 return new IntentSender[size]; 326 } 327 }; 328 329 /** 330 * Convenience function for writing either a IntentSender or null pointer to 331 * a Parcel. You must use this with {@link #readIntentSenderOrNullFromParcel} 332 * for later reading it. 333 * 334 * @param sender The IntentSender to write, or null. 335 * @param out Where to write the IntentSender. 336 */ 337 public static void writeIntentSenderOrNullToParcel(IntentSender sender, 338 Parcel out) { 339 out.writeStrongBinder(sender != null ? sender.mTarget.asBinder() 340 : null); 341 } 342 343 /** 344 * Convenience function for reading either a Messenger or null pointer from 345 * a Parcel. You must have previously written the Messenger with 346 * {@link #writeIntentSenderOrNullToParcel}. 347 * 348 * @param in The Parcel containing the written Messenger. 349 * 350 * @return Returns the Messenger read from the Parcel, or null if null had 351 * been written. 352 */ 353 public static IntentSender readIntentSenderOrNullFromParcel(Parcel in) { 354 IBinder b = in.readStrongBinder(); 355 return b != null ? new IntentSender(b) : null; 356 } 357 358 /** @hide */ 359 public IIntentSender getTarget() { 360 return mTarget; 361 } 362 363 /** @hide */ 364 public IBinder getWhitelistToken() { 365 return mWhitelistToken; 366 } 367 368 /** @hide */ 369 public IntentSender(IIntentSender target) { 370 mTarget = target; 371 } 372 373 /** @hide */ 374 public IntentSender(IIntentSender target, IBinder whitelistToken) { 375 mTarget = target; 376 mWhitelistToken = whitelistToken; 377 } 378 379 /** @hide */ 380 public IntentSender(IBinder target) { 381 mTarget = IIntentSender.Stub.asInterface(target); 382 } 383 } 384