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 {
SendIntentException()68         public SendIntentException() {
69         }
70 
SendIntentException(String name)71         public SendIntentException(String name) {
72             super(name);
73         }
74 
SendIntentException(Exception cause)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          */
onSendFinished(IntentSender IntentSender, Intent intent, int resultCode, String resultData, Bundle resultExtras)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;
FinishedDispatcher(IntentSender pi, OnFinished who, Handler handler)111         FinishedDispatcher(IntentSender pi, OnFinished who, Handler handler) {
112             mIntentSender = pi;
113             mWho = who;
114             mHandler = handler;
115         }
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean serialized, boolean sticky, int sendingUser)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         }
run()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      */
sendIntent(Context context, int code, Intent intent, OnFinished onFinished, Handler handler)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      */
sendIntent(Context context, int code, Intent intent, OnFinished onFinished, Handler handler, String requiredPermission)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
getTargetPackage()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      */
getCreatorPackage()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      */
getCreatorUid()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      */
getCreatorUserHandle()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
equals(Object otherObj)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
hashCode()296     public int hashCode() {
297         return mTarget.asBinder().hashCode();
298     }
299 
300     @Override
toString()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 
describeContents()311     public int describeContents() {
312         return 0;
313     }
314 
writeToParcel(Parcel out, int flags)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      */
writeIntentSenderOrNullToParcel(IntentSender sender, Parcel out)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      */
readIntentSenderOrNullFromParcel(Parcel in)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
getTarget()362     public IIntentSender getTarget() {
363         return mTarget;
364     }
365 
366     /** @hide */
getWhitelistToken()367     public IBinder getWhitelistToken() {
368         return mWhitelistToken;
369     }
370 
371     /** @hide */
372     @UnsupportedAppUsage
IntentSender(IIntentSender target)373     public IntentSender(IIntentSender target) {
374         mTarget = target;
375     }
376 
377     /** @hide */
IntentSender(IIntentSender target, IBinder whitelistToken)378     public IntentSender(IIntentSender target, IBinder whitelistToken) {
379         mTarget = target;
380         mWhitelistToken = whitelistToken;
381     }
382 
383     /** @hide */
IntentSender(IBinder target)384     public IntentSender(IBinder target) {
385         mTarget = IIntentSender.Stub.asInterface(target);
386     }
387 }
388