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