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