1 /* 2 * Copyright (C) 2017 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 android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 21 22 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 23 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 24 import static com.android.server.am.ActivityManagerService.ALLOW_FULL_ONLY; 25 26 import android.app.IApplicationThread; 27 import android.content.ComponentName; 28 import android.content.ContentResolver; 29 import android.content.Intent; 30 import android.content.pm.ActivityInfo; 31 import android.content.pm.ApplicationInfo; 32 import android.content.pm.PackageManager; 33 import android.content.pm.ResolveInfo; 34 import android.os.Binder; 35 import android.os.FactoryTest; 36 import android.os.Handler; 37 import android.os.IBinder; 38 import android.os.Looper; 39 import android.os.Message; 40 import android.os.UserHandle; 41 import android.provider.Settings; 42 import android.util.Slog; 43 import android.view.RemoteAnimationAdapter; 44 45 import com.android.internal.annotations.VisibleForTesting; 46 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch; 47 import com.android.server.am.ActivityStarter.DefaultFactory; 48 import com.android.server.am.ActivityStarter.Factory; 49 50 import java.io.PrintWriter; 51 import java.util.ArrayList; 52 import java.util.List; 53 54 /** 55 * Controller for delegating activity launches. 56 * 57 * This class' main objective is to take external activity start requests and prepare them into 58 * a series of discrete activity launches that can be handled by an {@link ActivityStarter}. It is 59 * also responsible for handling logic that happens around an activity launch, but doesn't 60 * necessarily influence the activity start. Examples include power hint management, processing 61 * through the pending activity list, and recording home activity launches. 62 */ 63 public class ActivityStartController { 64 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStartController" : TAG_AM; 65 66 private static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 1; 67 68 private final ActivityManagerService mService; 69 private final ActivityStackSupervisor mSupervisor; 70 71 /** Last home activity record we attempted to start. */ 72 private ActivityRecord mLastHomeActivityStartRecord; 73 74 /** Temporary array to capture start activity results */ 75 private ActivityRecord[] tmpOutRecord = new ActivityRecord[1]; 76 77 /**The result of the last home activity we attempted to start. */ 78 private int mLastHomeActivityStartResult; 79 80 /** A list of activities that are waiting to launch. */ 81 private final ArrayList<ActivityStackSupervisor.PendingActivityLaunch> 82 mPendingActivityLaunches = new ArrayList<>(); 83 84 private final Factory mFactory; 85 86 private final Handler mHandler; 87 88 private final PendingRemoteAnimationRegistry mPendingRemoteAnimationRegistry; 89 90 private final class StartHandler extends Handler { StartHandler(Looper looper)91 public StartHandler(Looper looper) { 92 super(looper, null, true); 93 } 94 95 @Override handleMessage(Message msg)96 public void handleMessage(Message msg) { 97 switch(msg.what) { 98 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: 99 synchronized (mService) { 100 doPendingActivityLaunches(true); 101 } 102 break; 103 } 104 } 105 } 106 107 /** 108 * TODO(b/64750076): Capture information necessary for dump and 109 * {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object 110 * around 111 */ 112 private ActivityStarter mLastStarter; 113 ActivityStartController(ActivityManagerService service)114 ActivityStartController(ActivityManagerService service) { 115 this(service, service.mStackSupervisor, 116 new DefaultFactory(service, service.mStackSupervisor, 117 new ActivityStartInterceptor(service, service.mStackSupervisor))); 118 } 119 120 @VisibleForTesting ActivityStartController(ActivityManagerService service, ActivityStackSupervisor supervisor, Factory factory)121 ActivityStartController(ActivityManagerService service, ActivityStackSupervisor supervisor, 122 Factory factory) { 123 mService = service; 124 mSupervisor = supervisor; 125 mHandler = new StartHandler(mService.mHandlerThread.getLooper()); 126 mFactory = factory; 127 mFactory.setController(this); 128 mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service, 129 service.mHandler); 130 } 131 132 /** 133 * @return A starter to configure and execute starting an activity. It is valid until after 134 * {@link ActivityStarter#execute} is invoked. At that point, the starter should be 135 * considered invalid and no longer modified or used. 136 */ obtainStarter(Intent intent, String reason)137 ActivityStarter obtainStarter(Intent intent, String reason) { 138 return mFactory.obtain().setIntent(intent).setReason(reason); 139 } 140 onExecutionComplete(ActivityStarter starter)141 void onExecutionComplete(ActivityStarter starter) { 142 if (mLastStarter == null) { 143 mLastStarter = mFactory.obtain(); 144 } 145 146 mLastStarter.set(starter); 147 mFactory.recycle(starter); 148 } 149 150 /** 151 * TODO(b/64750076): usage of this doesn't seem right. We're making decisions based off the 152 * last starter for an arbitrary task record. Re-evaluate whether we can remove. 153 */ postStartActivityProcessingForLastStarter(ActivityRecord r, int result, ActivityStack targetStack)154 void postStartActivityProcessingForLastStarter(ActivityRecord r, int result, 155 ActivityStack targetStack) { 156 if (mLastStarter == null) { 157 return; 158 } 159 160 mLastStarter.postStartActivityProcessing(r, result, targetStack); 161 } 162 startHomeActivity(Intent intent, ActivityInfo aInfo, String reason)163 void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) { 164 mSupervisor.moveHomeStackTaskToTop(reason); 165 166 mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason) 167 .setOutActivity(tmpOutRecord) 168 .setCallingUid(0) 169 .setActivityInfo(aInfo) 170 .execute(); 171 mLastHomeActivityStartRecord = tmpOutRecord[0]; 172 if (mSupervisor.inResumeTopActivity) { 173 // If we are in resume section already, home activity will be initialized, but not 174 // resumed (to avoid recursive resume) and will stay that way until something pokes it 175 // again. We need to schedule another resume. 176 mSupervisor.scheduleResumeTopActivities(); 177 } 178 } 179 180 /** 181 * Starts the "new version setup screen" if appropriate. 182 */ startSetupActivity()183 void startSetupActivity() { 184 // Only do this once per boot. 185 if (mService.getCheckedForSetup()) { 186 return; 187 } 188 189 // We will show this screen if the current one is a different 190 // version than the last one shown, and we are not running in 191 // low-level factory test mode. 192 final ContentResolver resolver = mService.mContext.getContentResolver(); 193 if (mService.mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL && 194 Settings.Global.getInt(resolver, 195 Settings.Global.DEVICE_PROVISIONED, 0) != 0) { 196 mService.setCheckedForSetup(true); 197 198 // See if we should be showing the platform update setup UI. 199 final Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP); 200 final List<ResolveInfo> ris = 201 mService.mContext.getPackageManager().queryIntentActivities(intent, 202 PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA 203 | ActivityManagerService.STOCK_PM_FLAGS); 204 if (!ris.isEmpty()) { 205 final ResolveInfo ri = ris.get(0); 206 String vers = ri.activityInfo.metaData != null 207 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION) 208 : null; 209 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) { 210 vers = ri.activityInfo.applicationInfo.metaData.getString( 211 Intent.METADATA_SETUP_VERSION); 212 } 213 String lastVers = Settings.Secure.getString( 214 resolver, Settings.Secure.LAST_SETUP_SHOWN); 215 if (vers != null && !vers.equals(lastVers)) { 216 intent.setFlags(FLAG_ACTIVITY_NEW_TASK); 217 intent.setComponent(new ComponentName( 218 ri.activityInfo.packageName, ri.activityInfo.name)); 219 obtainStarter(intent, "startSetupActivity") 220 .setCallingUid(0) 221 .setActivityInfo(ri.activityInfo) 222 .execute(); 223 } 224 } 225 } 226 } 227 228 /** 229 * If {@code validateIncomingUser} is true, check {@code targetUserId} against the real calling 230 * user ID inferred from {@code realCallingUid}, then return the resolved user-id, taking into 231 * account "current user", etc. 232 * 233 * If {@code validateIncomingUser} is false, it skips the above check, but instead 234 * ensures {@code targetUserId} is a real user ID and not a special user ID such as 235 * {@link android.os.UserHandle#USER_ALL}, etc. 236 */ checkTargetUser(int targetUserId, boolean validateIncomingUser, int realCallingPid, int realCallingUid, String reason)237 int checkTargetUser(int targetUserId, boolean validateIncomingUser, 238 int realCallingPid, int realCallingUid, String reason) { 239 if (validateIncomingUser) { 240 return mService.mUserController.handleIncomingUser(realCallingPid, realCallingUid, 241 targetUserId, false, ALLOW_FULL_ONLY, reason, null); 242 } else { 243 mService.mUserController.ensureNotSpecialUser(targetUserId); 244 return targetUserId; 245 } 246 } 247 startActivityInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, SafeActivityOptions options, int userId, TaskRecord inTask, String reason, boolean validateIncomingUser)248 final int startActivityInPackage(int uid, int realCallingPid, int realCallingUid, 249 String callingPackage, Intent intent, String resolvedType, IBinder resultTo, 250 String resultWho, int requestCode, int startFlags, SafeActivityOptions options, 251 int userId, TaskRecord inTask, String reason, boolean validateIncomingUser) { 252 253 userId = checkTargetUser(userId, validateIncomingUser, realCallingPid, realCallingUid, 254 reason); 255 256 // TODO: Switch to user app stacks here. 257 return obtainStarter(intent, reason) 258 .setCallingUid(uid) 259 .setRealCallingPid(realCallingPid) 260 .setRealCallingUid(realCallingUid) 261 .setCallingPackage(callingPackage) 262 .setResolvedType(resolvedType) 263 .setResultTo(resultTo) 264 .setResultWho(resultWho) 265 .setRequestCode(requestCode) 266 .setStartFlags(startFlags) 267 .setActivityOptions(options) 268 .setMayWait(userId) 269 .setInTask(inTask) 270 .execute(); 271 } 272 273 /** 274 * Start intents as a package. 275 * 276 * @param uid Make a call as if this UID did. 277 * @param callingPackage Make a call as if this package did. 278 * @param intents Intents to start. 279 * @param userId Start the intents on this user. 280 * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID. 281 */ startActivitiesInPackage(int uid, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser)282 final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents, 283 String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, 284 boolean validateIncomingUser) { 285 return startActivitiesInPackage(uid, 0, UserHandle.USER_NULL, 286 callingPackage, intents, resolvedTypes, resultTo, options, userId, 287 validateIncomingUser); 288 } 289 startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser)290 final int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, 291 String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, 292 SafeActivityOptions options, int userId, boolean validateIncomingUser) { 293 final String reason = "startActivityInPackage"; 294 295 userId = checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(), 296 Binder.getCallingUid(), reason); 297 298 // TODO: Switch to user app stacks here. 299 return startActivities(null, uid, realCallingPid, realCallingUid, callingPackage, intents, 300 resolvedTypes, resultTo, options, userId, reason); 301 } 302 startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid, int incomingRealCallingUid, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, String reason)303 int startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid, 304 int incomingRealCallingUid, String callingPackage, Intent[] intents, String[] resolvedTypes, 305 IBinder resultTo, SafeActivityOptions options, int userId, String reason) { 306 if (intents == null) { 307 throw new NullPointerException("intents is null"); 308 } 309 if (resolvedTypes == null) { 310 throw new NullPointerException("resolvedTypes is null"); 311 } 312 if (intents.length != resolvedTypes.length) { 313 throw new IllegalArgumentException("intents are length different than resolvedTypes"); 314 } 315 316 final int realCallingPid = incomingRealCallingPid != 0 317 ? incomingRealCallingPid 318 : Binder.getCallingPid(); 319 final int realCallingUid = incomingRealCallingUid != UserHandle.USER_NULL 320 ? incomingRealCallingUid 321 : Binder.getCallingUid(); 322 int callingPid; 323 if (callingUid >= 0) { 324 callingPid = -1; 325 } else if (caller == null) { 326 callingPid = realCallingPid; 327 callingUid = realCallingUid; 328 } else { 329 callingPid = callingUid = -1; 330 } 331 boolean forceNewTask = false; 332 final int filterCallingUid = ActivityStarter.computeResolveFilterUid( 333 callingUid, realCallingUid, UserHandle.USER_NULL); 334 final long origId = Binder.clearCallingIdentity(); 335 try { 336 synchronized (mService) { 337 ActivityRecord[] outActivity = new ActivityRecord[1]; 338 for (int i=0; i < intents.length; i++) { 339 Intent intent = intents[i]; 340 if (intent == null) { 341 continue; 342 } 343 344 // Refuse possible leaked file descriptors 345 if (intent != null && intent.hasFileDescriptors()) { 346 throw new IllegalArgumentException("File descriptors passed in Intent"); 347 } 348 349 boolean componentSpecified = intent.getComponent() != null; 350 351 // Don't modify the client's object! 352 intent = new Intent(intent); 353 if (forceNewTask) { 354 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 355 } 356 357 // Collect information about the target of the Intent. 358 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0, 359 null, userId, filterCallingUid); 360 // TODO: New, check if this is correct 361 aInfo = mService.getActivityInfoForUser(aInfo, userId); 362 363 if (aInfo != null && 364 (aInfo.applicationInfo.privateFlags 365 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { 366 throw new IllegalArgumentException( 367 "FLAG_CANT_SAVE_STATE not supported here"); 368 } 369 370 final boolean top = i == intents.length - 1; 371 final SafeActivityOptions checkedOptions = top 372 ? options 373 : null; 374 final int res = obtainStarter(intent, reason) 375 .setCaller(caller) 376 .setResolvedType(resolvedTypes[i]) 377 .setActivityInfo(aInfo) 378 .setResultTo(resultTo) 379 .setRequestCode(-1) 380 .setCallingPid(callingPid) 381 .setCallingUid(callingUid) 382 .setCallingPackage(callingPackage) 383 .setRealCallingPid(realCallingPid) 384 .setRealCallingUid(realCallingUid) 385 .setActivityOptions(checkedOptions) 386 .setComponentSpecified(componentSpecified) 387 .setOutActivity(outActivity) 388 389 // Top activity decides on animation being run, so we allow only for the 390 // top one as otherwise an activity below might consume it. 391 .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/) 392 .execute(); 393 394 if (res < 0) { 395 return res; 396 } 397 398 final ActivityRecord started = outActivity[0]; 399 if (started != null && started.getUid() == filterCallingUid) { 400 // Only the started activity which has the same uid as the source caller can 401 // be the caller of next activity. 402 resultTo = started.appToken; 403 forceNewTask = false; 404 } else { 405 // Different apps not adjacent to the caller are forced to be new task. 406 resultTo = null; 407 forceNewTask = true; 408 } 409 } 410 } 411 } finally { 412 Binder.restoreCallingIdentity(origId); 413 } 414 415 return START_SUCCESS; 416 } 417 schedulePendingActivityLaunches(long delayMs)418 void schedulePendingActivityLaunches(long delayMs) { 419 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG); 420 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG); 421 mHandler.sendMessageDelayed(msg, delayMs); 422 } 423 doPendingActivityLaunches(boolean doResume)424 void doPendingActivityLaunches(boolean doResume) { 425 while (!mPendingActivityLaunches.isEmpty()) { 426 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0); 427 final boolean resume = doResume && mPendingActivityLaunches.isEmpty(); 428 final ActivityStarter starter = obtainStarter(null /* intent */, 429 "pendingActivityLaunch"); 430 try { 431 starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, 432 resume, null, null, null /* outRecords */); 433 } catch (Exception e) { 434 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e); 435 pal.sendErrorResult(e.getMessage()); 436 } 437 } 438 } 439 addPendingActivityLaunch(PendingActivityLaunch launch)440 void addPendingActivityLaunch(PendingActivityLaunch launch) { 441 mPendingActivityLaunches.add(launch); 442 } 443 clearPendingActivityLaunches(String packageName)444 boolean clearPendingActivityLaunches(String packageName) { 445 final int pendingLaunches = mPendingActivityLaunches.size(); 446 447 for (int palNdx = pendingLaunches - 1; palNdx >= 0; --palNdx) { 448 final PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx); 449 final ActivityRecord r = pal.r; 450 if (r != null && r.packageName.equals(packageName)) { 451 mPendingActivityLaunches.remove(palNdx); 452 } 453 } 454 return mPendingActivityLaunches.size() < pendingLaunches; 455 } 456 registerRemoteAnimationForNextActivityStart(String packageName, RemoteAnimationAdapter adapter)457 void registerRemoteAnimationForNextActivityStart(String packageName, 458 RemoteAnimationAdapter adapter) { 459 mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter); 460 } 461 getPendingRemoteAnimationRegistry()462 PendingRemoteAnimationRegistry getPendingRemoteAnimationRegistry() { 463 return mPendingRemoteAnimationRegistry; 464 } 465 dump(PrintWriter pw, String prefix, String dumpPackage)466 void dump(PrintWriter pw, String prefix, String dumpPackage) { 467 pw.print(prefix); 468 pw.print("mLastHomeActivityStartResult="); 469 pw.println(mLastHomeActivityStartResult); 470 471 if (mLastHomeActivityStartRecord != null) { 472 pw.print(prefix); 473 pw.println("mLastHomeActivityStartRecord:"); 474 mLastHomeActivityStartRecord.dump(pw, prefix + " "); 475 } 476 477 final boolean dumpPackagePresent = dumpPackage != null; 478 479 if (mLastStarter != null) { 480 final boolean dump = !dumpPackagePresent 481 || mLastStarter.relatedToPackage(dumpPackage) 482 || (mLastHomeActivityStartRecord != null 483 && dumpPackage.equals(mLastHomeActivityStartRecord.packageName)); 484 485 if (dump) { 486 pw.print(prefix); 487 mLastStarter.dump(pw, prefix + " "); 488 489 if (dumpPackagePresent) { 490 return; 491 } 492 } 493 } 494 495 if (dumpPackagePresent) { 496 pw.print(prefix); 497 pw.println("(nothing)"); 498 } 499 } 500 } 501