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