blob: 079241aeadc9af364a0726020e9f057032ad07c6 [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 }
117 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700118 String data, Bundle extras, boolean serialized, boolean sticky) {
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,
198 requiredPermission);
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 Hackborn860755f2010-06-03 18:47:52 -0700208 * 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 /**
Dianne Hackbornc7501272012-08-14 18:05:05 -0700227 * 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
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700248 * sending the Intent. The returned UserHandle is supplied by the system, so
Dianne Hackbornc7501272012-08-14 18:05:05 -0700249 * 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 *
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700253 * @return The user handle of the PendingIntent, or null if there is
Dianne Hackbornc7501272012-08-14 18:05:05 -0700254 * none associated with it.
255 */
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700256 public UserHandle getTargetUserHandle() {
Dianne Hackbornc7501272012-08-14 18:05:05 -0700257 try {
258 int uid = ActivityManagerNative.getDefault()
259 .getUidForIntentSender(mTarget);
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700260 return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
Dianne Hackbornc7501272012-08-14 18:05:05 -0700261 } catch (RemoteException e) {
262 // Should never happen.
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700263 return null;
Dianne Hackbornc7501272012-08-14 18:05:05 -0700264 }
265 }
266
267 /**
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700268 * 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
Dianne Hackborn7f205432009-07-28 00:13:47 -0700346 /** @hide */
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700347 public IIntentSender getTarget() {
348 return mTarget;
349 }
350
351 /** @hide */
Dianne Hackborn7f205432009-07-28 00:13:47 -0700352 public IntentSender(IIntentSender target) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700353 mTarget = target;
354 }
355
Dianne Hackborn7f205432009-07-28 00:13:47 -0700356 /** @hide */
357 public IntentSender(IBinder target) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700358 mTarget = IIntentSender.Stub.asInterface(target);
359 }
360}