blob: bfd1a43d36be85e6cc48f47cae46ae58c0f4ef44 [file] [log] [blame]
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001/*
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
17package android.content;
18
Mathew Inwood5c0d3542018-08-14 13:54:31 +010019import android.annotation.UnsupportedAppUsage;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080020import android.app.ActivityManager;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070021import android.os.Bundle;
22import android.os.RemoteException;
23import android.os.Handler;
24import android.os.IBinder;
25import android.os.Parcel;
26import android.os.Parcelable;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070027import android.os.UserHandle;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070028import 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 *
Dianne Hackborn7f205432009-07-28 00:13:47 -070054 * <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()}.
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070057 */
58public class IntentSender implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +010059 @UnsupportedAppUsage
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070060 private final IIntentSender mTarget;
Dianne Hackborn98305522017-05-05 17:53:53 -070061 IBinder mWhitelistToken;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070062
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 }
Dianne Hackborn20e80982012-08-31 19:00:44 -0700116 public void performReceive(Intent intent, int resultCode, String data,
117 Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700118 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 {
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700157 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 {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700189 try {
190 String resolvedType = intent != null ?
191 intent.resolveTypeIfNeeded(context.getContentResolver())
192 : null;
Dianne Hackborn98305522017-05-05 17:53:53 -0700193 int res = ActivityManager.getService().sendIntentSender(mTarget, mWhitelistToken,
Dianne Hackborn0c4e6a82016-05-13 17:37:08 -0700194 code, intent, resolvedType,
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700195 onFinished != null
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700196 ? new FinishedDispatcher(this, onFinished, handler)
197 : null,
Dianne Hackborna750a632015-06-16 17:18:23 -0700198 requiredPermission, null);
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700199 if (res < 0) {
200 throw new SendIntentException();
201 }
202 } catch (RemoteException e) {
203 throw new SendIntentException();
204 }
205 }
206
207 /**
Dianne Hackborn8832c182012-09-17 17:20:24 -0700208 * @deprecated Renamed to {@link #getCreatorPackage()}.
209 */
210 @Deprecated
211 public String getTargetPackage() {
212 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800213 return ActivityManager.getService()
Dianne Hackborn8832c182012-09-17 17:20:24 -0700214 .getPackageForIntentSender(mTarget);
215 } catch (RemoteException e) {
216 // Should never happen.
217 return null;
218 }
219 }
220
221 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700222 * 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 */
Dianne Hackborn8832c182012-09-17 17:20:24 -0700230 public String getCreatorPackage() {
Dianne Hackborn860755f2010-06-03 18:47:52 -0700231 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800232 return ActivityManager.getService()
Dianne Hackborn860755f2010-06-03 18:47:52 -0700233 .getPackageForIntentSender(mTarget);
234 } catch (RemoteException e) {
235 // Should never happen.
236 return null;
237 }
238 }
239
240 /**
Dianne Hackbornc7501272012-08-14 18:05:05 -0700241 * 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 */
Dianne Hackborn8832c182012-09-17 17:20:24 -0700249 public int getCreatorUid() {
Dianne Hackbornc7501272012-08-14 18:05:05 -0700250 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800251 return ActivityManager.getService()
Dianne Hackbornc7501272012-08-14 18:05:05 -0700252 .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
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700262 * sending the Intent. The returned UserHandle is supplied by the system, so
Dianne Hackbornc7501272012-08-14 18:05:05 -0700263 * 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 *
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700267 * @return The user handle of the PendingIntent, or null if there is
Dianne Hackbornc7501272012-08-14 18:05:05 -0700268 * none associated with it.
269 */
Dianne Hackborn8832c182012-09-17 17:20:24 -0700270 public UserHandle getCreatorUserHandle() {
Dianne Hackbornc7501272012-08-14 18:05:05 -0700271 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800272 int uid = ActivityManager.getService()
Dianne Hackbornc7501272012-08-14 18:05:05 -0700273 .getUidForIntentSender(mTarget);
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700274 return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
Dianne Hackbornc7501272012-08-14 18:05:05 -0700275 } catch (RemoteException e) {
276 // Should never happen.
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700277 return null;
Dianne Hackbornc7501272012-08-14 18:05:05 -0700278 }
279 }
280
281 /**
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700282 * 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
Dianne Hackborn7f205432009-07-28 00:13:47 -0700360 /** @hide */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100361 @UnsupportedAppUsage
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700362 public IIntentSender getTarget() {
363 return mTarget;
364 }
365
366 /** @hide */
Dianne Hackborn3e6e3852017-05-19 16:12:08 -0700367 public IBinder getWhitelistToken() {
368 return mWhitelistToken;
369 }
370
371 /** @hide */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100372 @UnsupportedAppUsage
Dianne Hackborn7f205432009-07-28 00:13:47 -0700373 public IntentSender(IIntentSender target) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700374 mTarget = target;
375 }
376
Dianne Hackborn7f205432009-07-28 00:13:47 -0700377 /** @hide */
Dianne Hackborn98305522017-05-05 17:53:53 -0700378 public IntentSender(IIntentSender target, IBinder whitelistToken) {
379 mTarget = target;
380 mWhitelistToken = whitelistToken;
381 }
382
383 /** @hide */
Dianne Hackborn7f205432009-07-28 00:13:47 -0700384 public IntentSender(IBinder target) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -0700385 mTarget = IIntentSender.Stub.asInterface(target);
386 }
387}