Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.app;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.NonNull;
     21 import android.annotation.Nullable;
     22 import android.annotation.UnsupportedAppUsage;
     23 import android.content.Context;
     24 import android.content.IIntentReceiver;
     25 import android.content.IIntentSender;
     26 import android.content.Intent;
     27 import android.content.IntentSender;
     28 import android.os.Bundle;
     29 import android.os.Handler;
     30 import android.os.IBinder;
     31 import android.os.Looper;
     32 import android.os.Parcel;
     33 import android.os.Parcelable;
     34 import android.os.RemoteException;
     35 import android.os.UserHandle;
     36 import android.util.AndroidException;
     37 import android.util.ArraySet;
     38 import android.util.proto.ProtoOutputStream;
     39 
     40 import com.android.internal.os.IResultReceiver;
     41 
     42 import java.lang.annotation.Retention;
     43 import java.lang.annotation.RetentionPolicy;
     44 
     45 /**
     46  * A description of an Intent and target action to perform with it.  Instances
     47  * of this class are created with {@link #getActivity}, {@link #getActivities},
     48  * {@link #getBroadcast}, and {@link #getService}; the returned object can be
     49  * handed to other applications so that they can perform the action you
     50  * described on your behalf at a later time.
     51  *
     52  * <p>By giving a PendingIntent to another application,
     53  * you are granting it the right to perform the operation you have specified
     54  * as if the other application was yourself (with the same permissions and
     55  * identity).  As such, you should be careful about how you build the PendingIntent:
     56  * almost always, for example, the base Intent you supply should have the component
     57  * name explicitly set to one of your own components, to ensure it is ultimately
     58  * sent there and nowhere else.
     59  *
     60  * <p>A PendingIntent itself is simply a reference to a token maintained by
     61  * the system describing the original data used to retrieve it.  This means
     62  * that, even if its owning application's process is killed, the
     63  * PendingIntent itself will remain usable from other processes that
     64  * have been given it.  If the creating application later re-retrieves the
     65  * same kind of PendingIntent (same operation, same Intent action, data,
     66  * categories, and components, and same flags), it will receive a PendingIntent
     67  * representing the same token if that is still valid, and can thus call
     68  * {@link #cancel} to remove it.
     69  *
     70  * <p>Because of this behavior, it is important to know when two Intents
     71  * are considered to be the same for purposes of retrieving a PendingIntent.
     72  * A common mistake people make is to create multiple PendingIntent objects
     73  * with Intents that only vary in their "extra" contents, expecting to get
     74  * a different PendingIntent each time.  This does <em>not</em> happen.  The
     75  * parts of the Intent that are used for matching are the same ones defined
     76  * by {@link Intent#filterEquals(Intent) Intent.filterEquals}.  If you use two
     77  * Intent objects that are equivalent as per
     78  * {@link Intent#filterEquals(Intent) Intent.filterEquals}, then you will get
     79  * the same PendingIntent for both of them.
     80  *
     81  * <p>There are two typical ways to deal with this.
     82  *
     83  * <p>If you truly need multiple distinct PendingIntent objects active at
     84  * the same time (such as to use as two notifications that are both shown
     85  * at the same time), then you will need to ensure there is something that
     86  * is different about them to associate them with different PendingIntents.
     87  * This may be any of the Intent attributes considered by
     88  * {@link Intent#filterEquals(Intent) Intent.filterEquals}, or different
     89  * request code integers supplied to {@link #getActivity}, {@link #getActivities},
     90  * {@link #getBroadcast}, or {@link #getService}.
     91  *
     92  * <p>If you only need one PendingIntent active at a time for any of the
     93  * Intents you will use, then you can alternatively use the flags
     94  * {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either
     95  * cancel or modify whatever current PendingIntent is associated with the
     96  * Intent you are supplying.
     97  */
     98 public final class PendingIntent implements Parcelable {
     99     private final IIntentSender mTarget;
    100     private IResultReceiver mCancelReceiver;
    101     private IBinder mWhitelistToken;
    102     private ArraySet<CancelListener> mCancelListeners;
    103 
    104     /** @hide */
    105     @IntDef(flag = true,
    106             value = {
    107                     FLAG_ONE_SHOT,
    108                     FLAG_NO_CREATE,
    109                     FLAG_CANCEL_CURRENT,
    110                     FLAG_UPDATE_CURRENT,
    111                     FLAG_IMMUTABLE,
    112 
    113                     Intent.FILL_IN_ACTION,
    114                     Intent.FILL_IN_DATA,
    115                     Intent.FILL_IN_CATEGORIES,
    116                     Intent.FILL_IN_COMPONENT,
    117                     Intent.FILL_IN_PACKAGE,
    118                     Intent.FILL_IN_SOURCE_BOUNDS,
    119                     Intent.FILL_IN_SELECTOR,
    120                     Intent.FILL_IN_CLIP_DATA
    121             })
    122     @Retention(RetentionPolicy.SOURCE)
    123     public @interface Flags {}
    124 
    125     /**
    126      * Flag indicating that this PendingIntent can be used only once.
    127      * For use with {@link #getActivity}, {@link #getBroadcast}, and
    128      * {@link #getService}. <p>If set, after
    129      * {@link #send()} is called on it, it will be automatically
    130      * canceled for you and any future attempt to send through it will fail.
    131      */
    132     public static final int FLAG_ONE_SHOT = 1<<30;
    133     /**
    134      * Flag indicating that if the described PendingIntent does not
    135      * already exist, then simply return null instead of creating it.
    136      * For use with {@link #getActivity}, {@link #getBroadcast}, and
    137      * {@link #getService}.
    138      */
    139     public static final int FLAG_NO_CREATE = 1<<29;
    140     /**
    141      * Flag indicating that if the described PendingIntent already exists,
    142      * the current one should be canceled before generating a new one.
    143      * For use with {@link #getActivity}, {@link #getBroadcast}, and
    144      * {@link #getService}. <p>You can use
    145      * this to retrieve a new PendingIntent when you are only changing the
    146      * extra data in the Intent; by canceling the previous pending intent,
    147      * this ensures that only entities given the new data will be able to
    148      * launch it.  If this assurance is not an issue, consider
    149      * {@link #FLAG_UPDATE_CURRENT}.
    150      */
    151     public static final int FLAG_CANCEL_CURRENT = 1<<28;
    152     /**
    153      * Flag indicating that if the described PendingIntent already exists,
    154      * then keep it but replace its extra data with what is in this new
    155      * Intent. For use with {@link #getActivity}, {@link #getBroadcast}, and
    156      * {@link #getService}. <p>This can be used if you are creating intents where only the
    157      * extras change, and don't care that any entities that received your
    158      * previous PendingIntent will be able to launch it with your new
    159      * extras even if they are not explicitly given to it.
    160      */
    161     public static final int FLAG_UPDATE_CURRENT = 1<<27;
    162 
    163     /**
    164      * Flag indicating that the created PendingIntent should be immutable.
    165      * This means that the additional intent argument passed to the send
    166      * methods to fill in unpopulated properties of this intent will be
    167      * ignored.
    168      */
    169     public static final int FLAG_IMMUTABLE = 1<<26;
    170 
    171     /**
    172      * Exception thrown when trying to send through a PendingIntent that
    173      * has been canceled or is otherwise no longer able to execute the request.
    174      */
    175     public static class CanceledException extends AndroidException {
    176         public CanceledException() {
    177         }
    178 
    179         public CanceledException(String name) {
    180             super(name);
    181         }
    182 
    183         public CanceledException(Exception cause) {
    184             super(cause);
    185         }
    186     }
    187 
    188     /**
    189      * Callback interface for discovering when a send operation has
    190      * completed.  Primarily for use with a PendingIntent that is
    191      * performing a broadcast, this provides the same information as
    192      * calling {@link Context#sendOrderedBroadcast(Intent, String,
    193      * android.content.BroadcastReceiver, Handler, int, String, Bundle)
    194      * Context.sendBroadcast()} with a final BroadcastReceiver.
    195      */
    196     public interface OnFinished {
    197         /**
    198          * Called when a send operation as completed.
    199          *
    200          * @param pendingIntent The PendingIntent this operation was sent through.
    201          * @param intent The original Intent that was sent.
    202          * @param resultCode The final result code determined by the send.
    203          * @param resultData The final data collected by a broadcast.
    204          * @param resultExtras The final extras collected by a broadcast.
    205          */
    206         void onSendFinished(PendingIntent pendingIntent, Intent intent,
    207                 int resultCode, String resultData, Bundle resultExtras);
    208     }
    209 
    210     private static class FinishedDispatcher extends IIntentReceiver.Stub
    211             implements Runnable {
    212         private final PendingIntent mPendingIntent;
    213         private final OnFinished mWho;
    214         private final Handler mHandler;
    215         private Intent mIntent;
    216         private int mResultCode;
    217         private String mResultData;
    218         private Bundle mResultExtras;
    219         private static Handler sDefaultSystemHandler;
    220         FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) {
    221             mPendingIntent = pi;
    222             mWho = who;
    223             if (handler == null && ActivityThread.isSystem()) {
    224                 // We assign a default handler for the system process to avoid deadlocks when
    225                 // processing receivers in various components that hold global service locks.
    226                 if (sDefaultSystemHandler == null) {
    227                     sDefaultSystemHandler = new Handler(Looper.getMainLooper());
    228                 }
    229                 mHandler = sDefaultSystemHandler;
    230             } else {
    231                 mHandler = handler;
    232             }
    233         }
    234         public void performReceive(Intent intent, int resultCode, String data,
    235                 Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
    236             mIntent = intent;
    237             mResultCode = resultCode;
    238             mResultData = data;
    239             mResultExtras = extras;
    240             if (mHandler == null) {
    241                 run();
    242             } else {
    243                 mHandler.post(this);
    244             }
    245         }
    246         public void run() {
    247             mWho.onSendFinished(mPendingIntent, mIntent, mResultCode,
    248                     mResultData, mResultExtras);
    249         }
    250     }
    251 
    252     /**
    253      * Listener for observing when pending intents are written to a parcel.
    254      *
    255      * @hide
    256      */
    257     public interface OnMarshaledListener {
    258         /**
    259          * Called when a pending intent is written to a parcel.
    260          *
    261          * @param intent The pending intent.
    262          * @param parcel The parcel to which it was written.
    263          * @param flags The parcel flags when it was written.
    264          */
    265         void onMarshaled(PendingIntent intent, Parcel parcel, int flags);
    266     }
    267 
    268     private static final ThreadLocal<OnMarshaledListener> sOnMarshaledListener
    269             = new ThreadLocal<>();
    270 
    271     /**
    272      * Registers an listener for pending intents being written to a parcel.
    273      *
    274      * @param listener The listener, null to clear.
    275      *
    276      * @hide
    277      */
    278     @UnsupportedAppUsage
    279     public static void setOnMarshaledListener(OnMarshaledListener listener) {
    280         sOnMarshaledListener.set(listener);
    281     }
    282 
    283     /**
    284      * Retrieve a PendingIntent that will start a new activity, like calling
    285      * {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
    286      * Note that the activity will be started outside of the context of an
    287      * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
    288      * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.
    289      *
    290      * <p class="note">For security reasons, the {@link android.content.Intent}
    291      * you supply here should almost always be an <em>explicit intent</em>,
    292      * that is specify an explicit component to be delivered to through
    293      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
    294      *
    295      * @param context The Context in which this PendingIntent should start
    296      * the activity.
    297      * @param requestCode Private request code for the sender
    298      * @param intent Intent of the activity to be launched.
    299      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
    300      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
    301      * or any of the flags as supported by
    302      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
    303      * of the intent that can be supplied when the actual send happens.
    304      *
    305      * @return Returns an existing or new PendingIntent matching the given
    306      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
    307      * supplied.
    308      */
    309     public static PendingIntent getActivity(Context context, int requestCode,
    310             Intent intent, @Flags int flags) {
    311         return getActivity(context, requestCode, intent, flags, null);
    312     }
    313 
    314     /**
    315      * Retrieve a PendingIntent that will start a new activity, like calling
    316      * {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
    317      * Note that the activity will be started outside of the context of an
    318      * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
    319      * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.
    320      *
    321      * <p class="note">For security reasons, the {@link android.content.Intent}
    322      * you supply here should almost always be an <em>explicit intent</em>,
    323      * that is specify an explicit component to be delivered to through
    324      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
    325      *
    326      * @param context The Context in which this PendingIntent should start
    327      * the activity.
    328      * @param requestCode Private request code for the sender
    329      * @param intent Intent of the activity to be launched.
    330      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
    331      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
    332      * or any of the flags as supported by
    333      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
    334      * of the intent that can be supplied when the actual send happens.
    335      * @param options Additional options for how the Activity should be started.
    336      * May be null if there are no options.
    337      *
    338      * @return Returns an existing or new PendingIntent matching the given
    339      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
    340      * supplied.
    341      */
    342     public static PendingIntent getActivity(Context context, int requestCode,
    343             @NonNull Intent intent, @Flags int flags, @Nullable Bundle options) {
    344         String packageName = context.getPackageName();
    345         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
    346                 context.getContentResolver()) : null;
    347         try {
    348             intent.migrateExtraStreamToClipData();
    349             intent.prepareToLeaveProcess(context);
    350             IIntentSender target =
    351                 ActivityManager.getService().getIntentSender(
    352                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
    353                     null, null, requestCode, new Intent[] { intent },
    354                     resolvedType != null ? new String[] { resolvedType } : null,
    355                     flags, options, context.getUserId());
    356             return target != null ? new PendingIntent(target) : null;
    357         } catch (RemoteException e) {
    358             throw e.rethrowFromSystemServer();
    359         }
    360     }
    361 
    362     /**
    363      * @hide
    364      * Note that UserHandle.CURRENT will be interpreted at the time the
    365      * activity is started, not when the pending intent is created.
    366      */
    367     @UnsupportedAppUsage
    368     public static PendingIntent getActivityAsUser(Context context, int requestCode,
    369             @NonNull Intent intent, int flags, Bundle options, UserHandle user) {
    370         String packageName = context.getPackageName();
    371         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
    372                 context.getContentResolver()) : null;
    373         try {
    374             intent.migrateExtraStreamToClipData();
    375             intent.prepareToLeaveProcess(context);
    376             IIntentSender target =
    377                 ActivityManager.getService().getIntentSender(
    378                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
    379                     null, null, requestCode, new Intent[] { intent },
    380                     resolvedType != null ? new String[] { resolvedType } : null,
    381                     flags, options, user.getIdentifier());
    382             return target != null ? new PendingIntent(target) : null;
    383         } catch (RemoteException e) {
    384             throw e.rethrowFromSystemServer();
    385         }
    386     }
    387 
    388     /**
    389      * Like {@link #getActivity(Context, int, Intent, int)}, but allows an
    390      * array of Intents to be supplied.  The last Intent in the array is
    391      * taken as the primary key for the PendingIntent, like the single Intent
    392      * given to {@link #getActivity(Context, int, Intent, int)}.  Upon sending
    393      * the resulting PendingIntent, all of the Intents are started in the same
    394      * way as they would be by passing them to {@link Context#startActivities(Intent[])}.
    395      *
    396      * <p class="note">
    397      * The <em>first</em> intent in the array will be started outside of the context of an
    398      * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
    399      * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.  (Activities after
    400      * the first in the array are started in the context of the previous activity
    401      * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.)
    402      * </p>
    403      *
    404      * <p class="note">
    405      * The <em>last</em> intent in the array represents the key for the
    406      * PendingIntent.  In other words, it is the significant element for matching
    407      * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)},
    408      * its content will be the subject of replacement by
    409      * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc.
    410      * This is because it is the most specific of the supplied intents, and the
    411      * UI the user actually sees when the intents are started.
    412      * </p>
    413      *
    414      * <p class="note">For security reasons, the {@link android.content.Intent} objects
    415      * you supply here should almost always be <em>explicit intents</em>,
    416      * that is specify an explicit component to be delivered to through
    417      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
    418      *
    419      * @param context The Context in which this PendingIntent should start
    420      * the activity.
    421      * @param requestCode Private request code for the sender
    422      * @param intents Array of Intents of the activities to be launched.
    423      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
    424      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
    425      * or any of the flags as supported by
    426      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
    427      * of the intent that can be supplied when the actual send happens.
    428      *
    429      * @return Returns an existing or new PendingIntent matching the given
    430      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
    431      * supplied.
    432      */
    433     public static PendingIntent getActivities(Context context, int requestCode,
    434             @NonNull Intent[] intents, @Flags int flags) {
    435         return getActivities(context, requestCode, intents, flags, null);
    436     }
    437 
    438     /**
    439      * Like {@link #getActivity(Context, int, Intent, int)}, but allows an
    440      * array of Intents to be supplied.  The last Intent in the array is
    441      * taken as the primary key for the PendingIntent, like the single Intent
    442      * given to {@link #getActivity(Context, int, Intent, int)}.  Upon sending
    443      * the resulting PendingIntent, all of the Intents are started in the same
    444      * way as they would be by passing them to {@link Context#startActivities(Intent[])}.
    445      *
    446      * <p class="note">
    447      * The <em>first</em> intent in the array will be started outside of the context of an
    448      * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
    449      * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.  (Activities after
    450      * the first in the array are started in the context of the previous activity
    451      * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.)
    452      * </p>
    453      *
    454      * <p class="note">
    455      * The <em>last</em> intent in the array represents the key for the
    456      * PendingIntent.  In other words, it is the significant element for matching
    457      * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)},
    458      * its content will be the subject of replacement by
    459      * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc.
    460      * This is because it is the most specific of the supplied intents, and the
    461      * UI the user actually sees when the intents are started.
    462      * </p>
    463      *
    464      * <p class="note">For security reasons, the {@link android.content.Intent} objects
    465      * you supply here should almost always be <em>explicit intents</em>,
    466      * that is specify an explicit component to be delivered to through
    467      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
    468      *
    469      * @param context The Context in which this PendingIntent should start
    470      * the activity.
    471      * @param requestCode Private request code for the sender
    472      * @param intents Array of Intents of the activities to be launched.
    473      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
    474      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
    475      * {@link #FLAG_IMMUTABLE} or any of the flags as supported by
    476      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
    477      * of the intent that can be supplied when the actual send happens.
    478      *
    479      * @return Returns an existing or new PendingIntent matching the given
    480      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
    481      * supplied.
    482      */
    483     public static PendingIntent getActivities(Context context, int requestCode,
    484             @NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options) {
    485         String packageName = context.getPackageName();
    486         String[] resolvedTypes = new String[intents.length];
    487         for (int i=0; i<intents.length; i++) {
    488             intents[i].migrateExtraStreamToClipData();
    489             intents[i].prepareToLeaveProcess(context);
    490             resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
    491         }
    492         try {
    493             IIntentSender target =
    494                 ActivityManager.getService().getIntentSender(
    495                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
    496                     null, null, requestCode, intents, resolvedTypes, flags, options,
    497                     context.getUserId());
    498             return target != null ? new PendingIntent(target) : null;
    499         } catch (RemoteException e) {
    500             throw e.rethrowFromSystemServer();
    501         }
    502     }
    503 
    504     /**
    505      * @hide
    506      * Note that UserHandle.CURRENT will be interpreted at the time the
    507      * activity is started, not when the pending intent is created.
    508      */
    509     public static PendingIntent getActivitiesAsUser(Context context, int requestCode,
    510             @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
    511         String packageName = context.getPackageName();
    512         String[] resolvedTypes = new String[intents.length];
    513         for (int i=0; i<intents.length; i++) {
    514             intents[i].migrateExtraStreamToClipData();
    515             intents[i].prepareToLeaveProcess(context);
    516             resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
    517         }
    518         try {
    519             IIntentSender target =
    520                 ActivityManager.getService().getIntentSender(
    521                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
    522                     null, null, requestCode, intents, resolvedTypes,
    523                     flags, options, user.getIdentifier());
    524             return target != null ? new PendingIntent(target) : null;
    525         } catch (RemoteException e) {
    526             throw e.rethrowFromSystemServer();
    527         }
    528     }
    529 
    530     /**
    531      * Retrieve a PendingIntent that will perform a broadcast, like calling
    532      * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
    533      *
    534      * <p class="note">For security reasons, the {@link android.content.Intent}
    535      * you supply here should almost always be an <em>explicit intent</em>,
    536      * that is specify an explicit component to be delivered to through
    537      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
    538      *
    539      * @param context The Context in which this PendingIntent should perform
    540      * the broadcast.
    541      * @param requestCode Private request code for the sender
    542      * @param intent The Intent to be broadcast.
    543      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
    544      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
    545      * {@link #FLAG_IMMUTABLE} or any of the flags as supported by
    546      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
    547      * of the intent that can be supplied when the actual send happens.
    548      *
    549      * @return Returns an existing or new PendingIntent matching the given
    550      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
    551      * supplied.
    552      */
    553     public static PendingIntent getBroadcast(Context context, int requestCode,
    554             Intent intent, @Flags int flags) {
    555         return getBroadcastAsUser(context, requestCode, intent, flags, context.getUser());
    556     }
    557 
    558     /**
    559      * @hide
    560      * Note that UserHandle.CURRENT will be interpreted at the time the
    561      * broadcast is sent, not when the pending intent is created.
    562      */
    563     @UnsupportedAppUsage
    564     public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
    565             Intent intent, int flags, UserHandle userHandle) {
    566         String packageName = context.getPackageName();
    567         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
    568                 context.getContentResolver()) : null;
    569         try {
    570             intent.prepareToLeaveProcess(context);
    571             IIntentSender target =
    572                 ActivityManager.getService().getIntentSender(
    573                     ActivityManager.INTENT_SENDER_BROADCAST, packageName,
    574                     null, null, requestCode, new Intent[] { intent },
    575                     resolvedType != null ? new String[] { resolvedType } : null,
    576                     flags, null, userHandle.getIdentifier());
    577             return target != null ? new PendingIntent(target) : null;
    578         } catch (RemoteException e) {
    579             throw e.rethrowFromSystemServer();
    580         }
    581     }
    582 
    583     /**
    584      * Retrieve a PendingIntent that will start a service, like calling
    585      * {@link Context#startService Context.startService()}.  The start
    586      * arguments given to the service will come from the extras of the Intent.
    587      *
    588      * <p class="note">For security reasons, the {@link android.content.Intent}
    589      * you supply here should almost always be an <em>explicit intent</em>,
    590      * that is specify an explicit component to be delivered to through
    591      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
    592      *
    593      * @param context The Context in which this PendingIntent should start
    594      * the service.
    595      * @param requestCode Private request code for the sender
    596      * @param intent An Intent describing the service to be started.
    597      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
    598      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
    599      * {@link #FLAG_IMMUTABLE} or any of the flags as supported by
    600      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
    601      * of the intent that can be supplied when the actual send happens.
    602      *
    603      * @return Returns an existing or new PendingIntent matching the given
    604      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
    605      * supplied.
    606      */
    607     public static PendingIntent getService(Context context, int requestCode,
    608             @NonNull Intent intent, @Flags int flags) {
    609         return buildServicePendingIntent(context, requestCode, intent, flags,
    610                 ActivityManager.INTENT_SENDER_SERVICE);
    611     }
    612 
    613     /**
    614      * Retrieve a PendingIntent that will start a foreground service, like calling
    615      * {@link Context#startForegroundService Context.startForegroundService()}.  The start
    616      * arguments given to the service will come from the extras of the Intent.
    617      *
    618      * <p class="note">For security reasons, the {@link android.content.Intent}
    619      * you supply here should almost always be an <em>explicit intent</em>,
    620      * that is specify an explicit component to be delivered to through
    621      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
    622      *
    623      * @param context The Context in which this PendingIntent should start
    624      * the service.
    625      * @param requestCode Private request code for the sender
    626      * @param intent An Intent describing the service to be started.
    627      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
    628      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
    629      * {@link #FLAG_IMMUTABLE} or any of the flags as supported by
    630      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
    631      * of the intent that can be supplied when the actual send happens.
    632      *
    633      * @return Returns an existing or new PendingIntent matching the given
    634      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
    635      * supplied.
    636      */
    637     public static PendingIntent getForegroundService(Context context, int requestCode,
    638             @NonNull Intent intent, @Flags int flags) {
    639         return buildServicePendingIntent(context, requestCode, intent, flags,
    640                 ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE);
    641     }
    642 
    643     private static PendingIntent buildServicePendingIntent(Context context, int requestCode,
    644             Intent intent, int flags, int serviceKind) {
    645         String packageName = context.getPackageName();
    646         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
    647                 context.getContentResolver()) : null;
    648         try {
    649             intent.prepareToLeaveProcess(context);
    650             IIntentSender target =
    651                 ActivityManager.getService().getIntentSender(
    652                     serviceKind, packageName,
    653                     null, null, requestCode, new Intent[] { intent },
    654                     resolvedType != null ? new String[] { resolvedType } : null,
    655                     flags, null, context.getUserId());
    656             return target != null ? new PendingIntent(target) : null;
    657         } catch (RemoteException e) {
    658             throw e.rethrowFromSystemServer();
    659         }
    660     }
    661 
    662     /**
    663      * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent
    664      *
    665      * @return Returns a IntentSender object that wraps the sender of PendingIntent
    666      *
    667      */
    668     public IntentSender getIntentSender() {
    669         return new IntentSender(mTarget, mWhitelistToken);
    670     }
    671 
    672     /**
    673      * Cancel a currently active PendingIntent.  Only the original application
    674      * owning a PendingIntent can cancel it.
    675      */
    676     public void cancel() {
    677         try {
    678             ActivityManager.getService().cancelIntentSender(mTarget);
    679         } catch (RemoteException e) {
    680         }
    681     }
    682 
    683     /**
    684      * Perform the operation associated with this PendingIntent.
    685      *
    686      * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
    687      *
    688      * @throws CanceledException Throws CanceledException if the PendingIntent
    689      * is no longer allowing more intents to be sent through it.
    690      */
    691     public void send() throws CanceledException {
    692         send(null, 0, null, null, null, null, null);
    693     }
    694 
    695     /**
    696      * Perform the operation associated with this PendingIntent.
    697      *
    698      * @param code Result code to supply back to the PendingIntent's target.
    699      *
    700      * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
    701      *
    702      * @throws CanceledException Throws CanceledException if the PendingIntent
    703      * is no longer allowing more intents to be sent through it.
    704      */
    705     public void send(int code) throws CanceledException {
    706         send(null, code, null, null, null, null, null);
    707     }
    708 
    709     /**
    710      * Perform the operation associated with this PendingIntent, allowing the
    711      * caller to specify information about the Intent to use.
    712      *
    713      * @param context The Context of the caller.
    714      * @param code Result code to supply back to the PendingIntent's target.
    715      * @param intent Additional Intent data.  See {@link Intent#fillIn
    716      * Intent.fillIn()} for information on how this is applied to the
    717      * original Intent. If flag {@link #FLAG_IMMUTABLE} was set when this
    718      * pending intent was created, this argument will be ignored.
    719      *
    720      * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
    721      *
    722      * @throws CanceledException Throws CanceledException if the PendingIntent
    723      * is no longer allowing more intents to be sent through it.
    724      */
    725     public void send(Context context, int code, @Nullable Intent intent)
    726             throws CanceledException {
    727         send(context, code, intent, null, null, null, null);
    728     }
    729 
    730     /**
    731      * Perform the operation associated with this PendingIntent, allowing the
    732      * caller to be notified when the send has completed.
    733      *
    734      * @param code Result code to supply back to the PendingIntent's target.
    735      * @param onFinished The object to call back on when the send has
    736      * completed, or null for no callback.
    737      * @param handler Handler identifying the thread on which the callback
    738      * should happen.  If null, the callback will happen from the thread
    739      * pool of the process.
    740      *
    741      * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
    742      *
    743      * @throws CanceledException Throws CanceledException if the PendingIntent
    744      * is no longer allowing more intents to be sent through it.
    745      */
    746     public void send(int code, @Nullable OnFinished onFinished, @Nullable Handler handler)
    747             throws CanceledException {
    748         send(null, code, null, onFinished, handler, null, null);
    749     }
    750 
    751     /**
    752      * Perform the operation associated with this PendingIntent, allowing the
    753      * caller to specify information about the Intent to use and be notified
    754      * when the send has completed.
    755      *
    756      * <p>For the intent parameter, a PendingIntent
    757      * often has restrictions on which fields can be supplied here, based on
    758      * how the PendingIntent was retrieved in {@link #getActivity},
    759      * {@link #getBroadcast}, or {@link #getService}.
    760      *
    761      * @param context The Context of the caller.  This may be null if
    762      * <var>intent</var> is also null.
    763      * @param code Result code to supply back to the PendingIntent's target.
    764      * @param intent Additional Intent data.  See {@link Intent#fillIn
    765      * Intent.fillIn()} for information on how this is applied to the
    766      * original Intent.  Use null to not modify the original Intent.
    767      * If flag {@link #FLAG_IMMUTABLE} was set when this pending intent was
    768      * created, this argument will be ignored.
    769      * @param onFinished The object to call back on when the send has
    770      * completed, or null for no callback.
    771      * @param handler Handler identifying the thread on which the callback
    772      * should happen.  If null, the callback will happen from the thread
    773      * pool of the process.
    774      *
    775      * @see #send()
    776      * @see #send(int)
    777      * @see #send(Context, int, Intent)
    778      * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
    779      * @see #send(Context, int, Intent, OnFinished, Handler, String)
    780      *
    781      * @throws CanceledException Throws CanceledException if the PendingIntent
    782      * is no longer allowing more intents to be sent through it.
    783      */
    784     public void send(Context context, int code, @Nullable Intent intent,
    785             @Nullable OnFinished onFinished, @Nullable Handler handler) throws CanceledException {
    786         send(context, code, intent, onFinished, handler, null, null);
    787     }
    788 
    789     /**
    790      * Perform the operation associated with this PendingIntent, allowing the
    791      * caller to specify information about the Intent to use and be notified
    792      * when the send has completed.
    793      *
    794      * <p>For the intent parameter, a PendingIntent
    795      * often has restrictions on which fields can be supplied here, based on
    796      * how the PendingIntent was retrieved in {@link #getActivity},
    797      * {@link #getBroadcast}, or {@link #getService}.
    798      *
    799      * @param context The Context of the caller.  This may be null if
    800      * <var>intent</var> is also null.
    801      * @param code Result code to supply back to the PendingIntent's target.
    802      * @param intent Additional Intent data.  See {@link Intent#fillIn
    803      * Intent.fillIn()} for information on how this is applied to the
    804      * original Intent.  Use null to not modify the original Intent.
    805      * If flag {@link #FLAG_IMMUTABLE} was set when this pending intent was
    806      * created, this argument will be ignored.
    807      * @param onFinished The object to call back on when the send has
    808      * completed, or null for no callback.
    809      * @param handler Handler identifying the thread on which the callback
    810      * should happen.  If null, the callback will happen from the thread
    811      * pool of the process.
    812      * @param requiredPermission Name of permission that a recipient of the PendingIntent
    813      * is required to hold.  This is only valid for broadcast intents, and
    814      * corresponds to the permission argument in
    815      * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
    816      * If null, no permission is required.
    817      *
    818      * @see #send()
    819      * @see #send(int)
    820      * @see #send(Context, int, Intent)
    821      * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
    822      * @see #send(Context, int, Intent, OnFinished, Handler)
    823      *
    824      * @throws CanceledException Throws CanceledException if the PendingIntent
    825      * is no longer allowing more intents to be sent through it.
    826      */
    827     public void send(Context context, int code, @Nullable Intent intent,
    828             @Nullable OnFinished onFinished, @Nullable Handler handler,
    829             @Nullable String requiredPermission)
    830             throws CanceledException {
    831         send(context, code, intent, onFinished, handler, requiredPermission, null);
    832     }
    833 
    834     /**
    835      * Perform the operation associated with this PendingIntent, allowing the
    836      * caller to specify information about the Intent to use and be notified
    837      * when the send has completed.
    838      *
    839      * <p>For the intent parameter, a PendingIntent
    840      * often has restrictions on which fields can be supplied here, based on
    841      * how the PendingIntent was retrieved in {@link #getActivity},
    842      * {@link #getBroadcast}, or {@link #getService}.
    843      *
    844      * @param context The Context of the caller.  This may be null if
    845      * <var>intent</var> is also null.
    846      * @param code Result code to supply back to the PendingIntent's target.
    847      * @param intent Additional Intent data.  See {@link Intent#fillIn
    848      * Intent.fillIn()} for information on how this is applied to the
    849      * original Intent.  Use null to not modify the original Intent.
    850      * If flag {@link #FLAG_IMMUTABLE} was set when this pending intent was
    851      * created, this argument will be ignored.
    852      * @param onFinished The object to call back on when the send has
    853      * completed, or null for no callback.
    854      * @param handler Handler identifying the thread on which the callback
    855      * should happen.  If null, the callback will happen from the thread
    856      * pool of the process.
    857      * @param requiredPermission Name of permission that a recipient of the PendingIntent
    858      * is required to hold.  This is only valid for broadcast intents, and
    859      * corresponds to the permission argument in
    860      * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
    861      * If null, no permission is required.
    862      * @param options Additional options the caller would like to provide to modify the sending
    863      * behavior.  May be built from an {@link ActivityOptions} to apply to an activity start.
    864      *
    865      * @see #send()
    866      * @see #send(int)
    867      * @see #send(Context, int, Intent)
    868      * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
    869      * @see #send(Context, int, Intent, OnFinished, Handler)
    870      *
    871      * @throws CanceledException Throws CanceledException if the PendingIntent
    872      * is no longer allowing more intents to be sent through it.
    873      */
    874     public void send(Context context, int code, @Nullable Intent intent,
    875             @Nullable OnFinished onFinished, @Nullable Handler handler,
    876             @Nullable String requiredPermission, @Nullable Bundle options)
    877             throws CanceledException {
    878         if (sendAndReturnResult(context, code, intent, onFinished, handler, requiredPermission,
    879                 options) < 0) {
    880             throw new CanceledException();
    881         }
    882     }
    883 
    884     /**
    885      * Like {@link #send}, but returns the result
    886      * @hide
    887      */
    888     public int sendAndReturnResult(Context context, int code, @Nullable Intent intent,
    889             @Nullable OnFinished onFinished, @Nullable Handler handler,
    890             @Nullable String requiredPermission, @Nullable Bundle options)
    891             throws CanceledException {
    892         try {
    893             String resolvedType = intent != null ?
    894                     intent.resolveTypeIfNeeded(context.getContentResolver())
    895                     : null;
    896             return ActivityManager.getService().sendIntentSender(
    897                     mTarget, mWhitelistToken, code, intent, resolvedType,
    898                     onFinished != null
    899                             ? new FinishedDispatcher(this, onFinished, handler)
    900                             : null,
    901                     requiredPermission, options);
    902         } catch (RemoteException e) {
    903             throw new CanceledException(e);
    904         }
    905     }
    906 
    907     /**
    908      * @deprecated Renamed to {@link #getCreatorPackage()}.
    909      */
    910     @Deprecated
    911     public String getTargetPackage() {
    912         try {
    913             return ActivityManager.getService()
    914                 .getPackageForIntentSender(mTarget);
    915         } catch (RemoteException e) {
    916             throw e.rethrowFromSystemServer();
    917         }
    918     }
    919 
    920     /**
    921      * Return the package name of the application that created this
    922      * PendingIntent, that is the identity under which you will actually be
    923      * sending the Intent.  The returned string is supplied by the system, so
    924      * that an application can not spoof its package.
    925      *
    926      * <p class="note">Be careful about how you use this.  All this tells you is
    927      * who created the PendingIntent.  It does <strong>not</strong> tell you who
    928      * handed the PendingIntent to you: that is, PendingIntent objects are intended to be
    929      * passed between applications, so the PendingIntent you receive from an application
    930      * could actually be one it received from another application, meaning the result
    931      * you get here will identify the original application.  Because of this, you should
    932      * only use this information to identify who you expect to be interacting with
    933      * through a {@link #send} call, not who gave you the PendingIntent.</p>
    934      *
    935      * @return The package name of the PendingIntent, or null if there is
    936      * none associated with it.
    937      */
    938     @Nullable
    939     public String getCreatorPackage() {
    940         try {
    941             return ActivityManager.getService()
    942                 .getPackageForIntentSender(mTarget);
    943         } catch (RemoteException e) {
    944             throw e.rethrowFromSystemServer();
    945         }
    946     }
    947 
    948     /**
    949      * Return the uid of the application that created this
    950      * PendingIntent, that is the identity under which you will actually be
    951      * sending the Intent.  The returned integer is supplied by the system, so
    952      * that an application can not spoof its uid.
    953      *
    954      * <p class="note">Be careful about how you use this.  All this tells you is
    955      * who created the PendingIntent.  It does <strong>not</strong> tell you who
    956      * handed the PendingIntent to you: that is, PendingIntent objects are intended to be
    957      * passed between applications, so the PendingIntent you receive from an application
    958      * could actually be one it received from another application, meaning the result
    959      * you get here will identify the original application.  Because of this, you should
    960      * only use this information to identify who you expect to be interacting with
    961      * through a {@link #send} call, not who gave you the PendingIntent.</p>
    962      *
    963      * @return The uid of the PendingIntent, or -1 if there is
    964      * none associated with it.
    965      */
    966     public int getCreatorUid() {
    967         try {
    968             return ActivityManager.getService()
    969                 .getUidForIntentSender(mTarget);
    970         } catch (RemoteException e) {
    971             throw e.rethrowFromSystemServer();
    972         }
    973     }
    974 
    975     /**
    976      * Register a listener to when this pendingIntent is cancelled. There are no guarantees on which
    977      * thread a listener will be called and it's up to the caller to synchronize. This may
    978      * trigger a synchronous binder call so should therefore usually be called on a background
    979      * thread.
    980      *
    981      * @hide
    982      */
    983     public void registerCancelListener(CancelListener cancelListener) {
    984         synchronized (this) {
    985             if (mCancelReceiver == null) {
    986                 mCancelReceiver = new IResultReceiver.Stub() {
    987                     @Override
    988                     public void send(int resultCode, Bundle resultData) throws RemoteException {
    989                         notifyCancelListeners();
    990                     }
    991                 };
    992             }
    993             if (mCancelListeners == null) {
    994                 mCancelListeners = new ArraySet<>();
    995             }
    996             boolean wasEmpty = mCancelListeners.isEmpty();
    997             mCancelListeners.add(cancelListener);
    998             if (wasEmpty) {
    999                 try {
   1000                     ActivityManager.getService().registerIntentSenderCancelListener(mTarget,
   1001                             mCancelReceiver);
   1002                 } catch (RemoteException e) {
   1003                     throw e.rethrowFromSystemServer();
   1004                 }
   1005             }
   1006         }
   1007     }
   1008 
   1009     private void notifyCancelListeners() {
   1010         ArraySet<CancelListener> cancelListeners;
   1011         synchronized (this) {
   1012             cancelListeners = new ArraySet<>(mCancelListeners);
   1013         }
   1014         int size = cancelListeners.size();
   1015         for (int i = 0; i < size; i++) {
   1016             cancelListeners.valueAt(i).onCancelled(this);
   1017         }
   1018     }
   1019 
   1020     /**
   1021      * Un-register a listener to when this pendingIntent is cancelled.
   1022      *
   1023      * @hide
   1024      */
   1025     public void unregisterCancelListener(CancelListener cancelListener) {
   1026         synchronized (this) {
   1027             if (mCancelListeners == null) {
   1028                 return;
   1029             }
   1030             boolean wasEmpty = mCancelListeners.isEmpty();
   1031             mCancelListeners.remove(cancelListener);
   1032             if (mCancelListeners.isEmpty() && !wasEmpty) {
   1033                 try {
   1034                     ActivityManager.getService().unregisterIntentSenderCancelListener(mTarget,
   1035                             mCancelReceiver);
   1036                 } catch (RemoteException e) {
   1037                     throw e.rethrowFromSystemServer();
   1038                 }
   1039             }
   1040         }
   1041     }
   1042 
   1043     /**
   1044      * Return the user handle of the application that created this
   1045      * PendingIntent, that is the user under which you will actually be
   1046      * sending the Intent.  The returned UserHandle is supplied by the system, so
   1047      * that an application can not spoof its user.  See
   1048      * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
   1049      * more explanation of user handles.
   1050      *
   1051      * <p class="note">Be careful about how you use this.  All this tells you is
   1052      * who created the PendingIntent.  It does <strong>not</strong> tell you who
   1053      * handed the PendingIntent to you: that is, PendingIntent objects are intended to be
   1054      * passed between applications, so the PendingIntent you receive from an application
   1055      * could actually be one it received from another application, meaning the result
   1056      * you get here will identify the original application.  Because of this, you should
   1057      * only use this information to identify who you expect to be interacting with
   1058      * through a {@link #send} call, not who gave you the PendingIntent.</p>
   1059      *
   1060      * @return The user handle of the PendingIntent, or null if there is
   1061      * none associated with it.
   1062      */
   1063     @Nullable
   1064     public UserHandle getCreatorUserHandle() {
   1065         try {
   1066             int uid = ActivityManager.getService()
   1067                 .getUidForIntentSender(mTarget);
   1068             return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
   1069         } catch (RemoteException e) {
   1070             throw e.rethrowFromSystemServer();
   1071         }
   1072     }
   1073 
   1074     /**
   1075      * @hide
   1076      * Check to verify that this PendingIntent targets a specific package.
   1077      */
   1078     public boolean isTargetedToPackage() {
   1079         try {
   1080             return ActivityManager.getService()
   1081                 .isIntentSenderTargetedToPackage(mTarget);
   1082         } catch (RemoteException e) {
   1083             throw e.rethrowFromSystemServer();
   1084         }
   1085     }
   1086 
   1087     /**
   1088      * @hide
   1089      * Check whether this PendingIntent will launch an Activity.
   1090      */
   1091     @UnsupportedAppUsage
   1092     public boolean isActivity() {
   1093         try {
   1094             return ActivityManager.getService()
   1095                 .isIntentSenderAnActivity(mTarget);
   1096         } catch (RemoteException e) {
   1097             throw e.rethrowFromSystemServer();
   1098         }
   1099     }
   1100 
   1101     /**
   1102      * @hide
   1103      * Check whether this PendingIntent will launch a foreground service
   1104      */
   1105     public boolean isForegroundService() {
   1106         try {
   1107             return ActivityManager.getService()
   1108                     .isIntentSenderAForegroundService(mTarget);
   1109         } catch (RemoteException e) {
   1110             throw e.rethrowFromSystemServer();
   1111         }
   1112     }
   1113 
   1114     /**
   1115      * @hide
   1116      * Check whether this PendingIntent will launch an Activity.
   1117      */
   1118     public boolean isBroadcast() {
   1119         try {
   1120             return ActivityManager.getService()
   1121                 .isIntentSenderABroadcast(mTarget);
   1122         } catch (RemoteException e) {
   1123             throw e.rethrowFromSystemServer();
   1124         }
   1125     }
   1126 
   1127     /**
   1128      * @hide
   1129      * Return the Intent of this PendingIntent.
   1130      */
   1131     @UnsupportedAppUsage
   1132     public Intent getIntent() {
   1133         try {
   1134             return ActivityManager.getService()
   1135                 .getIntentForIntentSender(mTarget);
   1136         } catch (RemoteException e) {
   1137             throw e.rethrowFromSystemServer();
   1138         }
   1139     }
   1140 
   1141     /**
   1142      * @hide
   1143      * Return descriptive tag for this PendingIntent.
   1144      */
   1145     @UnsupportedAppUsage
   1146     public String getTag(String prefix) {
   1147         try {
   1148             return ActivityManager.getService()
   1149                 .getTagForIntentSender(mTarget, prefix);
   1150         } catch (RemoteException e) {
   1151             throw e.rethrowFromSystemServer();
   1152         }
   1153     }
   1154 
   1155     /**
   1156      * Comparison operator on two PendingIntent objects, such that true
   1157      * is returned then they both represent the same operation from the
   1158      * same package.  This allows you to use {@link #getActivity},
   1159      * {@link #getBroadcast}, or {@link #getService} multiple times (even
   1160      * across a process being killed), resulting in different PendingIntent
   1161      * objects but whose equals() method identifies them as being the same
   1162      * operation.
   1163      */
   1164     @Override
   1165     public boolean equals(Object otherObj) {
   1166         if (otherObj instanceof PendingIntent) {
   1167             return mTarget.asBinder().equals(((PendingIntent)otherObj)
   1168                     .mTarget.asBinder());
   1169         }
   1170         return false;
   1171     }
   1172 
   1173     @Override
   1174     public int hashCode() {
   1175         return mTarget.asBinder().hashCode();
   1176     }
   1177 
   1178     @Override
   1179     public String toString() {
   1180         StringBuilder sb = new StringBuilder(128);
   1181         sb.append("PendingIntent{");
   1182         sb.append(Integer.toHexString(System.identityHashCode(this)));
   1183         sb.append(": ");
   1184         sb.append(mTarget != null ? mTarget.asBinder() : null);
   1185         sb.append('}');
   1186         return sb.toString();
   1187     }
   1188 
   1189     /** @hide */
   1190     public void writeToProto(ProtoOutputStream proto, long fieldId) {
   1191         final long token = proto.start(fieldId);
   1192         if (mTarget != null) {
   1193             proto.write(PendingIntentProto.TARGET, mTarget.asBinder().toString());
   1194         }
   1195         proto.end(token);
   1196     }
   1197 
   1198     public int describeContents() {
   1199         return 0;
   1200     }
   1201 
   1202     public void writeToParcel(Parcel out, int flags) {
   1203         out.writeStrongBinder(mTarget.asBinder());
   1204         OnMarshaledListener listener = sOnMarshaledListener.get();
   1205         if (listener != null) {
   1206             listener.onMarshaled(this, out, flags);
   1207         }
   1208 
   1209     }
   1210 
   1211     public static final @android.annotation.NonNull Parcelable.Creator<PendingIntent> CREATOR
   1212             = new Parcelable.Creator<PendingIntent>() {
   1213         public PendingIntent createFromParcel(Parcel in) {
   1214             IBinder target = in.readStrongBinder();
   1215             return target != null
   1216                     ? new PendingIntent(target, in.getClassCookie(PendingIntent.class))
   1217                     : null;
   1218         }
   1219 
   1220         public PendingIntent[] newArray(int size) {
   1221             return new PendingIntent[size];
   1222         }
   1223     };
   1224 
   1225     /**
   1226      * Convenience function for writing either a PendingIntent or null pointer to
   1227      * a Parcel.  You must use this with {@link #readPendingIntentOrNullFromParcel}
   1228      * for later reading it.
   1229      *
   1230      * @param sender The PendingIntent to write, or null.
   1231      * @param out Where to write the PendingIntent.
   1232      */
   1233     public static void writePendingIntentOrNullToParcel(@Nullable PendingIntent sender,
   1234             @NonNull Parcel out) {
   1235         out.writeStrongBinder(sender != null ? sender.mTarget.asBinder() : null);
   1236         if (sender != null) {
   1237             OnMarshaledListener listener = sOnMarshaledListener.get();
   1238             if (listener != null) {
   1239                 listener.onMarshaled(sender, out, 0 /* flags */);
   1240             }
   1241         }
   1242     }
   1243 
   1244     /**
   1245      * Convenience function for reading either a PendingIntent or null pointer from
   1246      * a Parcel.  You must have previously written the PendingIntent with
   1247      * {@link #writePendingIntentOrNullToParcel}.
   1248      *
   1249      * @param in The Parcel containing the written PendingIntent.
   1250      *
   1251      * @return Returns the PendingIntent read from the Parcel, or null if null had
   1252      * been written.
   1253      */
   1254     @Nullable
   1255     public static PendingIntent readPendingIntentOrNullFromParcel(@NonNull Parcel in) {
   1256         IBinder b = in.readStrongBinder();
   1257         return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null;
   1258     }
   1259 
   1260     /*package*/ PendingIntent(IIntentSender target) {
   1261         mTarget = target;
   1262     }
   1263 
   1264     /*package*/ PendingIntent(IBinder target, Object cookie) {
   1265         mTarget = IIntentSender.Stub.asInterface(target);
   1266         if (cookie != null) {
   1267             mWhitelistToken = (IBinder)cookie;
   1268         }
   1269     }
   1270 
   1271     /** @hide */
   1272     public IIntentSender getTarget() {
   1273         return mTarget;
   1274     }
   1275 
   1276     /** @hide */
   1277     public IBinder getWhitelistToken() {
   1278         return mWhitelistToken;
   1279     }
   1280 
   1281     /**
   1282      * A listener to when a pending intent is cancelled
   1283      *
   1284      * @hide
   1285      */
   1286     public interface CancelListener {
   1287         /**
   1288          * Called when a Pending Intent is cancelled.
   1289          *
   1290          * @param intent The intent that was cancelled.
   1291          */
   1292         void onCancelled(PendingIntent intent);
   1293     }
   1294 }
   1295