1 /* 2 * Copyright (C) 2018 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.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; 20 21 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU; 22 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU; 23 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 24 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 25 26 import android.app.Activity; 27 import android.app.ActivityManagerInternal; 28 import android.app.AppGlobals; 29 import android.app.PendingIntent; 30 import android.content.IIntentSender; 31 import android.content.Intent; 32 import android.os.Binder; 33 import android.os.Bundle; 34 import android.os.Handler; 35 import android.os.IBinder; 36 import android.os.Looper; 37 import android.os.Message; 38 import android.os.RemoteCallbackList; 39 import android.os.RemoteException; 40 import android.os.UserHandle; 41 import android.util.ArrayMap; 42 import android.util.Slog; 43 44 import com.android.internal.os.IResultReceiver; 45 import com.android.internal.util.function.pooled.PooledLambda; 46 import com.android.server.AlarmManagerInternal; 47 import com.android.server.LocalServices; 48 import com.android.server.wm.ActivityTaskManagerInternal; 49 import com.android.server.wm.SafeActivityOptions; 50 51 import java.io.PrintWriter; 52 import java.lang.ref.WeakReference; 53 import java.util.ArrayList; 54 import java.util.HashMap; 55 import java.util.Iterator; 56 57 /** 58 * Helper class for {@link ActivityManagerService} responsible for managing pending intents. 59 * 60 * <p>This class uses {@link #mLock} to synchronize access to internal state and doesn't make use of 61 * {@link ActivityManagerService} lock since there can be direct calls into this class from outside 62 * AM. This helps avoid deadlocks. 63 */ 64 public class PendingIntentController { 65 private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentController" : TAG_AM; 66 private static final String TAG_MU = TAG + POSTFIX_MU; 67 68 /** Lock for internal state. */ 69 final Object mLock = new Object(); 70 final Handler mH; 71 ActivityManagerInternal mAmInternal; 72 final UserController mUserController; 73 final ActivityTaskManagerInternal mAtmInternal; 74 75 /** Set of IntentSenderRecord objects that are currently active. */ 76 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords 77 = new HashMap<>(); 78 PendingIntentController(Looper looper, UserController userController)79 PendingIntentController(Looper looper, UserController userController) { 80 mH = new Handler(looper); 81 mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); 82 mUserController = userController; 83 } 84 onActivityManagerInternalAdded()85 void onActivityManagerInternalAdded() { 86 synchronized (mLock) { 87 mAmInternal = LocalServices.getService(ActivityManagerInternal.class); 88 } 89 } 90 getIntentSender(int type, String packageName, int callingUid, int userId, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, int flags, Bundle bOptions)91 public PendingIntentRecord getIntentSender(int type, String packageName, int callingUid, 92 int userId, IBinder token, String resultWho, int requestCode, Intent[] intents, 93 String[] resolvedTypes, int flags, Bundle bOptions) { 94 synchronized (mLock) { 95 if (DEBUG_MU) Slog.v(TAG_MU, "getIntentSender(): uid=" + callingUid); 96 97 // We're going to be splicing together extras before sending, so we're 98 // okay poking into any contained extras. 99 if (intents != null) { 100 for (int i = 0; i < intents.length; i++) { 101 intents[i].setDefusable(true); 102 } 103 } 104 Bundle.setDefusable(bOptions, true); 105 106 final boolean noCreate = (flags & PendingIntent.FLAG_NO_CREATE) != 0; 107 final boolean cancelCurrent = (flags & PendingIntent.FLAG_CANCEL_CURRENT) != 0; 108 final boolean updateCurrent = (flags & PendingIntent.FLAG_UPDATE_CURRENT) != 0; 109 flags &= ~(PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_CANCEL_CURRENT 110 | PendingIntent.FLAG_UPDATE_CURRENT); 111 112 PendingIntentRecord.Key key = new PendingIntentRecord.Key(type, packageName, token, 113 resultWho, requestCode, intents, resolvedTypes, flags, 114 SafeActivityOptions.fromBundle(bOptions), userId); 115 WeakReference<PendingIntentRecord> ref; 116 ref = mIntentSenderRecords.get(key); 117 PendingIntentRecord rec = ref != null ? ref.get() : null; 118 if (rec != null) { 119 if (!cancelCurrent) { 120 if (updateCurrent) { 121 if (rec.key.requestIntent != null) { 122 rec.key.requestIntent.replaceExtras(intents != null ? 123 intents[intents.length - 1] : null); 124 } 125 if (intents != null) { 126 intents[intents.length - 1] = rec.key.requestIntent; 127 rec.key.allIntents = intents; 128 rec.key.allResolvedTypes = resolvedTypes; 129 } else { 130 rec.key.allIntents = null; 131 rec.key.allResolvedTypes = null; 132 } 133 } 134 return rec; 135 } 136 makeIntentSenderCanceled(rec); 137 mIntentSenderRecords.remove(key); 138 } 139 if (noCreate) { 140 return rec; 141 } 142 rec = new PendingIntentRecord(this, key, callingUid); 143 mIntentSenderRecords.put(key, rec.ref); 144 return rec; 145 } 146 } 147 removePendingIntentsForPackage(String packageName, int userId, int appId, boolean doIt)148 boolean removePendingIntentsForPackage(String packageName, int userId, int appId, 149 boolean doIt) { 150 151 boolean didSomething = false; 152 synchronized (mLock) { 153 154 // Remove pending intents. For now we only do this when force stopping users, because 155 // we have some problems when doing this for packages -- app widgets are not currently 156 // cleaned up for such packages, so they can be left with bad pending intents. 157 if (mIntentSenderRecords.size() <= 0) { 158 return false; 159 } 160 161 Iterator<WeakReference<PendingIntentRecord>> it 162 = mIntentSenderRecords.values().iterator(); 163 while (it.hasNext()) { 164 WeakReference<PendingIntentRecord> wpir = it.next(); 165 if (wpir == null) { 166 it.remove(); 167 continue; 168 } 169 PendingIntentRecord pir = wpir.get(); 170 if (pir == null) { 171 it.remove(); 172 continue; 173 } 174 if (packageName == null) { 175 // Stopping user, remove all objects for the user. 176 if (pir.key.userId != userId) { 177 // Not the same user, skip it. 178 continue; 179 } 180 } else { 181 if (UserHandle.getAppId(pir.uid) != appId) { 182 // Different app id, skip it. 183 continue; 184 } 185 if (userId != UserHandle.USER_ALL && pir.key.userId != userId) { 186 // Different user, skip it. 187 continue; 188 } 189 if (!pir.key.packageName.equals(packageName)) { 190 // Different package, skip it. 191 continue; 192 } 193 } 194 if (!doIt) { 195 return true; 196 } 197 didSomething = true; 198 it.remove(); 199 makeIntentSenderCanceled(pir); 200 if (pir.key.activity != null) { 201 final Message m = PooledLambda.obtainMessage( 202 PendingIntentController::clearPendingResultForActivity, this, 203 pir.key.activity, pir.ref); 204 mH.sendMessage(m); 205 } 206 } 207 } 208 209 return didSomething; 210 } 211 cancelIntentSender(IIntentSender sender)212 public void cancelIntentSender(IIntentSender sender) { 213 if (!(sender instanceof PendingIntentRecord)) { 214 return; 215 } 216 synchronized (mLock) { 217 final PendingIntentRecord rec = (PendingIntentRecord) sender; 218 try { 219 final int uid = AppGlobals.getPackageManager().getPackageUid(rec.key.packageName, 220 MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getCallingUserId()); 221 if (!UserHandle.isSameApp(uid, Binder.getCallingUid())) { 222 String msg = "Permission Denial: cancelIntentSender() from pid=" 223 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 224 + " is not allowed to cancel package " + rec.key.packageName; 225 Slog.w(TAG, msg); 226 throw new SecurityException(msg); 227 } 228 } catch (RemoteException e) { 229 throw new SecurityException(e); 230 } 231 cancelIntentSender(rec, true); 232 } 233 } 234 cancelIntentSender(PendingIntentRecord rec, boolean cleanActivity)235 public void cancelIntentSender(PendingIntentRecord rec, boolean cleanActivity) { 236 synchronized (mLock) { 237 makeIntentSenderCanceled(rec); 238 mIntentSenderRecords.remove(rec.key); 239 if (cleanActivity && rec.key.activity != null) { 240 final Message m = PooledLambda.obtainMessage( 241 PendingIntentController::clearPendingResultForActivity, this, 242 rec.key.activity, rec.ref); 243 mH.sendMessage(m); 244 } 245 } 246 } 247 registerIntentSenderCancelListener(IIntentSender sender, IResultReceiver receiver)248 void registerIntentSenderCancelListener(IIntentSender sender, IResultReceiver receiver) { 249 if (!(sender instanceof PendingIntentRecord)) { 250 return; 251 } 252 boolean isCancelled; 253 synchronized (mLock) { 254 PendingIntentRecord pendingIntent = (PendingIntentRecord) sender; 255 isCancelled = pendingIntent.canceled; 256 if (!isCancelled) { 257 pendingIntent.registerCancelListenerLocked(receiver); 258 } 259 } 260 if (isCancelled) { 261 try { 262 receiver.send(Activity.RESULT_CANCELED, null); 263 } catch (RemoteException e) { 264 } 265 } 266 } 267 unregisterIntentSenderCancelListener(IIntentSender sender, IResultReceiver receiver)268 void unregisterIntentSenderCancelListener(IIntentSender sender, 269 IResultReceiver receiver) { 270 if (!(sender instanceof PendingIntentRecord)) { 271 return; 272 } 273 synchronized (mLock) { 274 ((PendingIntentRecord) sender).unregisterCancelListenerLocked(receiver); 275 } 276 } 277 setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken, long duration)278 void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken, 279 long duration) { 280 if (!(target instanceof PendingIntentRecord)) { 281 Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target); 282 return; 283 } 284 synchronized (mLock) { 285 ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration); 286 } 287 } 288 makeIntentSenderCanceled(PendingIntentRecord rec)289 private void makeIntentSenderCanceled(PendingIntentRecord rec) { 290 rec.canceled = true; 291 final RemoteCallbackList<IResultReceiver> callbacks = rec.detachCancelListenersLocked(); 292 if (callbacks != null) { 293 final Message m = PooledLambda.obtainMessage( 294 PendingIntentController::handlePendingIntentCancelled, this, callbacks); 295 mH.sendMessage(m); 296 } 297 final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class); 298 ami.remove(new PendingIntent(rec)); 299 } 300 handlePendingIntentCancelled(RemoteCallbackList<IResultReceiver> callbacks)301 private void handlePendingIntentCancelled(RemoteCallbackList<IResultReceiver> callbacks) { 302 int N = callbacks.beginBroadcast(); 303 for (int i = 0; i < N; i++) { 304 try { 305 callbacks.getBroadcastItem(i).send(Activity.RESULT_CANCELED, null); 306 } catch (RemoteException e) { 307 // Process is not longer running...whatever. 308 } 309 } 310 callbacks.finishBroadcast(); 311 // We have to clean up the RemoteCallbackList here, because otherwise it will 312 // needlessly hold the enclosed callbacks until the remote process dies. 313 callbacks.kill(); 314 } 315 clearPendingResultForActivity(IBinder activityToken, WeakReference<PendingIntentRecord> pir)316 private void clearPendingResultForActivity(IBinder activityToken, 317 WeakReference<PendingIntentRecord> pir) { 318 mAtmInternal.clearPendingResultForActivity(activityToken, pir); 319 } 320 dumpPendingIntents(PrintWriter pw, boolean dumpAll, String dumpPackage)321 void dumpPendingIntents(PrintWriter pw, boolean dumpAll, String dumpPackage) { 322 synchronized (mLock) { 323 boolean printed = false; 324 325 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)"); 326 327 if (mIntentSenderRecords.size() > 0) { 328 // Organize these by package name, so they are easier to read. 329 final ArrayMap<String, ArrayList<PendingIntentRecord>> byPackage = new ArrayMap<>(); 330 final ArrayList<WeakReference<PendingIntentRecord>> weakRefs = new ArrayList<>(); 331 final Iterator<WeakReference<PendingIntentRecord>> it 332 = mIntentSenderRecords.values().iterator(); 333 while (it.hasNext()) { 334 WeakReference<PendingIntentRecord> ref = it.next(); 335 PendingIntentRecord rec = ref != null ? ref.get() : null; 336 if (rec == null) { 337 weakRefs.add(ref); 338 continue; 339 } 340 if (dumpPackage != null && !dumpPackage.equals(rec.key.packageName)) { 341 continue; 342 } 343 ArrayList<PendingIntentRecord> list = byPackage.get(rec.key.packageName); 344 if (list == null) { 345 list = new ArrayList<>(); 346 byPackage.put(rec.key.packageName, list); 347 } 348 list.add(rec); 349 } 350 for (int i = 0; i < byPackage.size(); i++) { 351 ArrayList<PendingIntentRecord> intents = byPackage.valueAt(i); 352 printed = true; 353 pw.print(" * "); pw.print(byPackage.keyAt(i)); 354 pw.print(": "); pw.print(intents.size()); pw.println(" items"); 355 for (int j = 0; j < intents.size(); j++) { 356 pw.print(" #"); pw.print(j); pw.print(": "); pw.println(intents.get(j)); 357 if (dumpAll) { 358 intents.get(j).dump(pw, " "); 359 } 360 } 361 } 362 if (weakRefs.size() > 0) { 363 printed = true; 364 pw.println(" * WEAK REFS:"); 365 for (int i = 0; i < weakRefs.size(); i++) { 366 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(weakRefs.get(i)); 367 } 368 } 369 } 370 371 if (!printed) { 372 pw.println(" (nothing)"); 373 } 374 } 375 } 376 } 377