blob: 13a767e5dbac5b0a8c23718fe5aec1f4493a8353 [file] [log] [blame]
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001/*
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
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import android.app.ActivityManagerNative;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070020import 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;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070030import android.os.UserHandle;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070031import 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 *
Dianne Hackborn7f205432009-07-28 00:13:47 -070057 * <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()}.
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070060 */
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 }
Dianne Hackborn20e80982012-08-31 19:00:44 -0700117 public void performReceive(Intent intent, int resultCode, String data,
118 Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700119 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 {
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700158 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 {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700190 try {
191 String resolvedType = intent != null ?
192 intent.resolveTypeIfNeeded(context.getContentResolver())
193 : null;
194 int res = mTarget.send(code, intent, resolvedType,
195 onFinished != null
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700196 ? new FinishedDispatcher(this, onFinished, handler)
197 : null,
Dianne Hackborna750a632015-06-16 17:18:23 -0700198 requiredPermission, null);
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700199 if (res < 0) {
200 throw new SendIntentException();
201 }
202 } catch (RemoteException e) {
203 throw new SendIntentException();
204 }
205 }
206
207 /**
Dianne Hackborn8832c182012-09-17 17:20:24 -0700208 * @deprecated Renamed to {@link #getCreatorPackage()}.
209 */
210 @Deprecated
211 public String getTargetPackage() {
212 try {
213 return ActivityManagerNative.getDefault()
214 .getPackageForIntentSender(mTarget);
215 } catch (RemoteException e) {
216 // Should never happen.
217 return null;
218 }
219 }
220
221 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700222 * Return the package name of the application that created this
223 * IntentSender, that is the identity under which you will actually be
224 * sending the Intent. The returned string is supplied by the system, so
225 * that an application can not spoof its package.
226 *
227 * @return The package name of the PendingIntent, or null if there is
228 * none associated with it.
229 */
Dianne Hackborn8832c182012-09-17 17:20:24 -0700230 public String getCreatorPackage() {
Dianne Hackborn860755f2010-06-03 18:47:52 -0700231 try {
232 return ActivityManagerNative.getDefault()
233 .getPackageForIntentSender(mTarget);
234 } catch (RemoteException e) {
235 // Should never happen.
236 return null;
237 }
238 }
239
240 /**
Dianne Hackbornc7501272012-08-14 18:05:05 -0700241 * Return the uid of the application that created this
242 * PendingIntent, that is the identity under which you will actually be
243 * sending the Intent. The returned integer is supplied by the system, so
244 * that an application can not spoof its uid.
245 *
246 * @return The uid of the PendingIntent, or -1 if there is
247 * none associated with it.
248 */
Dianne Hackborn8832c182012-09-17 17:20:24 -0700249 public int getCreatorUid() {
Dianne Hackbornc7501272012-08-14 18:05:05 -0700250 try {
251 return ActivityManagerNative.getDefault()
252 .getUidForIntentSender(mTarget);
253 } catch (RemoteException e) {
254 // Should never happen.
255 return -1;
256 }
257 }
258
259 /**
260 * Return the user handle of the application that created this
261 * PendingIntent, that is the user under which you will actually be
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700262 * sending the Intent. The returned UserHandle is supplied by the system, so
Dianne Hackbornc7501272012-08-14 18:05:05 -0700263 * that an application can not spoof its user. See
264 * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
265 * more explanation of user handles.
266 *
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700267 * @return The user handle of the PendingIntent, or null if there is
Dianne Hackbornc7501272012-08-14 18:05:05 -0700268 * none associated with it.
269 */
Dianne Hackborn8832c182012-09-17 17:20:24 -0700270 public UserHandle getCreatorUserHandle() {
Dianne Hackbornc7501272012-08-14 18:05:05 -0700271 try {
272 int uid = ActivityManagerNative.getDefault()
273 .getUidForIntentSender(mTarget);
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700274 return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
Dianne Hackbornc7501272012-08-14 18:05:05 -0700275 } catch (RemoteException e) {
276 // Should never happen.
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700277 return null;
Dianne Hackbornc7501272012-08-14 18:05:05 -0700278 }
279 }
280
281 /**
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700282 * Comparison operator on two IntentSender objects, such that true
283 * is returned then they both represent the same operation from the
284 * same package.
285 */
286 @Override
287 public boolean equals(Object otherObj) {
288 if (otherObj instanceof IntentSender) {
289 return mTarget.asBinder().equals(((IntentSender)otherObj)
290 .mTarget.asBinder());
291 }
292 return false;
293 }
294
295 @Override
296 public int hashCode() {
297 return mTarget.asBinder().hashCode();
298 }
299
300 @Override
301 public String toString() {
302 StringBuilder sb = new StringBuilder(128);
303 sb.append("IntentSender{");
304 sb.append(Integer.toHexString(System.identityHashCode(this)));
305 sb.append(": ");
306 sb.append(mTarget != null ? mTarget.asBinder() : null);
307 sb.append('}');
308 return sb.toString();
309 }
310
311 public int describeContents() {
312 return 0;
313 }
314
315 public void writeToParcel(Parcel out, int flags) {
316 out.writeStrongBinder(mTarget.asBinder());
317 }
318
319 public static final Parcelable.Creator<IntentSender> CREATOR
320 = new Parcelable.Creator<IntentSender>() {
321 public IntentSender createFromParcel(Parcel in) {
322 IBinder target = in.readStrongBinder();
323 return target != null ? new IntentSender(target) : null;
324 }
325
326 public IntentSender[] newArray(int size) {
327 return new IntentSender[size];
328 }
329 };
330
331 /**
332 * Convenience function for writing either a IntentSender or null pointer to
333 * a Parcel. You must use this with {@link #readIntentSenderOrNullFromParcel}
334 * for later reading it.
335 *
336 * @param sender The IntentSender to write, or null.
337 * @param out Where to write the IntentSender.
338 */
339 public static void writeIntentSenderOrNullToParcel(IntentSender sender,
340 Parcel out) {
341 out.writeStrongBinder(sender != null ? sender.mTarget.asBinder()
342 : null);
343 }
344
345 /**
346 * Convenience function for reading either a Messenger or null pointer from
347 * a Parcel. You must have previously written the Messenger with
348 * {@link #writeIntentSenderOrNullToParcel}.
349 *
350 * @param in The Parcel containing the written Messenger.
351 *
352 * @return Returns the Messenger read from the Parcel, or null if null had
353 * been written.
354 */
355 public static IntentSender readIntentSenderOrNullFromParcel(Parcel in) {
356 IBinder b = in.readStrongBinder();
357 return b != null ? new IntentSender(b) : null;
358 }
359
Dianne Hackborn7f205432009-07-28 00:13:47 -0700360 /** @hide */
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700361 public IIntentSender getTarget() {
362 return mTarget;
363 }
364
365 /** @hide */
Dianne Hackborn7f205432009-07-28 00:13:47 -0700366 public IntentSender(IIntentSender target) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700367 mTarget = target;
368 }
369
Dianne Hackborn7f205432009-07-28 00:13:47 -0700370 /** @hide */
371 public IntentSender(IBinder target) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700372 mTarget = IIntentSender.Stub.asInterface(target);
373 }
374}