PendingIntent.java revision 599dd7ce9adf8ca067cefb0b191a5ac20ec35a79
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.app;
18
19import android.content.Context;
20import android.content.Intent;
21import android.content.IIntentReceiver;
22import android.content.IIntentSender;
23import android.content.IntentSender;
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 * A description of an Intent and target action to perform with it.  Instances
35 * of this class are created with {@link #getActivity}, {@link #getActivities},
36 * {@link #getBroadcast}, and {@link #getService}; 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 PendingIntent 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 PendingIntent:
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 PendingIntent 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 * PendingIntent 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 PendingIntent (same operation, same Intent action, data,
54 * categories, and components, and same flags), it will receive a PendingIntent
55 * representing the same token if that is still valid, and can thus call
56 * {@link #cancel} to remove it.
57 *
58 * <p>Because of this behavior, it is important to know when two Intents
59 * are considered to be the same for purposes of retrieving a PendingIntent.
60 * A common mistake people make is to create multiple PendingIntent objects
61 * with Intents that only vary in their "extra" contents, expecting to get
62 * a different PendingIntent each time.  This does <em>not</em> happen.  The
63 * parts of the Intent that are used for matching are the same ones defined
64 * by {@link Intent#filterEquals(Intent) Intent.filterEquals}.  If you use two
65 * Intent objects that are equivalent as per
66 * {@link Intent#filterEquals(Intent) Intent.filterEquals}, then you will get
67 * the same PendingIntent for both of them.
68 *
69 * <p>There are two typical ways to deal with this.
70 *
71 * <p>If you truly need multiple distinct PendingIntent objects active at
72 * the same time (such as to use as two notifications that are both shown
73 * at the same time), then you will need to ensure there is something that
74 * is different about them to associate them with different PendingIntents.
75 * This may be any of the Intent attributes considered by
76 * {@link Intent#filterEquals(Intent) Intent.filterEquals}, or different
77 * request code integers supplied to {@link #getActivity}, {@link #getActivities},
78 * {@link #getBroadcast}, or {@link #getService}.
79 *
80 * <p>If you only need one PendingIntent active at a time for any of the
81 * Intents you will use, then you can alternatively use the flags
82 * {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either
83 * cancel or modify whatever current PendingIntent is associated with the
84 * Intent you are supplying.
85 */
86public final class PendingIntent implements Parcelable {
87    private final IIntentSender mTarget;
88
89    /**
90     * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
91     * {@link #getService}: this
92     * PendingIntent can only be used once.  If set, after
93     * {@link #send()} is called on it, it will be automatically
94     * canceled for you and any future attempt to send through it will fail.
95     */
96    public static final int FLAG_ONE_SHOT = 1<<30;
97    /**
98     * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
99     * {@link #getService}: if the described PendingIntent does not already
100     * exist, then simply return null instead of creating it.
101     */
102    public static final int FLAG_NO_CREATE = 1<<29;
103    /**
104     * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
105     * {@link #getService}: if the described PendingIntent already exists,
106     * the current one is canceled before generating a new one.  You can use
107     * this to retrieve a new PendingIntent when you are only changing the
108     * extra data in the Intent; by canceling the previous pending intent,
109     * this ensures that only entities given the new data will be able to
110     * launch it.  If this assurance is not an issue, consider
111     * {@link #FLAG_UPDATE_CURRENT}.
112     */
113    public static final int FLAG_CANCEL_CURRENT = 1<<28;
114    /**
115     * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
116     * {@link #getService}: if the described PendingIntent already exists,
117     * then keep it but its replace its extra data with what is in this new
118     * Intent.  This can be used if you are creating intents where only the
119     * extras change, and don't care that any entities that received your
120     * previous PendingIntent will be able to launch it with your new
121     * extras even if they are not explicitly given to it.
122     */
123    public static final int FLAG_UPDATE_CURRENT = 1<<27;
124
125    /**
126     * Exception thrown when trying to send through a PendingIntent that
127     * has been canceled or is otherwise no longer able to execute the request.
128     */
129    public static class CanceledException extends AndroidException {
130        public CanceledException() {
131        }
132
133        public CanceledException(String name) {
134            super(name);
135        }
136
137        public CanceledException(Exception cause) {
138            super(cause);
139        }
140    }
141
142    /**
143     * Callback interface for discovering when a send operation has
144     * completed.  Primarily for use with a PendingIntent that is
145     * performing a broadcast, this provides the same information as
146     * calling {@link Context#sendOrderedBroadcast(Intent, String,
147     * android.content.BroadcastReceiver, Handler, int, String, Bundle)
148     * Context.sendBroadcast()} with a final BroadcastReceiver.
149     */
150    public interface OnFinished {
151        /**
152         * Called when a send operation as completed.
153         *
154         * @param pendingIntent The PendingIntent this operation was sent through.
155         * @param intent The original Intent that was sent.
156         * @param resultCode The final result code determined by the send.
157         * @param resultData The final data collected by a broadcast.
158         * @param resultExtras The final extras collected by a broadcast.
159         */
160        void onSendFinished(PendingIntent pendingIntent, Intent intent,
161                int resultCode, String resultData, Bundle resultExtras);
162    }
163
164    private static class FinishedDispatcher extends IIntentReceiver.Stub
165            implements Runnable {
166        private final PendingIntent mPendingIntent;
167        private final OnFinished mWho;
168        private final Handler mHandler;
169        private Intent mIntent;
170        private int mResultCode;
171        private String mResultData;
172        private Bundle mResultExtras;
173        FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) {
174            mPendingIntent = pi;
175            mWho = who;
176            mHandler = handler;
177        }
178        public void performReceive(Intent intent, int resultCode, String data,
179                Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
180            mIntent = intent;
181            mResultCode = resultCode;
182            mResultData = data;
183            mResultExtras = extras;
184            if (mHandler == null) {
185                run();
186            } else {
187                mHandler.post(this);
188            }
189        }
190        public void run() {
191            mWho.onSendFinished(mPendingIntent, mIntent, mResultCode,
192                    mResultData, mResultExtras);
193        }
194    }
195
196    /**
197     * Retrieve a PendingIntent that will start a new activity, like calling
198     * {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
199     * Note that the activity will be started outside of the context of an
200     * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
201     * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.
202     *
203     * @param context The Context in which this PendingIntent should start
204     * the activity.
205     * @param requestCode Private request code for the sender (currently
206     * not used).
207     * @param intent Intent of the activity to be launched.
208     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
209     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
210     * or any of the flags as supported by
211     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
212     * of the intent that can be supplied when the actual send happens.
213     *
214     * @return Returns an existing or new PendingIntent matching the given
215     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
216     * supplied.
217     */
218    public static PendingIntent getActivity(Context context, int requestCode,
219            Intent intent, int flags) {
220        return getActivity(context, requestCode, intent, flags, null);
221    }
222
223    /**
224     * Retrieve a PendingIntent that will start a new activity, like calling
225     * {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
226     * Note that the activity will be started outside of the context of an
227     * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
228     * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.
229     *
230     * @param context The Context in which this PendingIntent should start
231     * the activity.
232     * @param requestCode Private request code for the sender (currently
233     * not used).
234     * @param intent Intent of the activity to be launched.
235     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
236     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
237     * or any of the flags as supported by
238     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
239     * of the intent that can be supplied when the actual send happens.
240     * @param options Additional options for how the Activity should be started.
241     * May be null if there are no options.
242     *
243     * @return Returns an existing or new PendingIntent matching the given
244     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
245     * supplied.
246     */
247    public static PendingIntent getActivity(Context context, int requestCode,
248            Intent intent, int flags, Bundle options) {
249        String packageName = context.getPackageName();
250        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
251                context.getContentResolver()) : null;
252        try {
253            intent.setAllowFds(false);
254            IIntentSender target =
255                ActivityManagerNative.getDefault().getIntentSender(
256                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
257                    null, null, requestCode, new Intent[] { intent },
258                    resolvedType != null ? new String[] { resolvedType } : null,
259                    flags, options, UserHandle.myUserId());
260            return target != null ? new PendingIntent(target) : null;
261        } catch (RemoteException e) {
262        }
263        return null;
264    }
265
266    /**
267     * @hide
268     */
269    public static PendingIntent getActivityAsUser(Context context, int requestCode,
270            Intent intent, int flags, Bundle options, UserHandle user) {
271        String packageName = context.getPackageName();
272        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
273                context.getContentResolver()) : null;
274        try {
275            intent.setAllowFds(false);
276            IIntentSender target =
277                ActivityManagerNative.getDefault().getIntentSender(
278                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
279                    null, null, requestCode, new Intent[] { intent },
280                    resolvedType != null ? new String[] { resolvedType } : null,
281                    flags, options, user.getIdentifier());
282            return target != null ? new PendingIntent(target) : null;
283        } catch (RemoteException e) {
284        }
285        return null;
286    }
287
288    /**
289     * Like {@link #getActivity(Context, int, Intent, int)}, but allows an
290     * array of Intents to be supplied.  The first Intent in the array is
291     * taken as the primary key for the PendingIntent, like the single Intent
292     * given to {@link #getActivity(Context, int, Intent, int)}.  Upon sending
293     * the resulting PendingIntent, all of the Intents are started in the same
294     * way as they would be by passing them to {@link Context#startActivities(Intent[])}.
295     *
296     * <p class="note">
297     * The <em>first</em> intent in the array will be started outside of the context of an
298     * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
299     * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.  (Activities after
300     * the first in the array are started in the context of the previous activity
301     * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.)
302     * </p>
303     *
304     * <p class="note">
305     * The <em>last</em> intent in the array represents the key for the
306     * PendingIntent.  In other words, it is the significant element for matching
307     * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)},
308     * its content will be the subject of replacement by
309     * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc.
310     * This is because it is the most specific of the supplied intents, and the
311     * UI the user actually sees when the intents are started.
312     * </p>
313     *
314     * @param context The Context in which this PendingIntent should start
315     * the activity.
316     * @param requestCode Private request code for the sender (currently
317     * not used).
318     * @param intents Array of Intents of the activities to be launched.
319     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
320     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
321     * or any of the flags as supported by
322     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
323     * of the intent that can be supplied when the actual send happens.
324     *
325     * @return Returns an existing or new PendingIntent matching the given
326     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
327     * supplied.
328     */
329    public static PendingIntent getActivities(Context context, int requestCode,
330            Intent[] intents, int flags) {
331        return getActivities(context, requestCode, intents, flags, null);
332    }
333
334    /**
335     * Like {@link #getActivity(Context, int, Intent, int)}, but allows an
336     * array of Intents to be supplied.  The first Intent in the array is
337     * taken as the primary key for the PendingIntent, like the single Intent
338     * given to {@link #getActivity(Context, int, Intent, int)}.  Upon sending
339     * the resulting PendingIntent, all of the Intents are started in the same
340     * way as they would be by passing them to {@link Context#startActivities(Intent[])}.
341     *
342     * <p class="note">
343     * The <em>first</em> intent in the array will be started outside of the context of an
344     * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
345     * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.  (Activities after
346     * the first in the array are started in the context of the previous activity
347     * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.)
348     * </p>
349     *
350     * <p class="note">
351     * The <em>last</em> intent in the array represents the key for the
352     * PendingIntent.  In other words, it is the significant element for matching
353     * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)},
354     * its content will be the subject of replacement by
355     * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc.
356     * This is because it is the most specific of the supplied intents, and the
357     * UI the user actually sees when the intents are started.
358     * </p>
359     *
360     * @param context The Context in which this PendingIntent should start
361     * the activity.
362     * @param requestCode Private request code for the sender (currently
363     * not used).
364     * @param intents Array of Intents of the activities to be launched.
365     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
366     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
367     * or any of the flags as supported by
368     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
369     * of the intent that can be supplied when the actual send happens.
370     *
371     * @return Returns an existing or new PendingIntent matching the given
372     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
373     * supplied.
374     */
375    public static PendingIntent getActivities(Context context, int requestCode,
376            Intent[] intents, int flags, Bundle options) {
377        String packageName = context.getPackageName();
378        String[] resolvedTypes = new String[intents.length];
379        for (int i=0; i<intents.length; i++) {
380            intents[i].setAllowFds(false);
381            resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
382        }
383        try {
384            IIntentSender target =
385                ActivityManagerNative.getDefault().getIntentSender(
386                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
387                    null, null, requestCode, intents, resolvedTypes, flags, options,
388                    UserHandle.myUserId());
389            return target != null ? new PendingIntent(target) : null;
390        } catch (RemoteException e) {
391        }
392        return null;
393    }
394
395    /**
396     * Retrieve a PendingIntent that will perform a broadcast, like calling
397     * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
398     *
399     * @param context The Context in which this PendingIntent should perform
400     * the broadcast.
401     * @param requestCode Private request code for the sender (currently
402     * not used).
403     * @param intent The Intent to be broadcast.
404     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
405     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
406     * or any of the flags as supported by
407     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
408     * of the intent that can be supplied when the actual send happens.
409     *
410     * @return Returns an existing or new PendingIntent matching the given
411     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
412     * supplied.
413     */
414    public static PendingIntent getBroadcast(Context context, int requestCode,
415            Intent intent, int flags) {
416        return getBroadcastAsUser(context, requestCode, intent, flags,
417                new UserHandle(UserHandle.myUserId()));
418    }
419
420    /** @hide */
421    public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
422            Intent intent, int flags, UserHandle userHandle) {
423        String packageName = context.getPackageName();
424        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
425                context.getContentResolver()) : null;
426        try {
427            intent.setAllowFds(false);
428            IIntentSender target =
429                ActivityManagerNative.getDefault().getIntentSender(
430                    ActivityManager.INTENT_SENDER_BROADCAST, packageName,
431                    null, null, requestCode, new Intent[] { intent },
432                    resolvedType != null ? new String[] { resolvedType } : null,
433                    flags, null, userHandle.getIdentifier());
434            return target != null ? new PendingIntent(target) : null;
435        } catch (RemoteException e) {
436        }
437        return null;
438    }
439
440    /**
441     * Retrieve a PendingIntent that will start a service, like calling
442     * {@link Context#startService Context.startService()}.  The start
443     * arguments given to the service will come from the extras of the Intent.
444     *
445     * @param context The Context in which this PendingIntent should start
446     * the service.
447     * @param requestCode Private request code for the sender (currently
448     * not used).
449     * @param intent An Intent describing the service to be started.
450     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
451     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
452     * or any of the flags as supported by
453     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
454     * of the intent that can be supplied when the actual send happens.
455     *
456     * @return Returns an existing or new PendingIntent matching the given
457     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
458     * supplied.
459     */
460    public static PendingIntent getService(Context context, int requestCode,
461            Intent intent, int flags) {
462        String packageName = context.getPackageName();
463        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
464                context.getContentResolver()) : null;
465        try {
466            intent.setAllowFds(false);
467            IIntentSender target =
468                ActivityManagerNative.getDefault().getIntentSender(
469                    ActivityManager.INTENT_SENDER_SERVICE, packageName,
470                    null, null, requestCode, new Intent[] { intent },
471                    resolvedType != null ? new String[] { resolvedType } : null,
472                    flags, null, UserHandle.myUserId());
473            return target != null ? new PendingIntent(target) : null;
474        } catch (RemoteException e) {
475        }
476        return null;
477    }
478
479    /**
480     * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent
481     *
482     * @return Returns a IntentSender object that wraps the sender of PendingIntent
483     *
484     */
485    public IntentSender getIntentSender() {
486        return new IntentSender(mTarget);
487    }
488
489    /**
490     * Cancel a currently active PendingIntent.  Only the original application
491     * owning a PendingIntent can cancel it.
492     */
493    public void cancel() {
494        try {
495            ActivityManagerNative.getDefault().cancelIntentSender(mTarget);
496        } catch (RemoteException e) {
497        }
498    }
499
500    /**
501     * Perform the operation associated with this PendingIntent.
502     *
503     * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
504     *
505     * @throws CanceledException Throws CanceledException if the PendingIntent
506     * is no longer allowing more intents to be sent through it.
507     */
508    public void send() throws CanceledException {
509        send(null, 0, null, null, null, null);
510    }
511
512    /**
513     * Perform the operation associated with this PendingIntent.
514     *
515     * @param code Result code to supply back to the PendingIntent's target.
516     *
517     * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
518     *
519     * @throws CanceledException Throws CanceledException if the PendingIntent
520     * is no longer allowing more intents to be sent through it.
521     */
522    public void send(int code) throws CanceledException {
523        send(null, code, null, null, null, null);
524    }
525
526    /**
527     * Perform the operation associated with this PendingIntent, allowing the
528     * caller to specify information about the Intent to use.
529     *
530     * @param context The Context of the caller.
531     * @param code Result code to supply back to the PendingIntent's target.
532     * @param intent Additional Intent data.  See {@link Intent#fillIn
533     * Intent.fillIn()} for information on how this is applied to the
534     * original Intent.
535     *
536     * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
537     *
538     * @throws CanceledException Throws CanceledException if the PendingIntent
539     * is no longer allowing more intents to be sent through it.
540     */
541    public void send(Context context, int code, Intent intent)
542            throws CanceledException {
543        send(context, code, intent, null, null, null);
544    }
545
546    /**
547     * Perform the operation associated with this PendingIntent, allowing the
548     * caller to be notified when the send has completed.
549     *
550     * @param code Result code to supply back to the PendingIntent's target.
551     * @param onFinished The object to call back on when the send has
552     * completed, or null for no callback.
553     * @param handler Handler identifying the thread on which the callback
554     * should happen.  If null, the callback will happen from the thread
555     * pool of the process.
556     *
557     * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
558     *
559     * @throws CanceledException Throws CanceledException if the PendingIntent
560     * is no longer allowing more intents to be sent through it.
561     */
562    public void send(int code, OnFinished onFinished, Handler handler)
563            throws CanceledException {
564        send(null, code, null, onFinished, handler, null);
565    }
566
567    /**
568     * Perform the operation associated with this PendingIntent, allowing the
569     * caller to specify information about the Intent to use and be notified
570     * when the send has completed.
571     *
572     * <p>For the intent parameter, a PendingIntent
573     * often has restrictions on which fields can be supplied here, based on
574     * how the PendingIntent was retrieved in {@link #getActivity},
575     * {@link #getBroadcast}, or {@link #getService}.
576     *
577     * @param context The Context of the caller.  This may be null if
578     * <var>intent</var> is also null.
579     * @param code Result code to supply back to the PendingIntent's target.
580     * @param intent Additional Intent data.  See {@link Intent#fillIn
581     * Intent.fillIn()} for information on how this is applied to the
582     * original Intent.  Use null to not modify the original Intent.
583     * @param onFinished The object to call back on when the send has
584     * completed, or null for no callback.
585     * @param handler Handler identifying the thread on which the callback
586     * should happen.  If null, the callback will happen from the thread
587     * pool of the process.
588     *
589     * @see #send()
590     * @see #send(int)
591     * @see #send(Context, int, Intent)
592     * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
593     * @see #send(Context, int, Intent, OnFinished, Handler, String)
594     *
595     * @throws CanceledException Throws CanceledException if the PendingIntent
596     * is no longer allowing more intents to be sent through it.
597     */
598    public void send(Context context, int code, Intent intent,
599            OnFinished onFinished, Handler handler) throws CanceledException {
600        send(context, code, intent, onFinished, handler, null);
601    }
602
603    /**
604     * Perform the operation associated with this PendingIntent, allowing the
605     * caller to specify information about the Intent to use and be notified
606     * when the send has completed.
607     *
608     * <p>For the intent parameter, a PendingIntent
609     * often has restrictions on which fields can be supplied here, based on
610     * how the PendingIntent was retrieved in {@link #getActivity},
611     * {@link #getBroadcast}, or {@link #getService}.
612     *
613     * @param context The Context of the caller.  This may be null if
614     * <var>intent</var> is also null.
615     * @param code Result code to supply back to the PendingIntent's target.
616     * @param intent Additional Intent data.  See {@link Intent#fillIn
617     * Intent.fillIn()} for information on how this is applied to the
618     * original Intent.  Use null to not modify the original Intent.
619     * @param onFinished The object to call back on when the send has
620     * completed, or null for no callback.
621     * @param handler Handler identifying the thread on which the callback
622     * should happen.  If null, the callback will happen from the thread
623     * pool of the process.
624     * @param requiredPermission Name of permission that a recipient of the PendingIntent
625     * is required to hold.  This is only valid for broadcast intents, and
626     * corresponds to the permission argument in
627     * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
628     * If null, no permission is required.
629     *
630     * @see #send()
631     * @see #send(int)
632     * @see #send(Context, int, Intent)
633     * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
634     * @see #send(Context, int, Intent, OnFinished, Handler)
635     *
636     * @throws CanceledException Throws CanceledException if the PendingIntent
637     * is no longer allowing more intents to be sent through it.
638     */
639    public void send(Context context, int code, Intent intent,
640            OnFinished onFinished, Handler handler, String requiredPermission)
641            throws CanceledException {
642        try {
643            String resolvedType = intent != null ?
644                    intent.resolveTypeIfNeeded(context.getContentResolver())
645                    : null;
646            int res = mTarget.send(code, intent, resolvedType,
647                    onFinished != null
648                            ? new FinishedDispatcher(this, onFinished, handler)
649                            : null,
650                    requiredPermission);
651            if (res < 0) {
652                throw new CanceledException();
653            }
654        } catch (RemoteException e) {
655            throw new CanceledException(e);
656        }
657    }
658
659    /**
660     * @deprecated Renamed to {@link #getCreatorPackage()}.
661     */
662    @Deprecated
663    public String getTargetPackage() {
664        try {
665            return ActivityManagerNative.getDefault()
666                .getPackageForIntentSender(mTarget);
667        } catch (RemoteException e) {
668            // Should never happen.
669            return null;
670        }
671    }
672
673    /**
674     * Return the package name of the application that created this
675     * PendingIntent, that is the identity under which you will actually be
676     * sending the Intent.  The returned string is supplied by the system, so
677     * that an application can not spoof its package.
678     *
679     * @return The package name of the PendingIntent, or null if there is
680     * none associated with it.
681     */
682    public String getCreatorPackage() {
683        try {
684            return ActivityManagerNative.getDefault()
685                .getPackageForIntentSender(mTarget);
686        } catch (RemoteException e) {
687            // Should never happen.
688            return null;
689        }
690    }
691
692    /**
693     * Return the uid of the application that created this
694     * PendingIntent, that is the identity under which you will actually be
695     * sending the Intent.  The returned integer is supplied by the system, so
696     * that an application can not spoof its uid.
697     *
698     * @return The uid of the PendingIntent, or -1 if there is
699     * none associated with it.
700     */
701    public int getCreatorUid() {
702        try {
703            return ActivityManagerNative.getDefault()
704                .getUidForIntentSender(mTarget);
705        } catch (RemoteException e) {
706            // Should never happen.
707            return -1;
708        }
709    }
710
711    /**
712     * Return the user handle of the application that created this
713     * PendingIntent, that is the user under which you will actually be
714     * sending the Intent.  The returned UserHandle is supplied by the system, so
715     * that an application can not spoof its user.  See
716     * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
717     * more explanation of user handles.
718     *
719     * @return The user handle of the PendingIntent, or null if there is
720     * none associated with it.
721     */
722    public UserHandle getCreatorUserHandle() {
723        try {
724            int uid = ActivityManagerNative.getDefault()
725                .getUidForIntentSender(mTarget);
726            return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
727        } catch (RemoteException e) {
728            // Should never happen.
729            return null;
730        }
731    }
732
733    /**
734     * @hide
735     * Check to verify that this PendingIntent targets a specific package.
736     */
737    public boolean isTargetedToPackage() {
738        try {
739            return ActivityManagerNative.getDefault()
740                .isIntentSenderTargetedToPackage(mTarget);
741        } catch (RemoteException e) {
742            // Should never happen.
743            return false;
744        }
745    }
746
747    /**
748     * @hide
749     * Check whether this PendingIntent will launch an Activity.
750     */
751    public boolean isActivity() {
752        try {
753            return ActivityManagerNative.getDefault()
754                .isIntentSenderAnActivity(mTarget);
755        } catch (RemoteException e) {
756            // Should never happen.
757            return false;
758        }
759    }
760
761    /**
762     * Comparison operator on two PendingIntent objects, such that true
763     * is returned then they both represent the same operation from the
764     * same package.  This allows you to use {@link #getActivity},
765     * {@link #getBroadcast}, or {@link #getService} multiple times (even
766     * across a process being killed), resulting in different PendingIntent
767     * objects but whose equals() method identifies them as being the same
768     * operation.
769     */
770    @Override
771    public boolean equals(Object otherObj) {
772        if (otherObj instanceof PendingIntent) {
773            return mTarget.asBinder().equals(((PendingIntent)otherObj)
774                    .mTarget.asBinder());
775        }
776        return false;
777    }
778
779    @Override
780    public int hashCode() {
781        return mTarget.asBinder().hashCode();
782    }
783
784    @Override
785    public String toString() {
786        StringBuilder sb = new StringBuilder(128);
787        sb.append("PendingIntent{");
788        sb.append(Integer.toHexString(System.identityHashCode(this)));
789        sb.append(": ");
790        sb.append(mTarget != null ? mTarget.asBinder() : null);
791        sb.append('}');
792        return sb.toString();
793    }
794
795    public int describeContents() {
796        return 0;
797    }
798
799    public void writeToParcel(Parcel out, int flags) {
800        out.writeStrongBinder(mTarget.asBinder());
801    }
802
803    public static final Parcelable.Creator<PendingIntent> CREATOR
804            = new Parcelable.Creator<PendingIntent>() {
805        public PendingIntent createFromParcel(Parcel in) {
806            IBinder target = in.readStrongBinder();
807            return target != null ? new PendingIntent(target) : null;
808        }
809
810        public PendingIntent[] newArray(int size) {
811            return new PendingIntent[size];
812        }
813    };
814
815    /**
816     * Convenience function for writing either a PendingIntent or null pointer to
817     * a Parcel.  You must use this with {@link #readPendingIntentOrNullFromParcel}
818     * for later reading it.
819     *
820     * @param sender The PendingIntent to write, or null.
821     * @param out Where to write the PendingIntent.
822     */
823    public static void writePendingIntentOrNullToParcel(PendingIntent sender,
824            Parcel out) {
825        out.writeStrongBinder(sender != null ? sender.mTarget.asBinder()
826                : null);
827    }
828
829    /**
830     * Convenience function for reading either a Messenger or null pointer from
831     * a Parcel.  You must have previously written the Messenger with
832     * {@link #writePendingIntentOrNullToParcel}.
833     *
834     * @param in The Parcel containing the written Messenger.
835     *
836     * @return Returns the Messenger read from the Parcel, or null if null had
837     * been written.
838     */
839    public static PendingIntent readPendingIntentOrNullFromParcel(Parcel in) {
840        IBinder b = in.readStrongBinder();
841        return b != null ? new PendingIntent(b) : null;
842    }
843
844    /*package*/ PendingIntent(IIntentSender target) {
845        mTarget = target;
846    }
847
848    /*package*/ PendingIntent(IBinder target) {
849        mTarget = IIntentSender.Stub.asInterface(target);
850    }
851
852    /** @hide */
853    public IIntentSender getTarget() {
854        return mTarget;
855    }
856}
857