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