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 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.RemoteCallbackList;
     32 import android.os.RemoteException;
     33 import android.os.TransactionTooLargeException;
     34 import android.os.UserHandle;
     35 import android.util.ArrayMap;
     36 import android.util.Slog;
     37 import android.util.TimeUtils;
     38 
     39 import com.android.internal.os.IResultReceiver;
     40 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
     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 Bundle 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, Bundle _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         mCancelCallbacks.unregister(receiver);
    223         if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) {
    224             mCancelCallbacks = null;
    225         }
    226     }
    227 
    228     public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() {
    229         RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks;
    230         mCancelCallbacks = null;
    231         return listeners;
    232     }
    233 
    234     public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
    235             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
    236         sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
    237                 requiredPermission, null, null, 0, 0, 0, options, null);
    238     }
    239 
    240     public int sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken,
    241             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
    242         return sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
    243                 requiredPermission, null, null, 0, 0, 0, options, null);
    244     }
    245 
    246     int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
    247             IIntentReceiver finishedReceiver,
    248             String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
    249             int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
    250         if (intent != null) intent.setDefusable(true);
    251         if (options != null) options.setDefusable(true);
    252 
    253         synchronized (owner) {
    254             final ActivityContainer activityContainer = (ActivityContainer)container;
    255             if (activityContainer != null && activityContainer.mParentActivity != null &&
    256                     activityContainer.mParentActivity.state
    257                             != ActivityStack.ActivityState.RESUMED) {
    258                 // Cannot start a child activity if the parent is not resumed.
    259                 return ActivityManager.START_CANCELED;
    260             }
    261             if (!canceled) {
    262                 sent = true;
    263                 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
    264                     owner.cancelIntentSenderLocked(this, true);
    265                 }
    266 
    267                 Intent finalIntent = key.requestIntent != null
    268                         ? new Intent(key.requestIntent) : new Intent();
    269 
    270                 final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
    271                 if (!immutable) {
    272                     if (intent != null) {
    273                         int changes = finalIntent.fillIn(intent, key.flags);
    274                         if ((changes & Intent.FILL_IN_DATA) == 0) {
    275                             resolvedType = key.requestResolvedType;
    276                         }
    277                     } else {
    278                         resolvedType = key.requestResolvedType;
    279                     }
    280                     flagsMask &= ~Intent.IMMUTABLE_FLAGS;
    281                     flagsValues &= flagsMask;
    282                     finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
    283                 } else {
    284                     resolvedType = key.requestResolvedType;
    285                 }
    286 
    287                 final int callingUid = Binder.getCallingUid();
    288                 final int callingPid = Binder.getCallingPid();
    289 
    290                 final long origId = Binder.clearCallingIdentity();
    291 
    292                 if (whitelistDuration != null) {
    293                     Long duration = whitelistDuration.get(whitelistToken);
    294                     if (duration != null) {
    295                         int procState = owner.getUidState(callingUid);
    296                         if (!ActivityManager.isProcStateBackground(procState)) {
    297                             StringBuilder tag = new StringBuilder(64);
    298                             tag.append("pendingintent:");
    299                             UserHandle.formatUid(tag, callingUid);
    300                             tag.append(":");
    301                             if (finalIntent.getAction() != null) {
    302                                 tag.append(finalIntent.getAction());
    303                             } else if (finalIntent.getComponent() != null) {
    304                                 finalIntent.getComponent().appendShortString(tag);
    305                             } else if (finalIntent.getData() != null) {
    306                                 tag.append(finalIntent.getData());
    307                             }
    308                             owner.tempWhitelistForPendingIntentLocked(callingPid,
    309                                     callingUid, uid, duration, tag.toString());
    310                         } else {
    311                             Slog.w(TAG, "Not doing whitelist " + this + ": caller state="
    312                                     + procState);
    313                         }
    314                     }
    315                 }
    316 
    317                 boolean sendFinish = finishedReceiver != null;
    318                 int userId = key.userId;
    319                 if (userId == UserHandle.USER_CURRENT) {
    320                     userId = owner.mUserController.getCurrentOrTargetUserIdLocked();
    321                 }
    322                 int res = 0;
    323                 switch (key.type) {
    324                     case ActivityManager.INTENT_SENDER_ACTIVITY:
    325                         if (options == null) {
    326                             options = key.options;
    327                         } else if (key.options != null) {
    328                             Bundle opts = new Bundle(key.options);
    329                             opts.putAll(options);
    330                             options = opts;
    331                         }
    332                         try {
    333                             if (key.allIntents != null && key.allIntents.length > 1) {
    334                                 Intent[] allIntents = new Intent[key.allIntents.length];
    335                                 String[] allResolvedTypes = new String[key.allIntents.length];
    336                                 System.arraycopy(key.allIntents, 0, allIntents, 0,
    337                                         key.allIntents.length);
    338                                 if (key.allResolvedTypes != null) {
    339                                     System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
    340                                             key.allResolvedTypes.length);
    341                                 }
    342                                 allIntents[allIntents.length-1] = finalIntent;
    343                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
    344                                 owner.startActivitiesInPackage(uid, key.packageName, allIntents,
    345                                         allResolvedTypes, resultTo, options, userId);
    346                             } else {
    347                                 owner.startActivityInPackage(uid, key.packageName, finalIntent,
    348                                         resolvedType, resultTo, resultWho, requestCode, 0,
    349                                         options, userId, container, null, "PendingIntentRecord");
    350                             }
    351                         } catch (RuntimeException e) {
    352                             Slog.w(TAG, "Unable to send startActivity intent", e);
    353                         }
    354                         break;
    355                     case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
    356                         final ActivityStack stack = key.activity.getStack();
    357                         if (stack != null) {
    358                             stack.sendActivityResultLocked(-1, key.activity, key.who,
    359                                     key.requestCode, code, finalIntent);
    360                         }
    361                         break;
    362                     case ActivityManager.INTENT_SENDER_BROADCAST:
    363                         try {
    364                             // If a completion callback has been requested, require
    365                             // that the broadcast be delivered synchronously
    366                             int sent = owner.broadcastIntentInPackage(key.packageName, uid,
    367                                     finalIntent, resolvedType, finishedReceiver, code, null, null,
    368                                     requiredPermission, options, (finishedReceiver != null),
    369                                     false, userId);
    370                             if (sent == ActivityManager.BROADCAST_SUCCESS) {
    371                                 sendFinish = false;
    372                             }
    373                         } catch (RuntimeException e) {
    374                             Slog.w(TAG, "Unable to send startActivity intent", e);
    375                         }
    376                         break;
    377                     case ActivityManager.INTENT_SENDER_SERVICE:
    378                     case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
    379                         try {
    380                             owner.startServiceInPackage(uid, finalIntent, resolvedType,
    381                                     key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
    382                                     key.packageName, userId);
    383                         } catch (RuntimeException e) {
    384                             Slog.w(TAG, "Unable to send startService intent", e);
    385                         } catch (TransactionTooLargeException e) {
    386                             res = ActivityManager.START_CANCELED;
    387                         }
    388                         break;
    389                 }
    390 
    391                 if (sendFinish && res != ActivityManager.START_CANCELED) {
    392                     try {
    393                         finishedReceiver.performReceive(new Intent(finalIntent), 0,
    394                                 null, null, false, false, key.userId);
    395                     } catch (RemoteException e) {
    396                     }
    397                 }
    398 
    399                 Binder.restoreCallingIdentity(origId);
    400 
    401                 return res;
    402             }
    403         }
    404         return ActivityManager.START_CANCELED;
    405     }
    406 
    407     @Override
    408     protected void finalize() throws Throwable {
    409         try {
    410             if (!canceled) {
    411                 owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
    412                         ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
    413             }
    414         } finally {
    415             super.finalize();
    416         }
    417     }
    418 
    419     public void completeFinalize() {
    420         synchronized(owner) {
    421             WeakReference<PendingIntentRecord> current =
    422                     owner.mIntentSenderRecords.get(key);
    423             if (current == ref) {
    424                 owner.mIntentSenderRecords.remove(key);
    425             }
    426         }
    427     }
    428 
    429     void dump(PrintWriter pw, String prefix) {
    430         pw.print(prefix); pw.print("uid="); pw.print(uid);
    431                 pw.print(" packageName="); pw.print(key.packageName);
    432                 pw.print(" type="); pw.print(key.typeName());
    433                 pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
    434         if (key.activity != null || key.who != null) {
    435             pw.print(prefix); pw.print("activity="); pw.print(key.activity);
    436                     pw.print(" who="); pw.println(key.who);
    437         }
    438         if (key.requestCode != 0 || key.requestResolvedType != null) {
    439             pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
    440                     pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
    441         }
    442         if (key.requestIntent != null) {
    443             pw.print(prefix); pw.print("requestIntent=");
    444                     pw.println(key.requestIntent.toShortString(false, true, true, true));
    445         }
    446         if (sent || canceled) {
    447             pw.print(prefix); pw.print("sent="); pw.print(sent);
    448                     pw.print(" canceled="); pw.println(canceled);
    449         }
    450         if (whitelistDuration != null) {
    451             pw.print(prefix);
    452             pw.print("whitelistDuration=");
    453             for (int i = 0; i < whitelistDuration.size(); i++) {
    454                 if (i != 0) {
    455                     pw.print(", ");
    456                 }
    457                 pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
    458                 pw.print(":");
    459                 TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw);
    460             }
    461             pw.println();
    462         }
    463         if (mCancelCallbacks != null) {
    464             pw.print(prefix); pw.println("mCancelCallbacks:");
    465             for (int i = 0; i < mCancelCallbacks.getRegisteredCallbackCount(); i++) {
    466                 pw.print(prefix); pw.print("  #"); pw.print(i); pw.print(": ");
    467                 pw.println(mCancelCallbacks.getRegisteredCallbackItem(i));
    468             }
    469         }
    470     }
    471 
    472     public String toString() {
    473         if (stringName != null) {
    474             return stringName;
    475         }
    476         StringBuilder sb = new StringBuilder(128);
    477         sb.append("PendingIntentRecord{");
    478         sb.append(Integer.toHexString(System.identityHashCode(this)));
    479         sb.append(' ');
    480         sb.append(key.packageName);
    481         sb.append(' ');
    482         sb.append(key.typeName());
    483         if (whitelistDuration != null) {
    484             sb.append( " (whitelist: ");
    485             for (int i = 0; i < whitelistDuration.size(); i++) {
    486                 if (i != 0) {
    487                     sb.append(",");
    488                 }
    489                 sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
    490                 sb.append(":");
    491                 TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb);
    492             }
    493             sb.append(")");
    494         }
    495         sb.append('}');
    496         return stringName = sb.toString();
    497     }
    498 }
    499