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