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.annotation.UnsupportedAppUsage;
     20 import android.app.ActivityManager;
     21 import android.os.Bundle;
     22 import android.os.RemoteException;
     23 import android.os.Handler;
     24 import android.os.IBinder;
     25 import android.os.Parcel;
     26 import android.os.Parcelable;
     27 import android.os.UserHandle;
     28 import android.util.AndroidException;
     29 
     30 
     31 /**
     32  * A description of an Intent and target action to perform with it.
     33  * The returned object can be
     34  * handed to other applications so that they can perform the action you
     35  * described on your behalf at a later time.
     36  *
     37  * <p>By giving a IntentSender to another application,
     38  * you are granting it the right to perform the operation you have specified
     39  * as if the other application was yourself (with the same permissions and
     40  * identity).  As such, you should be careful about how you build the IntentSender:
     41  * often, for example, the base Intent you supply will have the component
     42  * name explicitly set to one of your own components, to ensure it is ultimately
     43  * sent there and nowhere else.
     44  *
     45  * <p>A IntentSender itself is simply a reference to a token maintained by
     46  * the system describing the original data used to retrieve it.  This means
     47  * that, even if its owning application's process is killed, the
     48  * IntentSender itself will remain usable from other processes that
     49  * have been given it.  If the creating application later re-retrieves the
     50  * same kind of IntentSender (same operation, same Intent action, data,
     51  * categories, and components, and same flags), it will receive a IntentSender
     52  * representing the same token if that is still valid.
     53  *
     54  * <p>Instances of this class can not be made directly, but rather must be
     55  * created from an existing {@link android.app.PendingIntent} with
     56  * {@link android.app.PendingIntent#getIntentSender() PendingIntent.getIntentSender()}.
     57  */
     58 public class IntentSender implements Parcelable {
     59     @UnsupportedAppUsage
     60     private final IIntentSender mTarget;
     61     IBinder mWhitelistToken;
     62 
     63     /**
     64      * Exception thrown when trying to send through a PendingIntent that
     65      * has been canceled or is otherwise no longer able to execute the request.
     66      */
     67     public static class SendIntentException extends AndroidException {
     68         public SendIntentException() {
     69         }
     70 
     71         public SendIntentException(String name) {
     72             super(name);
     73         }
     74 
     75         public SendIntentException(Exception cause) {
     76             super(cause);
     77         }
     78     }
     79 
     80     /**
     81      * Callback interface for discovering when a send operation has
     82      * completed.  Primarily for use with a IntentSender that is
     83      * performing a broadcast, this provides the same information as
     84      * calling {@link Context#sendOrderedBroadcast(Intent, String,
     85      * android.content.BroadcastReceiver, Handler, int, String, Bundle)
     86      * Context.sendBroadcast()} with a final BroadcastReceiver.
     87      */
     88     public interface OnFinished {
     89         /**
     90          * Called when a send operation as completed.
     91          *
     92          * @param IntentSender The IntentSender this operation was sent through.
     93          * @param intent The original Intent that was sent.
     94          * @param resultCode The final result code determined by the send.
     95          * @param resultData The final data collected by a broadcast.
     96          * @param resultExtras The final extras collected by a broadcast.
     97          */
     98         void onSendFinished(IntentSender IntentSender, Intent intent,
     99                 int resultCode, String resultData, Bundle resultExtras);
    100     }
    101 
    102     private static class FinishedDispatcher extends IIntentReceiver.Stub
    103             implements Runnable {
    104         private final IntentSender mIntentSender;
    105         private final OnFinished mWho;
    106         private final Handler mHandler;
    107         private Intent mIntent;
    108         private int mResultCode;
    109         private String mResultData;
    110         private Bundle mResultExtras;
    111         FinishedDispatcher(IntentSender pi, OnFinished who, Handler handler) {
    112             mIntentSender = pi;
    113             mWho = who;
    114             mHandler = handler;
    115         }
    116         public void performReceive(Intent intent, int resultCode, String data,
    117                 Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
    118             mIntent = intent;
    119             mResultCode = resultCode;
    120             mResultData = data;
    121             mResultExtras = extras;
    122             if (mHandler == null) {
    123                 run();
    124             } else {
    125                 mHandler.post(this);
    126             }
    127         }
    128         public void run() {
    129             mWho.onSendFinished(mIntentSender, mIntent, mResultCode,
    130                     mResultData, mResultExtras);
    131         }
    132     }
    133 
    134     /**
    135      * Perform the operation associated with this IntentSender, allowing the
    136      * caller to specify information about the Intent to use and be notified
    137      * when the send has completed.
    138      *
    139      * @param context The Context of the caller.  This may be null if
    140      * <var>intent</var> is also null.
    141      * @param code Result code to supply back to the IntentSender's target.
    142      * @param intent Additional Intent data.  See {@link Intent#fillIn
    143      * Intent.fillIn()} for information on how this is applied to the
    144      * original Intent.  Use null to not modify the original Intent.
    145      * @param onFinished The object to call back on when the send has
    146      * completed, or null for no callback.
    147      * @param handler Handler identifying the thread on which the callback
    148      * should happen.  If null, the callback will happen from the thread
    149      * pool of the process.
    150      *
    151      *
    152      * @throws SendIntentException Throws CanceledIntentException if the IntentSender
    153      * is no longer allowing more intents to be sent through it.
    154      */
    155     public void sendIntent(Context context, int code, Intent intent,
    156             OnFinished onFinished, Handler handler) throws SendIntentException {
    157         sendIntent(context, code, intent, onFinished, handler, null);
    158     }
    159 
    160     /**
    161      * Perform the operation associated with this IntentSender, allowing the
    162      * caller to specify information about the Intent to use and be notified
    163      * when the send has completed.
    164      *
    165      * @param context The Context of the caller.  This may be null if
    166      * <var>intent</var> is also null.
    167      * @param code Result code to supply back to the IntentSender's target.
    168      * @param intent Additional Intent data.  See {@link Intent#fillIn
    169      * Intent.fillIn()} for information on how this is applied to the
    170      * original Intent.  Use null to not modify the original Intent.
    171      * @param onFinished The object to call back on when the send has
    172      * completed, or null for no callback.
    173      * @param handler Handler identifying the thread on which the callback
    174      * should happen.  If null, the callback will happen from the thread
    175      * pool of the process.
    176      * @param requiredPermission Name of permission that a recipient of the PendingIntent
    177      * is required to hold.  This is only valid for broadcast intents, and
    178      * corresponds to the permission argument in
    179      * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
    180      * If null, no permission is required.
    181      *
    182      *
    183      * @throws SendIntentException Throws CanceledIntentException if the IntentSender
    184      * is no longer allowing more intents to be sent through it.
    185      */
    186     public void sendIntent(Context context, int code, Intent intent,
    187             OnFinished onFinished, Handler handler, String requiredPermission)
    188             throws SendIntentException {
    189         try {
    190             String resolvedType = intent != null ?
    191                     intent.resolveTypeIfNeeded(context.getContentResolver())
    192                     : null;
    193             int res = ActivityManager.getService().sendIntentSender(mTarget, mWhitelistToken,
    194                     code, intent, resolvedType,
    195                     onFinished != null
    196                             ? new FinishedDispatcher(this, onFinished, handler)
    197                             : null,
    198                     requiredPermission, null);
    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 ActivityManager.getService()
    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 ActivityManager.getService()
    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 ActivityManager.getService()
    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 = ActivityManager.getService()
    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 @android.annotation.NonNull 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     @UnsupportedAppUsage
    362     public IIntentSender getTarget() {
    363         return mTarget;
    364     }
    365 
    366     /** @hide */
    367     public IBinder getWhitelistToken() {
    368         return mWhitelistToken;
    369     }
    370 
    371     /** @hide */
    372     @UnsupportedAppUsage
    373     public IntentSender(IIntentSender target) {
    374         mTarget = target;
    375     }
    376 
    377     /** @hide */
    378     public IntentSender(IIntentSender target, IBinder whitelistToken) {
    379         mTarget = target;
    380         mWhitelistToken = whitelistToken;
    381     }
    382 
    383     /** @hide */
    384     public IntentSender(IBinder target) {
    385         mTarget = IIntentSender.Stub.asInterface(target);
    386     }
    387 }
    388