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     * Note that UserHandle.CURRENT will be interpreted at the time the
269     * activity is started, not when the pending intent is created.
270     */
271    public static PendingIntent getActivityAsUser(Context context, int requestCode,
272            Intent intent, int flags, Bundle options, UserHandle user) {
273        String packageName = context.getPackageName();
274        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
275                context.getContentResolver()) : null;
276        try {
277            intent.setAllowFds(false);
278            IIntentSender target =
279                ActivityManagerNative.getDefault().getIntentSender(
280                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
281                    null, null, requestCode, new Intent[] { intent },
282                    resolvedType != null ? new String[] { resolvedType } : null,
283                    flags, options, user.getIdentifier());
284            return target != null ? new PendingIntent(target) : null;
285        } catch (RemoteException e) {
286        }
287        return null;
288    }
289
290    /**
291     * Like {@link #getActivity(Context, int, Intent, int)}, but allows an
292     * array of Intents to be supplied.  The first Intent in the array is
293     * taken as the primary key for the PendingIntent, like the single Intent
294     * given to {@link #getActivity(Context, int, Intent, int)}.  Upon sending
295     * the resulting PendingIntent, all of the Intents are started in the same
296     * way as they would be by passing them to {@link Context#startActivities(Intent[])}.
297     *
298     * <p class="note">
299     * The <em>first</em> intent in the array will be started outside of the context of an
300     * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
301     * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.  (Activities after
302     * the first in the array are started in the context of the previous activity
303     * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.)
304     * </p>
305     *
306     * <p class="note">
307     * The <em>last</em> intent in the array represents the key for the
308     * PendingIntent.  In other words, it is the significant element for matching
309     * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)},
310     * its content will be the subject of replacement by
311     * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc.
312     * This is because it is the most specific of the supplied intents, and the
313     * UI the user actually sees when the intents are started.
314     * </p>
315     *
316     * @param context The Context in which this PendingIntent should start
317     * the activity.
318     * @param requestCode Private request code for the sender (currently
319     * not used).
320     * @param intents Array of Intents of the activities to be launched.
321     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
322     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
323     * or any of the flags as supported by
324     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
325     * of the intent that can be supplied when the actual send happens.
326     *
327     * @return Returns an existing or new PendingIntent matching the given
328     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
329     * supplied.
330     */
331    public static PendingIntent getActivities(Context context, int requestCode,
332            Intent[] intents, int flags) {
333        return getActivities(context, requestCode, intents, flags, null);
334    }
335
336    /**
337     * Like {@link #getActivity(Context, int, Intent, int)}, but allows an
338     * array of Intents to be supplied.  The first Intent in the array is
339     * taken as the primary key for the PendingIntent, like the single Intent
340     * given to {@link #getActivity(Context, int, Intent, int)}.  Upon sending
341     * the resulting PendingIntent, all of the Intents are started in the same
342     * way as they would be by passing them to {@link Context#startActivities(Intent[])}.
343     *
344     * <p class="note">
345     * The <em>first</em> intent in the array will be started outside of the context of an
346     * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
347     * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.  (Activities after
348     * the first in the array are started in the context of the previous activity
349     * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.)
350     * </p>
351     *
352     * <p class="note">
353     * The <em>last</em> intent in the array represents the key for the
354     * PendingIntent.  In other words, it is the significant element for matching
355     * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)},
356     * its content will be the subject of replacement by
357     * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc.
358     * This is because it is the most specific of the supplied intents, and the
359     * UI the user actually sees when the intents are started.
360     * </p>
361     *
362     * @param context The Context in which this PendingIntent should start
363     * the activity.
364     * @param requestCode Private request code for the sender (currently
365     * not used).
366     * @param intents Array of Intents of the activities to be launched.
367     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
368     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
369     * or any of the flags as supported by
370     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
371     * of the intent that can be supplied when the actual send happens.
372     *
373     * @return Returns an existing or new PendingIntent matching the given
374     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
375     * supplied.
376     */
377    public static PendingIntent getActivities(Context context, int requestCode,
378            Intent[] intents, int flags, Bundle options) {
379        String packageName = context.getPackageName();
380        String[] resolvedTypes = new String[intents.length];
381        for (int i=0; i<intents.length; i++) {
382            intents[i].setAllowFds(false);
383            resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
384        }
385        try {
386            IIntentSender target =
387                ActivityManagerNative.getDefault().getIntentSender(
388                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
389                    null, null, requestCode, intents, resolvedTypes, flags, options,
390                    UserHandle.myUserId());
391            return target != null ? new PendingIntent(target) : null;
392        } catch (RemoteException e) {
393        }
394        return null;
395    }
396
397    /**
398     * @hide
399     * Note that UserHandle.CURRENT will be interpreted at the time the
400     * activity is started, not when the pending intent is created.
401     */
402    public static PendingIntent getActivitiesAsUser(Context context, int requestCode,
403            Intent[] intents, int flags, Bundle options, UserHandle user) {
404        String packageName = context.getPackageName();
405        String[] resolvedTypes = new String[intents.length];
406        for (int i=0; i<intents.length; i++) {
407            intents[i].setAllowFds(false);
408            resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
409        }
410        try {
411            IIntentSender target =
412                ActivityManagerNative.getDefault().getIntentSender(
413                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
414                    null, null, requestCode, intents, resolvedTypes,
415                    flags, options, user.getIdentifier());
416            return target != null ? new PendingIntent(target) : null;
417        } catch (RemoteException e) {
418        }
419        return null;
420    }
421
422    /**
423     * Retrieve a PendingIntent that will perform a broadcast, like calling
424     * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
425     *
426     * @param context The Context in which this PendingIntent should perform
427     * the broadcast.
428     * @param requestCode Private request code for the sender (currently
429     * not used).
430     * @param intent The Intent to be broadcast.
431     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
432     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
433     * or any of the flags as supported by
434     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
435     * of the intent that can be supplied when the actual send happens.
436     *
437     * @return Returns an existing or new PendingIntent matching the given
438     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
439     * supplied.
440     */
441    public static PendingIntent getBroadcast(Context context, int requestCode,
442            Intent intent, int flags) {
443        return getBroadcastAsUser(context, requestCode, intent, flags,
444                new UserHandle(UserHandle.myUserId()));
445    }
446
447    /**
448     * @hide
449     * Note that UserHandle.CURRENT will be interpreted at the time the
450     * broadcast is sent, not when the pending intent is created.
451     */
452    public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
453            Intent intent, int flags, UserHandle userHandle) {
454        String packageName = context.getPackageName();
455        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
456                context.getContentResolver()) : null;
457        try {
458            intent.setAllowFds(false);
459            IIntentSender target =
460                ActivityManagerNative.getDefault().getIntentSender(
461                    ActivityManager.INTENT_SENDER_BROADCAST, packageName,
462                    null, null, requestCode, new Intent[] { intent },
463                    resolvedType != null ? new String[] { resolvedType } : null,
464                    flags, null, userHandle.getIdentifier());
465            return target != null ? new PendingIntent(target) : null;
466        } catch (RemoteException e) {
467        }
468        return null;
469    }
470
471    /**
472     * Retrieve a PendingIntent that will start a service, like calling
473     * {@link Context#startService Context.startService()}.  The start
474     * arguments given to the service will come from the extras of the Intent.
475     *
476     * @param context The Context in which this PendingIntent should start
477     * the service.
478     * @param requestCode Private request code for the sender (currently
479     * not used).
480     * @param intent An Intent describing the service to be started.
481     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
482     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
483     * or any of the flags as supported by
484     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
485     * of the intent that can be supplied when the actual send happens.
486     *
487     * @return Returns an existing or new PendingIntent matching the given
488     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
489     * supplied.
490     */
491    public static PendingIntent getService(Context context, int requestCode,
492            Intent intent, int flags) {
493        String packageName = context.getPackageName();
494        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
495                context.getContentResolver()) : null;
496        try {
497            intent.setAllowFds(false);
498            IIntentSender target =
499                ActivityManagerNative.getDefault().getIntentSender(
500                    ActivityManager.INTENT_SENDER_SERVICE, packageName,
501                    null, null, requestCode, new Intent[] { intent },
502                    resolvedType != null ? new String[] { resolvedType } : null,
503                    flags, null, UserHandle.myUserId());
504            return target != null ? new PendingIntent(target) : null;
505        } catch (RemoteException e) {
506        }
507        return null;
508    }
509
510    /**
511     * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent
512     *
513     * @return Returns a IntentSender object that wraps the sender of PendingIntent
514     *
515     */
516    public IntentSender getIntentSender() {
517        return new IntentSender(mTarget);
518    }
519
520    /**
521     * Cancel a currently active PendingIntent.  Only the original application
522     * owning a PendingIntent can cancel it.
523     */
524    public void cancel() {
525        try {
526            ActivityManagerNative.getDefault().cancelIntentSender(mTarget);
527        } catch (RemoteException e) {
528        }
529    }
530
531    /**
532     * Perform the operation associated with this PendingIntent.
533     *
534     * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
535     *
536     * @throws CanceledException Throws CanceledException if the PendingIntent
537     * is no longer allowing more intents to be sent through it.
538     */
539    public void send() throws CanceledException {
540        send(null, 0, null, null, null, null);
541    }
542
543    /**
544     * Perform the operation associated with this PendingIntent.
545     *
546     * @param code Result code to supply back to the PendingIntent's target.
547     *
548     * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
549     *
550     * @throws CanceledException Throws CanceledException if the PendingIntent
551     * is no longer allowing more intents to be sent through it.
552     */
553    public void send(int code) throws CanceledException {
554        send(null, code, null, null, null, null);
555    }
556
557    /**
558     * Perform the operation associated with this PendingIntent, allowing the
559     * caller to specify information about the Intent to use.
560     *
561     * @param context The Context of the caller.
562     * @param code Result code to supply back to the PendingIntent's target.
563     * @param intent Additional Intent data.  See {@link Intent#fillIn
564     * Intent.fillIn()} for information on how this is applied to the
565     * original Intent.
566     *
567     * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
568     *
569     * @throws CanceledException Throws CanceledException if the PendingIntent
570     * is no longer allowing more intents to be sent through it.
571     */
572    public void send(Context context, int code, Intent intent)
573            throws CanceledException {
574        send(context, code, intent, null, null, null);
575    }
576
577    /**
578     * Perform the operation associated with this PendingIntent, allowing the
579     * caller to be notified when the send has completed.
580     *
581     * @param code Result code to supply back to the PendingIntent's target.
582     * @param onFinished The object to call back on when the send has
583     * completed, or null for no callback.
584     * @param handler Handler identifying the thread on which the callback
585     * should happen.  If null, the callback will happen from the thread
586     * pool of the process.
587     *
588     * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
589     *
590     * @throws CanceledException Throws CanceledException if the PendingIntent
591     * is no longer allowing more intents to be sent through it.
592     */
593    public void send(int code, OnFinished onFinished, Handler handler)
594            throws CanceledException {
595        send(null, code, null, onFinished, handler, null);
596    }
597
598    /**
599     * Perform the operation associated with this PendingIntent, allowing the
600     * caller to specify information about the Intent to use and be notified
601     * when the send has completed.
602     *
603     * <p>For the intent parameter, a PendingIntent
604     * often has restrictions on which fields can be supplied here, based on
605     * how the PendingIntent was retrieved in {@link #getActivity},
606     * {@link #getBroadcast}, or {@link #getService}.
607     *
608     * @param context The Context of the caller.  This may be null if
609     * <var>intent</var> is also null.
610     * @param code Result code to supply back to the PendingIntent's target.
611     * @param intent Additional Intent data.  See {@link Intent#fillIn
612     * Intent.fillIn()} for information on how this is applied to the
613     * original Intent.  Use null to not modify the original Intent.
614     * @param onFinished The object to call back on when the send has
615     * completed, or null for no callback.
616     * @param handler Handler identifying the thread on which the callback
617     * should happen.  If null, the callback will happen from the thread
618     * pool of the process.
619     *
620     * @see #send()
621     * @see #send(int)
622     * @see #send(Context, int, Intent)
623     * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
624     * @see #send(Context, int, Intent, OnFinished, Handler, String)
625     *
626     * @throws CanceledException Throws CanceledException if the PendingIntent
627     * is no longer allowing more intents to be sent through it.
628     */
629    public void send(Context context, int code, Intent intent,
630            OnFinished onFinished, Handler handler) throws CanceledException {
631        send(context, code, intent, onFinished, handler, null);
632    }
633
634    /**
635     * Perform the operation associated with this PendingIntent, allowing the
636     * caller to specify information about the Intent to use and be notified
637     * when the send has completed.
638     *
639     * <p>For the intent parameter, a PendingIntent
640     * often has restrictions on which fields can be supplied here, based on
641     * how the PendingIntent was retrieved in {@link #getActivity},
642     * {@link #getBroadcast}, or {@link #getService}.
643     *
644     * @param context The Context of the caller.  This may be null if
645     * <var>intent</var> is also null.
646     * @param code Result code to supply back to the PendingIntent's target.
647     * @param intent Additional Intent data.  See {@link Intent#fillIn
648     * Intent.fillIn()} for information on how this is applied to the
649     * original Intent.  Use null to not modify the original Intent.
650     * @param onFinished The object to call back on when the send has
651     * completed, or null for no callback.
652     * @param handler Handler identifying the thread on which the callback
653     * should happen.  If null, the callback will happen from the thread
654     * pool of the process.
655     * @param requiredPermission Name of permission that a recipient of the PendingIntent
656     * is required to hold.  This is only valid for broadcast intents, and
657     * corresponds to the permission argument in
658     * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
659     * If null, no permission is required.
660     *
661     * @see #send()
662     * @see #send(int)
663     * @see #send(Context, int, Intent)
664     * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
665     * @see #send(Context, int, Intent, OnFinished, Handler)
666     *
667     * @throws CanceledException Throws CanceledException if the PendingIntent
668     * is no longer allowing more intents to be sent through it.
669     */
670    public void send(Context context, int code, Intent intent,
671            OnFinished onFinished, Handler handler, String requiredPermission)
672            throws CanceledException {
673        try {
674            String resolvedType = intent != null ?
675                    intent.resolveTypeIfNeeded(context.getContentResolver())
676                    : null;
677            int res = mTarget.send(code, intent, resolvedType,
678                    onFinished != null
679                            ? new FinishedDispatcher(this, onFinished, handler)
680                            : null,
681                    requiredPermission);
682            if (res < 0) {
683                throw new CanceledException();
684            }
685        } catch (RemoteException e) {
686            throw new CanceledException(e);
687        }
688    }
689
690    /**
691     * @deprecated Renamed to {@link #getCreatorPackage()}.
692     */
693    @Deprecated
694    public String getTargetPackage() {
695        try {
696            return ActivityManagerNative.getDefault()
697                .getPackageForIntentSender(mTarget);
698        } catch (RemoteException e) {
699            // Should never happen.
700            return null;
701        }
702    }
703
704    /**
705     * Return the package name of the application that created this
706     * PendingIntent, that is the identity under which you will actually be
707     * sending the Intent.  The returned string is supplied by the system, so
708     * that an application can not spoof its package.
709     *
710     * @return The package name of the PendingIntent, or null if there is
711     * none associated with it.
712     */
713    public String getCreatorPackage() {
714        try {
715            return ActivityManagerNative.getDefault()
716                .getPackageForIntentSender(mTarget);
717        } catch (RemoteException e) {
718            // Should never happen.
719            return null;
720        }
721    }
722
723    /**
724     * Return the uid of the application that created this
725     * PendingIntent, that is the identity under which you will actually be
726     * sending the Intent.  The returned integer is supplied by the system, so
727     * that an application can not spoof its uid.
728     *
729     * @return The uid of the PendingIntent, or -1 if there is
730     * none associated with it.
731     */
732    public int getCreatorUid() {
733        try {
734            return ActivityManagerNative.getDefault()
735                .getUidForIntentSender(mTarget);
736        } catch (RemoteException e) {
737            // Should never happen.
738            return -1;
739        }
740    }
741
742    /**
743     * Return the user handle of the application that created this
744     * PendingIntent, that is the user under which you will actually be
745     * sending the Intent.  The returned UserHandle is supplied by the system, so
746     * that an application can not spoof its user.  See
747     * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
748     * more explanation of user handles.
749     *
750     * @return The user handle of the PendingIntent, or null if there is
751     * none associated with it.
752     */
753    public UserHandle getCreatorUserHandle() {
754        try {
755            int uid = ActivityManagerNative.getDefault()
756                .getUidForIntentSender(mTarget);
757            return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
758        } catch (RemoteException e) {
759            // Should never happen.
760            return null;
761        }
762    }
763
764    /**
765     * @hide
766     * Check to verify that this PendingIntent targets a specific package.
767     */
768    public boolean isTargetedToPackage() {
769        try {
770            return ActivityManagerNative.getDefault()
771                .isIntentSenderTargetedToPackage(mTarget);
772        } catch (RemoteException e) {
773            // Should never happen.
774            return false;
775        }
776    }
777
778    /**
779     * @hide
780     * Check whether this PendingIntent will launch an Activity.
781     */
782    public boolean isActivity() {
783        try {
784            return ActivityManagerNative.getDefault()
785                .isIntentSenderAnActivity(mTarget);
786        } catch (RemoteException e) {
787            // Should never happen.
788            return false;
789        }
790    }
791
792    /**
793     * Comparison operator on two PendingIntent objects, such that true
794     * is returned then they both represent the same operation from the
795     * same package.  This allows you to use {@link #getActivity},
796     * {@link #getBroadcast}, or {@link #getService} multiple times (even
797     * across a process being killed), resulting in different PendingIntent
798     * objects but whose equals() method identifies them as being the same
799     * operation.
800     */
801    @Override
802    public boolean equals(Object otherObj) {
803        if (otherObj instanceof PendingIntent) {
804            return mTarget.asBinder().equals(((PendingIntent)otherObj)
805                    .mTarget.asBinder());
806        }
807        return false;
808    }
809
810    @Override
811    public int hashCode() {
812        return mTarget.asBinder().hashCode();
813    }
814
815    @Override
816    public String toString() {
817        StringBuilder sb = new StringBuilder(128);
818        sb.append("PendingIntent{");
819        sb.append(Integer.toHexString(System.identityHashCode(this)));
820        sb.append(": ");
821        sb.append(mTarget != null ? mTarget.asBinder() : null);
822        sb.append('}');
823        return sb.toString();
824    }
825
826    public int describeContents() {
827        return 0;
828    }
829
830    public void writeToParcel(Parcel out, int flags) {
831        out.writeStrongBinder(mTarget.asBinder());
832    }
833
834    public static final Parcelable.Creator<PendingIntent> CREATOR
835            = new Parcelable.Creator<PendingIntent>() {
836        public PendingIntent createFromParcel(Parcel in) {
837            IBinder target = in.readStrongBinder();
838            return target != null ? new PendingIntent(target) : null;
839        }
840
841        public PendingIntent[] newArray(int size) {
842            return new PendingIntent[size];
843        }
844    };
845
846    /**
847     * Convenience function for writing either a PendingIntent or null pointer to
848     * a Parcel.  You must use this with {@link #readPendingIntentOrNullFromParcel}
849     * for later reading it.
850     *
851     * @param sender The PendingIntent to write, or null.
852     * @param out Where to write the PendingIntent.
853     */
854    public static void writePendingIntentOrNullToParcel(PendingIntent sender,
855            Parcel out) {
856        out.writeStrongBinder(sender != null ? sender.mTarget.asBinder()
857                : null);
858    }
859
860    /**
861     * Convenience function for reading either a Messenger or null pointer from
862     * a Parcel.  You must have previously written the Messenger with
863     * {@link #writePendingIntentOrNullToParcel}.
864     *
865     * @param in The Parcel containing the written Messenger.
866     *
867     * @return Returns the Messenger read from the Parcel, or null if null had
868     * been written.
869     */
870    public static PendingIntent readPendingIntentOrNullFromParcel(Parcel in) {
871        IBinder b = in.readStrongBinder();
872        return b != null ? new PendingIntent(b) : null;
873    }
874
875    /*package*/ PendingIntent(IIntentSender target) {
876        mTarget = target;
877    }
878
879    /*package*/ PendingIntent(IBinder target) {
880        mTarget = IIntentSender.Stub.asInterface(target);
881    }
882
883    /** @hide */
884    public IIntentSender getTarget() {
885        return mTarget;
886    }
887}
888