Home | History | Annotate | Download | only in content
      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.content;
     18 
     19 import android.app.ActivityManagerNative;
     20 import android.os.Bundle;
     21 import android.os.RemoteException;
     22 import android.os.Handler;
     23 import android.os.IBinder;
     24 import android.os.Parcel;
     25 import android.os.Parcelable;
     26 import android.os.UserHandle;
     27 import android.util.AndroidException;
     28 
     29 
     30 /**
     31  * A description of an Intent and target action to perform with it.
     32  * The returned object can be
     33  * handed to other applications so that they can perform the action you
     34  * described on your behalf at a later time.
     35  *
     36  * <p>By giving a IntentSender to another application,
     37  * you are granting it the right to perform the operation you have specified
     38  * as if the other application was yourself (with the same permissions and
     39  * identity).  As such, you should be careful about how you build the IntentSender:
     40  * often, for example, the base Intent you supply will have the component
     41  * name explicitly set to one of your own components, to ensure it is ultimately
     42  * sent there and nowhere else.
     43  *
     44  * <p>A IntentSender itself is simply a reference to a token maintained by
     45  * the system describing the original data used to retrieve it.  This means
     46  * that, even if its owning application's process is killed, the
     47  * IntentSender itself will remain usable from other processes that
     48  * have been given it.  If the creating application later re-retrieves the
     49  * same kind of IntentSender (same operation, same Intent action, data,
     50  * categories, and components, and same flags), it will receive a IntentSender
     51  * representing the same token if that is still valid.
     52  *
     53  * <p>Instances of this class can not be made directly, but rather must be
     54  * created from an existing {@link android.app.PendingIntent} with
     55  * {@link android.app.PendingIntent#getIntentSender() PendingIntent.getIntentSender()}.
     56  */
     57 public class IntentSender implements Parcelable {
     58     private final IIntentSender mTarget;
     59 
     60     /**
     61      * Exception thrown when trying to send through a PendingIntent that
     62      * has been canceled or is otherwise no longer able to execute the request.
     63      */
     64     public static class SendIntentException extends AndroidException {
     65         public SendIntentException() {
     66         }
     67 
     68         public SendIntentException(String name) {
     69             super(name);
     70         }
     71 
     72         public SendIntentException(Exception cause) {
     73             super(cause);
     74         }
     75     }
     76 
     77     /**
     78      * Callback interface for discovering when a send operation has
     79      * completed.  Primarily for use with a IntentSender that is
     80      * performing a broadcast, this provides the same information as
     81      * calling {@link Context#sendOrderedBroadcast(Intent, String,
     82      * android.content.BroadcastReceiver, Handler, int, String, Bundle)
     83      * Context.sendBroadcast()} with a final BroadcastReceiver.
     84      */
     85     public interface OnFinished {
     86         /**
     87          * Called when a send operation as completed.
     88          *
     89          * @param IntentSender The IntentSender this operation was sent through.
     90          * @param intent The original Intent that was sent.
     91          * @param resultCode The final result code determined by the send.
     92          * @param resultData The final data collected by a broadcast.
     93          * @param resultExtras The final extras collected by a broadcast.
     94          */
     95         void onSendFinished(IntentSender IntentSender, Intent intent,
     96                 int resultCode, String resultData, Bundle resultExtras);
     97     }
     98 
     99     private static class FinishedDispatcher extends IIntentReceiver.Stub
    100             implements Runnable {
    101         private final IntentSender mIntentSender;
    102         private final OnFinished mWho;
    103         private final Handler mHandler;
    104         private Intent mIntent;
    105         private int mResultCode;
    106         private String mResultData;
    107         private Bundle mResultExtras;
    108         FinishedDispatcher(IntentSender pi, OnFinished who, Handler handler) {
    109             mIntentSender = pi;
    110             mWho = who;
    111             mHandler = handler;
    112         }
    113         public void performReceive(Intent intent, int resultCode, String data,
    114                 Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
    115             mIntent = intent;
    116             mResultCode = resultCode;
    117             mResultData = data;
    118             mResultExtras = extras;
    119             if (mHandler == null) {
    120                 run();
    121             } else {
    122                 mHandler.post(this);
    123             }
    124         }
    125         public void run() {
    126             mWho.onSendFinished(mIntentSender, mIntent, mResultCode,
    127                     mResultData, mResultExtras);
    128         }
    129     }
    130 
    131     /**
    132      * Perform the operation associated with this IntentSender, allowing the
    133      * caller to specify information about the Intent to use and be notified
    134      * when the send has completed.
    135      *
    136      * @param context The Context of the caller.  This may be null if
    137      * <var>intent</var> is also null.
    138      * @param code Result code to supply back to the IntentSender's target.
    139      * @param intent Additional Intent data.  See {@link Intent#fillIn
    140      * Intent.fillIn()} for information on how this is applied to the
    141      * original Intent.  Use null to not modify the original Intent.
    142      * @param onFinished The object to call back on when the send has
    143      * completed, or null for no callback.
    144      * @param handler Handler identifying the thread on which the callback
    145      * should happen.  If null, the callback will happen from the thread
    146      * pool of the process.
    147      *
    148      *
    149      * @throws SendIntentException Throws CanceledIntentException if the IntentSender
    150      * is no longer allowing more intents to be sent through it.
    151      */
    152     public void sendIntent(Context context, int code, Intent intent,
    153             OnFinished onFinished, Handler handler) throws SendIntentException {
    154         sendIntent(context, code, intent, onFinished, handler, null);
    155     }
    156 
    157     /**
    158      * Perform the operation associated with this IntentSender, allowing the
    159      * caller to specify information about the Intent to use and be notified
    160      * when the send has completed.
    161      *
    162      * @param context The Context of the caller.  This may be null if
    163      * <var>intent</var> is also null.
    164      * @param code Result code to supply back to the IntentSender's target.
    165      * @param intent Additional Intent data.  See {@link Intent#fillIn
    166      * Intent.fillIn()} for information on how this is applied to the
    167      * original Intent.  Use null to not modify the original Intent.
    168      * @param onFinished The object to call back on when the send has
    169      * completed, or null for no callback.
    170      * @param handler Handler identifying the thread on which the callback
    171      * should happen.  If null, the callback will happen from the thread
    172      * pool of the process.
    173      * @param requiredPermission Name of permission that a recipient of the PendingIntent
    174      * is required to hold.  This is only valid for broadcast intents, and
    175      * corresponds to the permission argument in
    176      * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
    177      * If null, no permission is required.
    178      *
    179      *
    180      * @throws SendIntentException Throws CanceledIntentException if the IntentSender
    181      * is no longer allowing more intents to be sent through it.
    182      */
    183     public void sendIntent(Context context, int code, Intent intent,
    184             OnFinished onFinished, Handler handler, String requiredPermission)
    185             throws SendIntentException {
    186         try {
    187             String resolvedType = intent != null ?
    188                     intent.resolveTypeIfNeeded(context.getContentResolver())
    189                     : null;
    190             int res = ActivityManagerNative.getDefault().sendIntentSender(mTarget,
    191                     code, intent, resolvedType,
    192                     onFinished != null
    193                             ? new FinishedDispatcher(this, onFinished, handler)
    194                             : null,
    195                     requiredPermission, null);
    196             if (res < 0) {
    197                 throw new SendIntentException();
    198             }
    199         } catch (RemoteException e) {
    200             throw new SendIntentException();
    201         }
    202     }
    203 
    204     /**
    205      * @deprecated Renamed to {@link #getCreatorPackage()}.
    206      */
    207     @Deprecated
    208     public String getTargetPackage() {
    209         try {
    210             return ActivityManagerNative.getDefault()
    211                 .getPackageForIntentSender(mTarget);
    212         } catch (RemoteException e) {
    213             // Should never happen.
    214             return null;
    215         }
    216     }
    217 
    218     /**
    219      * Return the package name of the application that created this
    220      * IntentSender, that is the identity under which you will actually be
    221      * sending the Intent.  The returned string is supplied by the system, so
    222      * that an application can not spoof its package.
    223      *
    224      * @return The package name of the PendingIntent, or null if there is
    225      * none associated with it.
    226      */
    227     public String getCreatorPackage() {
    228         try {
    229             return ActivityManagerNative.getDefault()
    230                 .getPackageForIntentSender(mTarget);
    231         } catch (RemoteException e) {
    232             // Should never happen.
    233             return null;
    234         }
    235     }
    236 
    237     /**
    238      * Return the uid of the application that created this
    239      * PendingIntent, that is the identity under which you will actually be
    240      * sending the Intent.  The returned integer is supplied by the system, so
    241      * that an application can not spoof its uid.
    242      *
    243      * @return The uid of the PendingIntent, or -1 if there is
    244      * none associated with it.
    245      */
    246     public int getCreatorUid() {
    247         try {
    248             return ActivityManagerNative.getDefault()
    249                 .getUidForIntentSender(mTarget);
    250         } catch (RemoteException e) {
    251             // Should never happen.
    252             return -1;
    253         }
    254     }
    255 
    256     /**
    257      * Return the user handle of the application that created this
    258      * PendingIntent, that is the user under which you will actually be
    259      * sending the Intent.  The returned UserHandle is supplied by the system, so
    260      * that an application can not spoof its user.  See
    261      * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
    262      * more explanation of user handles.
    263      *
    264      * @return The user handle of the PendingIntent, or null if there is
    265      * none associated with it.
    266      */
    267     public UserHandle getCreatorUserHandle() {
    268         try {
    269             int uid = ActivityManagerNative.getDefault()
    270                 .getUidForIntentSender(mTarget);
    271             return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
    272         } catch (RemoteException e) {
    273             // Should never happen.
    274             return null;
    275         }
    276     }
    277 
    278     /**
    279      * Comparison operator on two IntentSender objects, such that true
    280      * is returned then they both represent the same operation from the
    281      * same package.
    282      */
    283     @Override
    284     public boolean equals(Object otherObj) {
    285         if (otherObj instanceof IntentSender) {
    286             return mTarget.asBinder().equals(((IntentSender)otherObj)
    287                     .mTarget.asBinder());
    288         }
    289         return false;
    290     }
    291 
    292     @Override
    293     public int hashCode() {
    294         return mTarget.asBinder().hashCode();
    295     }
    296 
    297     @Override
    298     public String toString() {
    299         StringBuilder sb = new StringBuilder(128);
    300         sb.append("IntentSender{");
    301         sb.append(Integer.toHexString(System.identityHashCode(this)));
    302         sb.append(": ");
    303         sb.append(mTarget != null ? mTarget.asBinder() : null);
    304         sb.append('}');
    305         return sb.toString();
    306     }
    307 
    308     public int describeContents() {
    309         return 0;
    310     }
    311 
    312     public void writeToParcel(Parcel out, int flags) {
    313         out.writeStrongBinder(mTarget.asBinder());
    314     }
    315 
    316     public static final Parcelable.Creator<IntentSender> CREATOR
    317             = new Parcelable.Creator<IntentSender>() {
    318         public IntentSender createFromParcel(Parcel in) {
    319             IBinder target = in.readStrongBinder();
    320             return target != null ? new IntentSender(target) : null;
    321         }
    322 
    323         public IntentSender[] newArray(int size) {
    324             return new IntentSender[size];
    325         }
    326     };
    327 
    328     /**
    329      * Convenience function for writing either a IntentSender or null pointer to
    330      * a Parcel.  You must use this with {@link #readIntentSenderOrNullFromParcel}
    331      * for later reading it.
    332      *
    333      * @param sender The IntentSender to write, or null.
    334      * @param out Where to write the IntentSender.
    335      */
    336     public static void writeIntentSenderOrNullToParcel(IntentSender sender,
    337             Parcel out) {
    338         out.writeStrongBinder(sender != null ? sender.mTarget.asBinder()
    339                 : null);
    340     }
    341 
    342     /**
    343      * Convenience function for reading either a Messenger or null pointer from
    344      * a Parcel.  You must have previously written the Messenger with
    345      * {@link #writeIntentSenderOrNullToParcel}.
    346      *
    347      * @param in The Parcel containing the written Messenger.
    348      *
    349      * @return Returns the Messenger read from the Parcel, or null if null had
    350      * been written.
    351      */
    352     public static IntentSender readIntentSenderOrNullFromParcel(Parcel in) {
    353         IBinder b = in.readStrongBinder();
    354         return b != null ? new IntentSender(b) : null;
    355     }
    356 
    357     /** @hide */
    358     public IIntentSender getTarget() {
    359         return mTarget;
    360     }
    361 
    362     /** @hide */
    363     public IntentSender(IIntentSender target) {
    364         mTarget = target;
    365     }
    366 
    367     /** @hide */
    368     public IntentSender(IBinder target) {
    369         mTarget = IIntentSender.Stub.asInterface(target);
    370     }
    371 }
    372