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 static android.app.ActivityManager.START_SUCCESS;
     20 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
     21 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
     22 
     23 import android.app.ActivityManager;
     24 import android.app.ActivityOptions;
     25 import android.content.IIntentSender;
     26 import android.content.IIntentReceiver;
     27 import android.app.PendingIntent;
     28 import android.content.Intent;
     29 import android.os.Binder;
     30 import android.os.Bundle;
     31 import android.os.IBinder;
     32 import android.os.RemoteCallbackList;
     33 import android.os.RemoteException;
     34 import android.os.TransactionTooLargeException;
     35 import android.os.UserHandle;
     36 import android.util.ArrayMap;
     37 import android.util.Slog;
     38 import android.util.TimeUtils;
     39 
     40 import com.android.internal.os.IResultReceiver;
     41 
     42 import java.io.PrintWriter;
     43 import java.lang.ref.WeakReference;
     44 import java.util.Objects;
     45 
     46 final class PendingIntentRecord extends IIntentSender.Stub {
     47     private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM;
     48 
     49     final ActivityManagerService owner;
     50     final Key key;
     51     final int uid;
     52     final WeakReference<PendingIntentRecord> ref;
     53     boolean sent = false;
     54     boolean canceled = false;
     55     private ArrayMap<IBinder, Long> whitelistDuration;
     56     private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
     57 
     58     String stringName;
     59     String lastTagPrefix;
     60     String lastTag;
     61 
     62     final static class Key {
     63         final int type;
     64         final String packageName;
     65         final ActivityRecord activity;
     66         final String who;
     67         final int requestCode;
     68         final Intent requestIntent;
     69         final String requestResolvedType;
     70         final SafeActivityOptions options;
     71         Intent[] allIntents;
     72         String[] allResolvedTypes;
     73         final int flags;
     74         final int hashCode;
     75         final int userId;
     76 
     77         private static final int ODD_PRIME_NUMBER = 37;
     78 
     79         Key(int _t, String _p, ActivityRecord _a, String _w,
     80                 int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId) {
     81             type = _t;
     82             packageName = _p;
     83             activity = _a;
     84             who = _w;
     85             requestCode = _r;
     86             requestIntent = _i != null ? _i[_i.length-1] : null;
     87             requestResolvedType = _it != null ? _it[_it.length-1] : null;
     88             allIntents = _i;
     89             allResolvedTypes = _it;
     90             flags = _f;
     91             options = _o;
     92             userId = _userId;
     93 
     94             int hash = 23;
     95             hash = (ODD_PRIME_NUMBER*hash) + _f;
     96             hash = (ODD_PRIME_NUMBER*hash) + _r;
     97             hash = (ODD_PRIME_NUMBER*hash) + _userId;
     98             if (_w != null) {
     99                 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
    100             }
    101             if (_a != null) {
    102                 hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode();
    103             }
    104             if (requestIntent != null) {
    105                 hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode();
    106             }
    107             if (requestResolvedType != null) {
    108                 hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode();
    109             }
    110             hash = (ODD_PRIME_NUMBER*hash) + (_p != null ? _p.hashCode() : 0);
    111             hash = (ODD_PRIME_NUMBER*hash) + _t;
    112             hashCode = hash;
    113             //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x"
    114             //        + Integer.toHexString(hashCode));
    115         }
    116 
    117         public boolean equals(Object otherObj) {
    118             if (otherObj == null) {
    119                 return false;
    120             }
    121             try {
    122                 Key other = (Key)otherObj;
    123                 if (type != other.type) {
    124                     return false;
    125                 }
    126                 if (userId != other.userId){
    127                     return false;
    128                 }
    129                 if (!Objects.equals(packageName, other.packageName)) {
    130                     return false;
    131                 }
    132                 if (activity != other.activity) {
    133                     return false;
    134                 }
    135                 if (!Objects.equals(who, other.who)) {
    136                     return false;
    137                 }
    138                 if (requestCode != other.requestCode) {
    139                     return false;
    140                 }
    141                 if (requestIntent != other.requestIntent) {
    142                     if (requestIntent != null) {
    143                         if (!requestIntent.filterEquals(other.requestIntent)) {
    144                             return false;
    145                         }
    146                     } else if (other.requestIntent != null) {
    147                         return false;
    148                     }
    149                 }
    150                 if (!Objects.equals(requestResolvedType, other.requestResolvedType)) {
    151                     return false;
    152                 }
    153                 if (flags != other.flags) {
    154                     return false;
    155                 }
    156                 return true;
    157             } catch (ClassCastException e) {
    158             }
    159             return false;
    160         }
    161 
    162         public int hashCode() {
    163             return hashCode;
    164         }
    165 
    166         public String toString() {
    167             return "Key{" + typeName() + " pkg=" + packageName
    168                 + " intent="
    169                 + (requestIntent != null
    170                         ? requestIntent.toShortString(false, true, false, false) : "<null>")
    171                 + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
    172         }
    173 
    174         String typeName() {
    175             switch (type) {
    176                 case ActivityManager.INTENT_SENDER_ACTIVITY:
    177                     return "startActivity";
    178                 case ActivityManager.INTENT_SENDER_BROADCAST:
    179                     return "broadcastIntent";
    180                 case ActivityManager.INTENT_SENDER_SERVICE:
    181                     return "startService";
    182                 case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
    183                     return "startForegroundService";
    184                 case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
    185                     return "activityResult";
    186             }
    187             return Integer.toString(type);
    188         }
    189     }
    190 
    191     PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) {
    192         owner = _owner;
    193         key = _k;
    194         uid = _u;
    195         ref = new WeakReference<PendingIntentRecord>(this);
    196     }
    197 
    198     void setWhitelistDurationLocked(IBinder whitelistToken, long duration) {
    199         if (duration > 0) {
    200             if (whitelistDuration == null) {
    201                 whitelistDuration = new ArrayMap<>();
    202             }
    203             whitelistDuration.put(whitelistToken, duration);
    204         } else if (whitelistDuration != null) {
    205             whitelistDuration.remove(whitelistToken);
    206             if (whitelistDuration.size() <= 0) {
    207                 whitelistDuration = null;
    208             }
    209 
    210         }
    211         this.stringName = null;
    212     }
    213 
    214     public void registerCancelListenerLocked(IResultReceiver receiver) {
    215         if (mCancelCallbacks == null) {
    216             mCancelCallbacks = new RemoteCallbackList<>();
    217         }
    218         mCancelCallbacks.register(receiver);
    219     }
    220 
    221     public void unregisterCancelListenerLocked(IResultReceiver receiver) {
    222         if (mCancelCallbacks == null) {
    223             return; // Already unregistered or detached.
    224         }
    225         mCancelCallbacks.unregister(receiver);
    226         if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) {
    227             mCancelCallbacks = null;
    228         }
    229     }
    230 
    231     public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() {
    232         RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks;
    233         mCancelCallbacks = null;
    234         return listeners;
    235     }
    236 
    237     public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
    238             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
    239         sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
    240                 requiredPermission, null, null, 0, 0, 0, options);
    241     }
    242 
    243     public int sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken,
    244             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
    245         return sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
    246                 requiredPermission, null, null, 0, 0, 0, options);
    247     }
    248 
    249     int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
    250             IIntentReceiver finishedReceiver,
    251             String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
    252             int flagsMask, int flagsValues, Bundle options) {
    253         if (intent != null) intent.setDefusable(true);
    254         if (options != null) options.setDefusable(true);
    255 
    256         synchronized (owner) {
    257             if (!canceled) {
    258                 sent = true;
    259                 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
    260                     owner.cancelIntentSenderLocked(this, true);
    261                 }
    262 
    263                 Intent finalIntent = key.requestIntent != null
    264                         ? new Intent(key.requestIntent) : new Intent();
    265 
    266                 final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
    267                 if (!immutable) {
    268                     if (intent != null) {
    269                         int changes = finalIntent.fillIn(intent, key.flags);
    270                         if ((changes & Intent.FILL_IN_DATA) == 0) {
    271                             resolvedType = key.requestResolvedType;
    272                         }
    273                     } else {
    274                         resolvedType = key.requestResolvedType;
    275                     }
    276                     flagsMask &= ~Intent.IMMUTABLE_FLAGS;
    277                     flagsValues &= flagsMask;
    278                     finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
    279                 } else {
    280                     resolvedType = key.requestResolvedType;
    281                 }
    282 
    283                 final int callingUid = Binder.getCallingUid();
    284                 final int callingPid = Binder.getCallingPid();
    285 
    286                 // Extract options before clearing calling identity
    287                 SafeActivityOptions mergedOptions = key.options;
    288                 if (mergedOptions == null) {
    289                     mergedOptions = SafeActivityOptions.fromBundle(options);
    290                 } else {
    291                     mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options));
    292                 }
    293 
    294                 final long origId = Binder.clearCallingIdentity();
    295 
    296                 if (whitelistDuration != null) {
    297                     Long duration = whitelistDuration.get(whitelistToken);
    298                     if (duration != null) {
    299                         int procState = owner.getUidState(callingUid);
    300                         if (!ActivityManager.isProcStateBackground(procState)) {
    301                             StringBuilder tag = new StringBuilder(64);
    302                             tag.append("pendingintent:");
    303                             UserHandle.formatUid(tag, callingUid);
    304                             tag.append(":");
    305                             if (finalIntent.getAction() != null) {
    306                                 tag.append(finalIntent.getAction());
    307                             } else if (finalIntent.getComponent() != null) {
    308                                 finalIntent.getComponent().appendShortString(tag);
    309                             } else if (finalIntent.getData() != null) {
    310                                 tag.append(finalIntent.getData());
    311                             }
    312                             owner.tempWhitelistForPendingIntentLocked(callingPid,
    313                                     callingUid, uid, duration, tag.toString());
    314                         } else {
    315                             Slog.w(TAG, "Not doing whitelist " + this + ": caller state="
    316                                     + procState);
    317                         }
    318                     }
    319                 }
    320 
    321                 boolean sendFinish = finishedReceiver != null;
    322                 int userId = key.userId;
    323                 if (userId == UserHandle.USER_CURRENT) {
    324                     userId = owner.mUserController.getCurrentOrTargetUserId();
    325                 }
    326                 int res = START_SUCCESS;
    327                 switch (key.type) {
    328                     case ActivityManager.INTENT_SENDER_ACTIVITY:
    329                         try {
    330                             // Note when someone has a pending intent, even from different
    331                             // users, then there's no need to ensure the calling user matches
    332                             // the target user, so validateIncomingUser is always false below.
    333 
    334                             if (key.allIntents != null && key.allIntents.length > 1) {
    335                                 Intent[] allIntents = new Intent[key.allIntents.length];
    336                                 String[] allResolvedTypes = new String[key.allIntents.length];
    337                                 System.arraycopy(key.allIntents, 0, allIntents, 0,
    338                                         key.allIntents.length);
    339                                 if (key.allResolvedTypes != null) {
    340                                     System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
    341                                             key.allResolvedTypes.length);
    342                                 }
    343                                 allIntents[allIntents.length-1] = finalIntent;
    344                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
    345 
    346                                 res = owner.getActivityStartController().startActivitiesInPackage(
    347                                         uid, key.packageName, allIntents, allResolvedTypes,
    348                                         resultTo, mergedOptions, userId,
    349                                         false /* validateIncomingUser */);
    350                             } else {
    351                                 res = owner.getActivityStartController().startActivityInPackage(uid,
    352                                         callingPid, callingUid, key.packageName, finalIntent,
    353                                         resolvedType, resultTo, resultWho, requestCode, 0,
    354                                         mergedOptions, userId, null, "PendingIntentRecord",
    355                                         false /* validateIncomingUser */);
    356                             }
    357                         } catch (RuntimeException e) {
    358                             Slog.w(TAG, "Unable to send startActivity intent", e);
    359                         }
    360                         break;
    361                     case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
    362                         final ActivityStack stack = key.activity.getStack();
    363                         if (stack != null) {
    364                             stack.sendActivityResultLocked(-1, key.activity, key.who,
    365                                     key.requestCode, code, finalIntent);
    366                         }
    367                         break;
    368                     case ActivityManager.INTENT_SENDER_BROADCAST:
    369                         try {
    370                             // If a completion callback has been requested, require
    371                             // that the broadcast be delivered synchronously
    372                             int sent = owner.broadcastIntentInPackage(key.packageName, uid,
    373                                     finalIntent, resolvedType, finishedReceiver, code, null, null,
    374                                     requiredPermission, options, (finishedReceiver != null),
    375                                     false, userId);
    376                             if (sent == ActivityManager.BROADCAST_SUCCESS) {
    377                                 sendFinish = false;
    378                             }
    379                         } catch (RuntimeException e) {
    380                             Slog.w(TAG, "Unable to send startActivity intent", e);
    381                         }
    382                         break;
    383                     case ActivityManager.INTENT_SENDER_SERVICE:
    384                     case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
    385                         try {
    386                             owner.startServiceInPackage(uid, finalIntent, resolvedType,
    387                                     key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
    388                                     key.packageName, userId);
    389                         } catch (RuntimeException e) {
    390                             Slog.w(TAG, "Unable to send startService intent", e);
    391                         } catch (TransactionTooLargeException e) {
    392                             res = ActivityManager.START_CANCELED;
    393                         }
    394                         break;
    395                 }
    396 
    397                 if (sendFinish && res != ActivityManager.START_CANCELED) {
    398                     try {
    399                         finishedReceiver.performReceive(new Intent(finalIntent), 0,
    400                                 null, null, false, false, key.userId);
    401                     } catch (RemoteException e) {
    402                     }
    403                 }
    404 
    405                 Binder.restoreCallingIdentity(origId);
    406 
    407                 return res;
    408             }
    409         }
    410         return ActivityManager.START_CANCELED;
    411     }
    412 
    413     @Override
    414     protected void finalize() throws Throwable {
    415         try {
    416             if (!canceled) {
    417                 owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
    418                         ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
    419             }
    420         } finally {
    421             super.finalize();
    422         }
    423     }
    424 
    425     public void completeFinalize() {
    426         synchronized(owner) {
    427             WeakReference<PendingIntentRecord> current =
    428                     owner.mIntentSenderRecords.get(key);
    429             if (current == ref) {
    430                 owner.mIntentSenderRecords.remove(key);
    431             }
    432         }
    433     }
    434 
    435     void dump(PrintWriter pw, String prefix) {
    436         pw.print(prefix); pw.print("uid="); pw.print(uid);
    437                 pw.print(" packageName="); pw.print(key.packageName);
    438                 pw.print(" type="); pw.print(key.typeName());
    439                 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
    440         if (key.activity != null || key.who != null) {
    441             pw.print(prefix); pw.print("activity="); pw.print(key.activity);
    442                     pw.print(" who="); pw.println(key.who);
    443         }
    444         if (key.requestCode != 0 || key.requestResolvedType != null) {
    445             pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
    446                     pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
    447         }
    448         if (key.requestIntent != null) {
    449             pw.print(prefix); pw.print("requestIntent=");
    450                     pw.println(key.requestIntent.toShortString(false, true, true, true));
    451         }
    452         if (sent || canceled) {
    453             pw.print(prefix); pw.print("sent="); pw.print(sent);
    454                     pw.print(" canceled="); pw.println(canceled);
    455         }
    456         if (whitelistDuration != null) {
    457             pw.print(prefix);
    458             pw.print("whitelistDuration=");
    459             for (int i = 0; i < whitelistDuration.size(); i++) {
    460                 if (i != 0) {
    461                     pw.print(", ");
    462                 }
    463                 pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
    464                 pw.print(":");
    465                 TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw);
    466             }
    467             pw.println();
    468         }
    469         if (mCancelCallbacks != null) {
    470             pw.print(prefix); pw.println("mCancelCallbacks:");
    471             for (int i = 0; i < mCancelCallbacks.getRegisteredCallbackCount(); i++) {
    472                 pw.print(prefix); pw.print("  #"); pw.print(i); pw.print(": ");
    473                 pw.println(mCancelCallbacks.getRegisteredCallbackItem(i));
    474             }
    475         }
    476     }
    477 
    478     public String toString() {
    479         if (stringName != null) {
    480             return stringName;
    481         }
    482         StringBuilder sb = new StringBuilder(128);
    483         sb.append("PendingIntentRecord{");
    484         sb.append(Integer.toHexString(System.identityHashCode(this)));
    485         sb.append(' ');
    486         sb.append(key.packageName);
    487         sb.append(' ');
    488         sb.append(key.typeName());
    489         if (whitelistDuration != null) {
    490             sb.append( " (whitelist: ");
    491             for (int i = 0; i < whitelistDuration.size(); i++) {
    492                 if (i != 0) {
    493                     sb.append(",");
    494                 }
    495                 sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
    496                 sb.append(":");
    497                 TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb);
    498             }
    499             sb.append(")");
    500         }
    501         sb.append('}');
    502         return stringName = sb.toString();
    503     }
    504 }
    505