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 286 final String reason = "startActivityInPackage"; 287 288 userId = checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(), 289 Binder.getCallingUid(), reason); 290 291 // TODO: Switch to user app stacks here. 292 return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options, 293 userId, reason); 294 } 295 startActivities(IApplicationThread caller, int callingUid, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, String reason)296 int startActivities(IApplicationThread caller, int callingUid, String callingPackage, 297 Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, 298 int userId, String reason) { 299 if (intents == null) { 300 throw new NullPointerException("intents is null"); 301 } 302 if (resolvedTypes == null) { 303 throw new NullPointerException("resolvedTypes is null"); 304 } 305 if (intents.length != resolvedTypes.length) { 306 throw new IllegalArgumentException("intents are length different than resolvedTypes"); 307 } 308 309 final int realCallingPid = Binder.getCallingPid(); 310 final int realCallingUid = Binder.getCallingUid(); 311 312 int callingPid; 313 if (callingUid >= 0) { 314 callingPid = -1; 315 } else if (caller == null) { 316 callingPid = realCallingPid; 317 callingUid = realCallingUid; 318 } else { 319 callingPid = callingUid = -1; 320 } 321 final long origId = Binder.clearCallingIdentity(); 322 try { 323 synchronized (mService) { 324 ActivityRecord[] outActivity = new ActivityRecord[1]; 325 for (int i=0; i < intents.length; i++) { 326 Intent intent = intents[i]; 327 if (intent == null) { 328 continue; 329 } 330 331 // Refuse possible leaked file descriptors 332 if (intent != null && intent.hasFileDescriptors()) { 333 throw new IllegalArgumentException("File descriptors passed in Intent"); 334 } 335 336 boolean componentSpecified = intent.getComponent() != null; 337 338 // Don't modify the client's object! 339 intent = new Intent(intent); 340 341 // Collect information about the target of the Intent. 342 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0, 343 null, userId, ActivityStarter.computeResolveFilterUid( 344 callingUid, realCallingUid, UserHandle.USER_NULL)); 345 // TODO: New, check if this is correct 346 aInfo = mService.getActivityInfoForUser(aInfo, userId); 347 348 if (aInfo != null && 349 (aInfo.applicationInfo.privateFlags 350 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { 351 throw new IllegalArgumentException( 352 "FLAG_CANT_SAVE_STATE not supported here"); 353 } 354 355 final boolean top = i == intents.length - 1; 356 final SafeActivityOptions checkedOptions = top 357 ? options 358 : null; 359 final int res = obtainStarter(intent, reason) 360 .setCaller(caller) 361 .setResolvedType(resolvedTypes[i]) 362 .setActivityInfo(aInfo) 363 .setResultTo(resultTo) 364 .setRequestCode(-1) 365 .setCallingPid(callingPid) 366 .setCallingUid(callingUid) 367 .setCallingPackage(callingPackage) 368 .setRealCallingPid(realCallingPid) 369 .setRealCallingUid(realCallingUid) 370 .setActivityOptions(checkedOptions) 371 .setComponentSpecified(componentSpecified) 372 .setOutActivity(outActivity) 373 374 // Top activity decides on animation being run, so we allow only for the 375 // top one as otherwise an activity below might consume it. 376 .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/) 377 .execute(); 378 379 if (res < 0) { 380 return res; 381 } 382 383 resultTo = outActivity[0] != null ? outActivity[0].appToken : null; 384 } 385 } 386 } finally { 387 Binder.restoreCallingIdentity(origId); 388 } 389 390 return START_SUCCESS; 391 } 392 schedulePendingActivityLaunches(long delayMs)393 void schedulePendingActivityLaunches(long delayMs) { 394 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG); 395 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG); 396 mHandler.sendMessageDelayed(msg, delayMs); 397 } 398 doPendingActivityLaunches(boolean doResume)399 void doPendingActivityLaunches(boolean doResume) { 400 while (!mPendingActivityLaunches.isEmpty()) { 401 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0); 402 final boolean resume = doResume && mPendingActivityLaunches.isEmpty(); 403 final ActivityStarter starter = obtainStarter(null /* intent */, 404 "pendingActivityLaunch"); 405 try { 406 starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, 407 resume, null, null, null /* outRecords */); 408 } catch (Exception e) { 409 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e); 410 pal.sendErrorResult(e.getMessage()); 411 } 412 } 413 } 414 addPendingActivityLaunch(PendingActivityLaunch launch)415 void addPendingActivityLaunch(PendingActivityLaunch launch) { 416 mPendingActivityLaunches.add(launch); 417 } 418 clearPendingActivityLaunches(String packageName)419 boolean clearPendingActivityLaunches(String packageName) { 420 final int pendingLaunches = mPendingActivityLaunches.size(); 421 422 for (int palNdx = pendingLaunches - 1; palNdx >= 0; --palNdx) { 423 final PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx); 424 final ActivityRecord r = pal.r; 425 if (r != null && r.packageName.equals(packageName)) { 426 mPendingActivityLaunches.remove(palNdx); 427 } 428 } 429 return mPendingActivityLaunches.size() < pendingLaunches; 430 } 431 registerRemoteAnimationForNextActivityStart(String packageName, RemoteAnimationAdapter adapter)432 void registerRemoteAnimationForNextActivityStart(String packageName, 433 RemoteAnimationAdapter adapter) { 434 mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter); 435 } 436 getPendingRemoteAnimationRegistry()437 PendingRemoteAnimationRegistry getPendingRemoteAnimationRegistry() { 438 return mPendingRemoteAnimationRegistry; 439 } 440 dump(PrintWriter pw, String prefix, String dumpPackage)441 void dump(PrintWriter pw, String prefix, String dumpPackage) { 442 pw.print(prefix); 443 pw.print("mLastHomeActivityStartResult="); 444 pw.println(mLastHomeActivityStartResult); 445 446 if (mLastHomeActivityStartRecord != null) { 447 pw.print(prefix); 448 pw.println("mLastHomeActivityStartRecord:"); 449 mLastHomeActivityStartRecord.dump(pw, prefix + " "); 450 } 451 452 final boolean dumpPackagePresent = dumpPackage != null; 453 454 if (mLastStarter != null) { 455 final boolean dump = !dumpPackagePresent 456 || mLastStarter.relatedToPackage(dumpPackage) 457 || (mLastHomeActivityStartRecord != null 458 && dumpPackage.equals(mLastHomeActivityStartRecord.packageName)); 459 460 if (dump) { 461 pw.print(prefix); 462 mLastStarter.dump(pw, prefix + " "); 463 464 if (dumpPackagePresent) { 465 return; 466 } 467 } 468 } 469 470 if (dumpPackagePresent) { 471 pw.print(prefix); 472 pw.println("(nothing)"); 473 } 474 } 475 } 476