OSDN Git Service

Handle null packageName in PendingIntentRecord
[android-x86/frameworks-base.git] / services / core / java / com / android / server / am / PendingIntentRecord.java
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 com.android.server.am;
18
19 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
20 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
21
22 import android.app.ActivityManager;
23 import android.app.IActivityContainer;
24 import android.content.IIntentSender;
25 import android.content.IIntentReceiver;
26 import android.app.PendingIntent;
27 import android.content.Intent;
28 import android.os.Binder;
29 import android.os.Bundle;
30 import android.os.IBinder;
31 import android.os.RemoteException;
32 import android.os.TransactionTooLargeException;
33 import android.os.UserHandle;
34 import android.util.Slog;
35 import android.util.TimeUtils;
36
37 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
38
39 import java.io.PrintWriter;
40 import java.lang.ref.WeakReference;
41 import java.util.Objects;
42
43 final class PendingIntentRecord extends IIntentSender.Stub {
44     private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM;
45
46     final ActivityManagerService owner;
47     final Key key;
48     final int uid;
49     final WeakReference<PendingIntentRecord> ref;
50     boolean sent = false;
51     boolean canceled = false;
52     private long whitelistDuration = 0;
53
54     String stringName;
55     String lastTagPrefix;
56     String lastTag;
57
58     final static class Key {
59         final int type;
60         final String packageName;
61         final ActivityRecord activity;
62         final String who;
63         final int requestCode;
64         final Intent requestIntent;
65         final String requestResolvedType;
66         final Bundle options;
67         Intent[] allIntents;
68         String[] allResolvedTypes;
69         final int flags;
70         final int hashCode;
71         final int userId;
72
73         private static final int ODD_PRIME_NUMBER = 37;
74
75         Key(int _t, String _p, ActivityRecord _a, String _w,
76                 int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) {
77             type = _t;
78             packageName = _p;
79             activity = _a;
80             who = _w;
81             requestCode = _r;
82             requestIntent = _i != null ? _i[_i.length-1] : null;
83             requestResolvedType = _it != null ? _it[_it.length-1] : null;
84             allIntents = _i;
85             allResolvedTypes = _it;
86             flags = _f;
87             options = _o;
88             userId = _userId;
89
90             int hash = 23;
91             hash = (ODD_PRIME_NUMBER*hash) + _f;
92             hash = (ODD_PRIME_NUMBER*hash) + _r;
93             hash = (ODD_PRIME_NUMBER*hash) + _userId;
94             if (_w != null) {
95                 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
96             }
97             if (_a != null) {
98                 hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode();
99             }
100             if (requestIntent != null) {
101                 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode();
102             }
103             if (requestResolvedType != null) {
104                 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode();
105             }
106             hash = (ODD_PRIME_NUMBER*hash) + (_p != null ? _p.hashCode() : 0);
107             hash = (ODD_PRIME_NUMBER*hash) + _t;
108             hashCode = hash;
109             //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x"
110             //        + Integer.toHexString(hashCode));
111         }
112
113         public boolean equals(Object otherObj) {
114             if (otherObj == null) {
115                 return false;
116             }
117             try {
118                 Key other = (Key)otherObj;
119                 if (type != other.type) {
120                     return false;
121                 }
122                 if (userId != other.userId){
123                     return false;
124                 }
125                 if (!Objects.equals(packageName, other.packageName)) {
126                     return false;
127                 }
128                 if (activity != other.activity) {
129                     return false;
130                 }
131                 if (!Objects.equals(who, other.who)) {
132                     return false;
133                 }
134                 if (requestCode != other.requestCode) {
135                     return false;
136                 }
137                 if (requestIntent != other.requestIntent) {
138                     if (requestIntent != null) {
139                         if (!requestIntent.filterEquals(other.requestIntent)) {
140                             return false;
141                         }
142                     } else if (other.requestIntent != null) {
143                         return false;
144                     }
145                 }
146                 if (!Objects.equals(requestResolvedType, other.requestResolvedType)) {
147                     return false;
148                 }
149                 if (flags != other.flags) {
150                     return false;
151                 }
152                 return true;
153             } catch (ClassCastException e) {
154             }
155             return false;
156         }
157
158         public int hashCode() {
159             return hashCode;
160         }
161
162         public String toString() {
163             return "Key{" + typeName() + " pkg=" + packageName
164                 + " intent="
165                 + (requestIntent != null
166                         ? requestIntent.toShortString(false, true, false, false) : "<null>")
167                 + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
168         }
169
170         String typeName() {
171             switch (type) {
172                 case ActivityManager.INTENT_SENDER_ACTIVITY:
173                     return "startActivity";
174                 case ActivityManager.INTENT_SENDER_BROADCAST:
175                     return "broadcastIntent";
176                 case ActivityManager.INTENT_SENDER_SERVICE:
177                     return "startService";
178                 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
179                     return "activityResult";
180             }
181             return Integer.toString(type);
182         }
183     }
184
185     PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) {
186         owner = _owner;
187         key = _k;
188         uid = _u;
189         ref = new WeakReference<PendingIntentRecord>(this);
190     }
191
192     void setWhitelistDuration(long duration) {
193         this.whitelistDuration = duration;
194         this.stringName = null;
195     }
196
197     public void send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
198             String requiredPermission, Bundle options) {
199         sendInner(code, intent, resolvedType, finishedReceiver,
200                 requiredPermission, null, null, 0, 0, 0, options, null);
201     }
202
203     public int sendWithResult(int code, Intent intent, String resolvedType,
204             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
205         return sendInner(code, intent, resolvedType, finishedReceiver,
206                 requiredPermission, null, null, 0, 0, 0, options, null);
207     }
208
209     int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
210             String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
211             int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
212         if (intent != null) intent.setDefusable(true);
213         if (options != null) options.setDefusable(true);
214
215         if (whitelistDuration > 0 && !canceled) {
216             // Must call before acquiring the lock. It's possible the method return before sending
217             // the intent due to some validations inside the lock, in which case the UID shouldn't
218             // be whitelisted, but since the whitelist is temporary, that would be ok.
219             owner.tempWhitelistAppForPowerSave(Binder.getCallingPid(), Binder.getCallingUid(), uid,
220                     whitelistDuration);
221         }
222
223         synchronized (owner) {
224             final ActivityContainer activityContainer = (ActivityContainer)container;
225             if (activityContainer != null && activityContainer.mParentActivity != null &&
226                     activityContainer.mParentActivity.state
227                             != ActivityStack.ActivityState.RESUMED) {
228                 // Cannot start a child activity if the parent is not resumed.
229                 return ActivityManager.START_CANCELED;
230             }
231             if (!canceled) {
232                 sent = true;
233                 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
234                     owner.cancelIntentSenderLocked(this, true);
235                     canceled = true;
236                 }
237
238                 Intent finalIntent = key.requestIntent != null
239                         ? new Intent(key.requestIntent) : new Intent();
240
241                 final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
242                 if (!immutable) {
243                     if (intent != null) {
244                         int changes = finalIntent.fillIn(intent, key.flags);
245                         if ((changes & Intent.FILL_IN_DATA) == 0) {
246                             resolvedType = key.requestResolvedType;
247                         }
248                     } else {
249                         resolvedType = key.requestResolvedType;
250                     }
251                     flagsMask &= ~Intent.IMMUTABLE_FLAGS;
252                     flagsValues &= flagsMask;
253                     finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
254                 } else {
255                     resolvedType = key.requestResolvedType;
256                 }
257
258                 final long origId = Binder.clearCallingIdentity();
259
260                 boolean sendFinish = finishedReceiver != null;
261                 int userId = key.userId;
262                 if (userId == UserHandle.USER_CURRENT) {
263                     userId = owner.mUserController.getCurrentOrTargetUserIdLocked();
264                 }
265                 int res = 0;
266                 switch (key.type) {
267                     case ActivityManager.INTENT_SENDER_ACTIVITY:
268                         if (options == null) {
269                             options = key.options;
270                         } else if (key.options != null) {
271                             Bundle opts = new Bundle(key.options);
272                             opts.putAll(options);
273                             options = opts;
274                         }
275                         try {
276                             if (key.allIntents != null && key.allIntents.length > 1) {
277                                 Intent[] allIntents = new Intent[key.allIntents.length];
278                                 String[] allResolvedTypes = new String[key.allIntents.length];
279                                 System.arraycopy(key.allIntents, 0, allIntents, 0,
280                                         key.allIntents.length);
281                                 if (key.allResolvedTypes != null) {
282                                     System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
283                                             key.allResolvedTypes.length);
284                                 }
285                                 allIntents[allIntents.length-1] = finalIntent;
286                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
287                                 owner.startActivitiesInPackage(uid, key.packageName, allIntents,
288                                         allResolvedTypes, resultTo, options, userId);
289                             } else {
290                                 owner.startActivityInPackage(uid, key.packageName, finalIntent,
291                                         resolvedType, resultTo, resultWho, requestCode, 0,
292                                         options, userId, container, null);
293                             }
294                         } catch (RuntimeException e) {
295                             Slog.w(TAG, "Unable to send startActivity intent", e);
296                         }
297                         break;
298                     case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
299                         if (key.activity.task.stack != null) {
300                             key.activity.task.stack.sendActivityResultLocked(-1, key.activity,
301                                     key.who, key.requestCode, code, finalIntent);
302                         }
303                         break;
304                     case ActivityManager.INTENT_SENDER_BROADCAST:
305                         try {
306                             // If a completion callback has been requested, require
307                             // that the broadcast be delivered synchronously
308                             int sent = owner.broadcastIntentInPackage(key.packageName, uid,
309                                     finalIntent, resolvedType, finishedReceiver, code, null, null,
310                                     requiredPermission, options, (finishedReceiver != null),
311                                     false, userId);
312                             if (sent == ActivityManager.BROADCAST_SUCCESS) {
313                                 sendFinish = false;
314                             }
315                         } catch (RuntimeException e) {
316                             Slog.w(TAG, "Unable to send startActivity intent", e);
317                         }
318                         break;
319                     case ActivityManager.INTENT_SENDER_SERVICE:
320                         try {
321                             owner.startServiceInPackage(uid, finalIntent,
322                                     resolvedType, key.packageName, userId);
323                         } catch (RuntimeException e) {
324                             Slog.w(TAG, "Unable to send startService intent", e);
325                         } catch (TransactionTooLargeException e) {
326                             res = ActivityManager.START_CANCELED;
327                         }
328                         break;
329                 }
330
331                 if (sendFinish && res != ActivityManager.START_CANCELED) {
332                     try {
333                         finishedReceiver.performReceive(new Intent(finalIntent), 0,
334                                 null, null, false, false, key.userId);
335                     } catch (RemoteException e) {
336                     }
337                 }
338
339                 Binder.restoreCallingIdentity(origId);
340
341                 return res;
342             }
343         }
344         return ActivityManager.START_CANCELED;
345     }
346
347     @Override
348     protected void finalize() throws Throwable {
349         try {
350             if (!canceled) {
351                 owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
352                         ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
353             }
354         } finally {
355             super.finalize();
356         }
357     }
358
359     public void completeFinalize() {
360         synchronized(owner) {
361             WeakReference<PendingIntentRecord> current =
362                     owner.mIntentSenderRecords.get(key);
363             if (current == ref) {
364                 owner.mIntentSenderRecords.remove(key);
365             }
366         }
367     }
368
369     void dump(PrintWriter pw, String prefix) {
370         pw.print(prefix); pw.print("uid="); pw.print(uid);
371                 pw.print(" packageName="); pw.print(key.packageName);
372                 pw.print(" type="); pw.print(key.typeName());
373                 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
374         if (key.activity != null || key.who != null) {
375             pw.print(prefix); pw.print("activity="); pw.print(key.activity);
376                     pw.print(" who="); pw.println(key.who);
377         }
378         if (key.requestCode != 0 || key.requestResolvedType != null) {
379             pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
380                     pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
381         }
382         if (key.requestIntent != null) {
383             pw.print(prefix); pw.print("requestIntent=");
384                     pw.println(key.requestIntent.toShortString(false, true, true, true));
385         }
386         if (sent || canceled) {
387             pw.print(prefix); pw.print("sent="); pw.print(sent);
388                     pw.print(" canceled="); pw.println(canceled);
389         }
390         if (whitelistDuration != 0) {
391             pw.print(prefix);
392             pw.print("whitelistDuration=");
393             TimeUtils.formatDuration(whitelistDuration, pw);
394             pw.println();
395         }
396     }
397
398     public String toString() {
399         if (stringName != null) {
400             return stringName;
401         }
402         StringBuilder sb = new StringBuilder(128);
403         sb.append("PendingIntentRecord{");
404         sb.append(Integer.toHexString(System.identityHashCode(this)));
405         sb.append(' ');
406         sb.append(key.packageName);
407         sb.append(' ');
408         sb.append(key.typeName());
409         if (whitelistDuration > 0) {
410             sb.append( " (whitelist: ");
411             TimeUtils.formatDuration(whitelistDuration, sb);
412             sb.append(")");
413         }
414         sb.append('}');
415         return stringName = sb.toString();
416     }
417 }