1 /* 2 * Copyright (C) 2019 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 android.app; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SuppressLint; 24 import android.content.Intent; 25 import android.content.pm.ApplicationInfo; 26 import android.icu.text.SimpleDateFormat; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.os.UserHandle; 30 import android.text.TextUtils; 31 import android.util.ArrayMap; 32 import android.util.Xml; 33 import android.util.proto.ProtoInputStream; 34 import android.util.proto.ProtoOutputStream; 35 import android.util.proto.WireTypeMismatchException; 36 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.internal.util.XmlUtils; 39 import com.android.modules.utils.TypedXmlPullParser; 40 import com.android.modules.utils.TypedXmlSerializer; 41 42 import org.xmlpull.v1.XmlPullParserException; 43 44 import java.io.ByteArrayInputStream; 45 import java.io.ByteArrayOutputStream; 46 import java.io.IOException; 47 import java.io.ObjectInputStream; 48 import java.io.ObjectOutputStream; 49 import java.io.PrintWriter; 50 import java.lang.annotation.Retention; 51 import java.lang.annotation.RetentionPolicy; 52 import java.util.Map; 53 import java.util.Objects; 54 55 /** 56 * Describes information related to an application process's startup. 57 * 58 * <p> 59 * Many aspects concerning why and how an applications process was started are valuable for apps 60 * both for logging and for potential behavior changes. Reason for process start, start type, 61 * start times, throttling, and other useful diagnostic data can be obtained from 62 * {@link ApplicationStartInfo} records. 63 * </p> 64 * 65 * <p> 66 * ApplicationStartInfo objects can be retrieved via: 67 * - {@link ActivityManager#getHistoricalProcessStartReasons}, which can be called during or after 68 * a application's startup. Using this method, an app can retrieve information about an 69 * in-progress app start. 70 * - {@link ActivityManager#addApplicationStartInfoCompletionListener}, which returns an 71 * ApplicationStartInfo object via a callback when the startup is complete, or immediately 72 * if requested after the startup is complete. 73 * </p> 74 */ 75 @FlaggedApi(Flags.FLAG_APP_START_INFO) 76 public final class ApplicationStartInfo implements Parcelable { 77 78 /** 79 * State indicating process startup has started. Some information is available in 80 * {@link ApplicationStartInfo} and more will be added. 81 */ 82 public static final int STARTUP_STATE_STARTED = 0; 83 84 /** 85 * State indicating process startup has failed. Startup information in 86 * {@link ApplicationStartInfo} is incomplete, but no more will be added. 87 */ 88 public static final int STARTUP_STATE_ERROR = 1; 89 90 /** 91 * State indicating process startup has made it to first frame draw. Startup 92 * information in {@link ApplicationStartInfo} is complete with potential exception 93 * of fully drawn timestamp which is not guaranteed to be set. 94 */ 95 public static final int STARTUP_STATE_FIRST_FRAME_DRAWN = 2; 96 97 /** Process started due to alarm. */ 98 public static final int START_REASON_ALARM = 0; 99 100 /** Process started to run backup. */ 101 public static final int START_REASON_BACKUP = 1; 102 103 /** Process started due to boot complete. */ 104 public static final int START_REASON_BOOT_COMPLETE = 2; 105 106 /** Process started due to broadcast received for any reason not explicitly listed. */ 107 public static final int START_REASON_BROADCAST = 3; 108 109 /** Process started due to access of ContentProvider for any reason not explicitly listed. */ 110 public static final int START_REASON_CONTENT_PROVIDER = 4; 111 112 /** * Process started to run scheduled job. */ 113 public static final int START_REASON_JOB = 5; 114 115 /** Process started due to click app icon or widget from launcher. */ 116 public static final int START_REASON_LAUNCHER = 6; 117 118 /** Process started from launcher recents. */ 119 public static final int START_REASON_LAUNCHER_RECENTS = 7; 120 121 /** Process started not for any of the listed reasons. */ 122 public static final int START_REASON_OTHER = 8; 123 124 /** Process started due to push message. */ 125 public static final int START_REASON_PUSH = 9; 126 127 /** Process started due to Service started for any reason not explicitly listed.. */ 128 public static final int START_REASON_SERVICE = 10; 129 130 /** Process started due to Activity started for any reason not explicitly listed. */ 131 public static final int START_REASON_START_ACTIVITY = 11; 132 133 /** Start type not yet set. */ 134 public static final int START_TYPE_UNSET = 0; 135 136 /** Process started from scratch. */ 137 public static final int START_TYPE_COLD = 1; 138 139 /** Process retained minimally SavedInstanceState. */ 140 public static final int START_TYPE_WARM = 2; 141 142 /** Process brought back to foreground. */ 143 public static final int START_TYPE_HOT = 3; 144 145 /** 146 * Default. The system always creates a new instance of the activity in the target task and 147 * routes the intent to it. 148 */ 149 public static final int LAUNCH_MODE_STANDARD = 0; 150 151 /** 152 * If an instance of the activity already exists at the top of the target task, the system 153 * routes the intent to that instance through a call to its onNewIntent() method, rather than 154 * creating a new instance of the activity. 155 */ 156 public static final int LAUNCH_MODE_SINGLE_TOP = 1; 157 158 /** 159 * The system creates the activity at the root of a new task or locates the activity on an 160 * existing task with the same affinity. If an instance of the activity already exists and is at 161 * the root of the task, the system routes the intent to existing instance through a call to its 162 * onNewIntent() method, rather than creating a new one. 163 */ 164 public static final int LAUNCH_MODE_SINGLE_INSTANCE = 2; 165 166 /** 167 * Same as "singleTask", except that the system doesn't launch any other activities into the 168 * task holding the instance. The activity is always the single and only member of its task. 169 */ 170 public static final int LAUNCH_MODE_SINGLE_TASK = 3; 171 172 /** 173 * The activity can only be running as the root activity of the task, the first activity that 174 * created the task, and therefore there will only be one instance of this activity in a task; 175 * but activity can be instantiated multiple times in different tasks. 176 */ 177 public static final int LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK = 4; 178 179 /** The end of the range, beginning with 0, reserved for system timestamps.*/ 180 public static final int START_TIMESTAMP_RESERVED_RANGE_SYSTEM = 20; 181 182 /** The beginning of the range reserved for developer supplied timestamps.*/ 183 public static final int START_TIMESTAMP_RESERVED_RANGE_DEVELOPER_START = 184 START_TIMESTAMP_RESERVED_RANGE_SYSTEM + 1; 185 186 /** The end of the range reserved for developer supplied timestamps.*/ 187 public static final int START_TIMESTAMP_RESERVED_RANGE_DEVELOPER = 30; 188 189 /** Clock monotonic timestamp of launch started. */ 190 public static final int START_TIMESTAMP_LAUNCH = 0; 191 192 /** Clock monotonic timestamp of process fork. */ 193 public static final int START_TIMESTAMP_FORK = 1; 194 195 /** Clock monotonic timestamp of Application onCreate called. */ 196 public static final int START_TIMESTAMP_APPLICATION_ONCREATE = 2; 197 198 /** Clock monotonic timestamp of bindApplication called. */ 199 public static final int START_TIMESTAMP_BIND_APPLICATION = 3; 200 201 /** Clock monotonic timestamp of first frame drawn. */ 202 public static final int START_TIMESTAMP_FIRST_FRAME = 4; 203 204 /** Clock monotonic timestamp of reportFullyDrawn called by application. */ 205 public static final int START_TIMESTAMP_FULLY_DRAWN = 5; 206 207 /** Clock monotonic timestamp of initial renderthread frame. */ 208 public static final int START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME = 6; 209 210 /** Clock monotonic timestamp of surfaceflinger composition complete. */ 211 public static final int START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE = 7; 212 213 /** Process was started for an activity component. */ 214 @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT) 215 public static final int START_COMPONENT_ACTIVITY = 1; 216 217 /** Process was started for a broadcast component. */ 218 @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT) 219 public static final int START_COMPONENT_BROADCAST = 2; 220 221 /** Process was started for a content provider component. */ 222 @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT) 223 public static final int START_COMPONENT_CONTENT_PROVIDER = 3; 224 225 /** Process was started for a service component. */ 226 @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT) 227 public static final int START_COMPONENT_SERVICE = 4; 228 229 /** Process was started not for one of the four standard components. */ 230 @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT) 231 public static final int START_COMPONENT_OTHER = 5; 232 233 /** 234 * @see #getMonotonicCreationTimeMs 235 */ 236 private long mMonotonicCreationTimeMs; 237 238 /** 239 * @see #getStartupState 240 */ 241 private @StartupState int mStartupState; 242 243 /** 244 * @see #getPid 245 */ 246 private int mPid; 247 248 /** 249 * @see #getRealUid 250 */ 251 private int mRealUid; 252 253 /** 254 * @see #getPackageUid 255 */ 256 private int mPackageUid; 257 258 /** 259 * @see #getDefiningUid 260 */ 261 private int mDefiningUid; 262 263 /** 264 * @see #getPackageName 265 */ 266 private String mPackageName; 267 268 /** 269 * @see #getProcessName 270 */ 271 private String mProcessName; 272 273 /** 274 * @see #getReason 275 */ 276 private @StartReason int mReason; 277 278 /** 279 * @see #getStartupTimestamps 280 */ 281 private ArrayMap<Integer, Long> mStartupTimestampsNs; 282 283 /** 284 * @see #getStartType 285 */ 286 private @StartType int mStartType; 287 288 /** 289 * @see #getIntent 290 */ 291 private Intent mStartIntent; 292 293 /** 294 * @see #getLaunchMode 295 */ 296 private @LaunchMode int mLaunchMode; 297 298 /** 299 * @see #wasForceStopped() 300 */ 301 private boolean mWasForceStopped; 302 303 /** 304 * @see #getStartComponent() 305 */ 306 private @StartComponent int mStartComponent; 307 308 /** 309 * @hide * 310 */ 311 @IntDef( 312 prefix = {"STARTUP_STATE_"}, 313 value = { 314 STARTUP_STATE_STARTED, 315 STARTUP_STATE_ERROR, 316 STARTUP_STATE_FIRST_FRAME_DRAWN, 317 }) 318 @Retention(RetentionPolicy.SOURCE) 319 public @interface StartupState {} 320 321 /** 322 * @hide * 323 */ 324 @IntDef( 325 prefix = {"START_REASON_"}, 326 value = { 327 START_REASON_ALARM, 328 START_REASON_BACKUP, 329 START_REASON_BOOT_COMPLETE, 330 START_REASON_BROADCAST, 331 START_REASON_CONTENT_PROVIDER, 332 START_REASON_JOB, 333 START_REASON_LAUNCHER, 334 START_REASON_LAUNCHER_RECENTS, 335 START_REASON_OTHER, 336 START_REASON_PUSH, 337 START_REASON_SERVICE, 338 START_REASON_START_ACTIVITY, 339 }) 340 @Retention(RetentionPolicy.SOURCE) 341 public @interface StartReason {} 342 343 /** 344 * @hide * 345 */ 346 @IntDef( 347 prefix = {"START_TYPE_"}, 348 value = { 349 START_TYPE_UNSET, 350 START_TYPE_COLD, 351 START_TYPE_WARM, 352 START_TYPE_HOT, 353 }) 354 @Retention(RetentionPolicy.SOURCE) 355 public @interface StartType {} 356 357 /** 358 * @hide * 359 */ 360 @IntDef( 361 prefix = {"LAUNCH_MODE_"}, 362 value = { 363 LAUNCH_MODE_STANDARD, 364 LAUNCH_MODE_SINGLE_TOP, 365 LAUNCH_MODE_SINGLE_INSTANCE, 366 LAUNCH_MODE_SINGLE_TASK, 367 LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK, 368 }) 369 @Retention(RetentionPolicy.SOURCE) 370 public @interface LaunchMode {} 371 372 /** 373 * @hide * 374 */ 375 @IntDef( 376 prefix = {"START_COMPONENT_"}, 377 value = { 378 START_COMPONENT_ACTIVITY, 379 START_COMPONENT_BROADCAST, 380 START_COMPONENT_CONTENT_PROVIDER, 381 START_COMPONENT_SERVICE, 382 START_COMPONENT_OTHER, 383 }) 384 @Retention(RetentionPolicy.SOURCE) 385 public @interface StartComponent {} 386 387 /** 388 * @see #getStartupState 389 * @hide 390 */ setStartupState(final @StartupState int startupState)391 public void setStartupState(final @StartupState int startupState) { 392 mStartupState = startupState; 393 } 394 395 /** 396 * @see #getPid 397 * @hide 398 */ setPid(final int pid)399 public void setPid(final int pid) { 400 mPid = pid; 401 } 402 403 /** 404 * @see #getRealUid 405 * @hide 406 */ setRealUid(final int uid)407 public void setRealUid(final int uid) { 408 mRealUid = uid; 409 } 410 411 /** 412 * @see #getPackageUid 413 * @hide 414 */ setPackageUid(final int uid)415 public void setPackageUid(final int uid) { 416 mPackageUid = uid; 417 } 418 419 /** 420 * @see #getDefiningUid 421 * @hide 422 */ setDefiningUid(final int uid)423 public void setDefiningUid(final int uid) { 424 mDefiningUid = uid; 425 } 426 427 /** 428 * @see #getPackageName 429 * @hide 430 */ setPackageName(final String packageName)431 public void setPackageName(final String packageName) { 432 mPackageName = intern(packageName); 433 } 434 435 /** 436 * @see #getProcessName 437 * @hide 438 */ setProcessName(final String processName)439 public void setProcessName(final String processName) { 440 mProcessName = intern(processName); 441 } 442 443 /** 444 * @see #getReason 445 * @hide 446 */ setReason(@tartReason int reason)447 public void setReason(@StartReason int reason) { 448 mReason = reason; 449 } 450 451 /** 452 * @see #getStartupTimestamps 453 * @hide 454 */ addStartupTimestamp(int key, long timestampNs)455 public void addStartupTimestamp(int key, long timestampNs) { 456 if (key < 0 || key > START_TIMESTAMP_RESERVED_RANGE_DEVELOPER) { 457 return; 458 } 459 if (mStartupTimestampsNs == null) { 460 mStartupTimestampsNs = new ArrayMap<Integer, Long>(); 461 } 462 mStartupTimestampsNs.put(key, timestampNs); 463 } 464 465 /** 466 * @see #getStartType 467 * @hide 468 */ setStartType(@tartType int startType)469 public void setStartType(@StartType int startType) { 470 mStartType = startType; 471 } 472 473 /** 474 * @see #getStartIntent 475 * 476 * <p class="note"> Note: This method will clone the provided intent and ensure that the cloned 477 * intent doesn't contain any large objects like bitmaps in its extras by stripping it in the 478 * least aggressive acceptable way for the individual intent.</p> 479 * 480 * @hide 481 */ setIntent(Intent startIntent)482 public void setIntent(Intent startIntent) { 483 if (startIntent != null) { 484 if (startIntent.canStripForHistory()) { 485 // If maybeStripForHistory will return a lightened version, do that. 486 mStartIntent = startIntent.maybeStripForHistory(); 487 } else if (startIntent.getExtras() != null) { 488 // If maybeStripForHistory would not return a lightened version and extras is 489 // non-null then extras contains un-parcelled data. Use cloneFilter to strip data 490 // more aggressively. 491 mStartIntent = startIntent.cloneFilter(); 492 } else { 493 // Finally, if maybeStripForHistory would not return a lightened version and extras 494 // is null then do a regular clone so we don't leak the intent. 495 mStartIntent = new Intent(startIntent); 496 } 497 498 // If the newly cloned intent has an original intent, clear that as we don't need it and 499 // can't guarantee it doesn't need to be stripped as well. 500 if (mStartIntent.getOriginalIntent() != null) { 501 mStartIntent.setOriginalIntent(null); 502 } 503 } 504 } 505 506 /** 507 * @see #getLaunchMode 508 * @hide 509 */ setLaunchMode(@aunchMode int launchMode)510 public void setLaunchMode(@LaunchMode int launchMode) { 511 mLaunchMode = launchMode; 512 } 513 514 /** 515 * @see #wasForceStopped() 516 * @param wasForceStopped whether the app had been force-stopped in the past 517 * @hide 518 */ setForceStopped(boolean wasForceStopped)519 public void setForceStopped(boolean wasForceStopped) { 520 mWasForceStopped = wasForceStopped; 521 } 522 523 /** 524 * @see #getStartComponent() 525 * @hide 526 */ setStartComponent(@tartComponent int startComponent)527 public void setStartComponent(@StartComponent int startComponent) { 528 mStartComponent = startComponent; 529 } 530 531 /** 532 * Current state of startup. 533 * 534 * Can be used to determine whether the object will have additional fields added as it may be 535 * queried before all data is collected. 536 * 537 * <p class="note"> Note: field will always be set and available.</p> 538 */ getStartupState()539 public @StartupState int getStartupState() { 540 return mStartupState; 541 } 542 543 /** 544 * Monotonic elapsed time persisted across reboots. 545 * 546 * @hide 547 */ getMonotonicCreationTimeMs()548 public long getMonotonicCreationTimeMs() { 549 return mMonotonicCreationTimeMs; 550 } 551 552 /** 553 * The process id. 554 * 555 * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> 556 */ getPid()557 public int getPid() { 558 return mPid; 559 } 560 561 /** 562 * The kernel user identifier of the process, most of the time the system uses this to do access 563 * control checks. It's typically the uid of the package where the component is running from, 564 * except the case of isolated process, where this field identifies the kernel user identifier 565 * that this process is actually running with, while the {@link #getPackageUid} identifies the 566 * kernel user identifier that is assigned at the package installation time. 567 * 568 * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> 569 */ getRealUid()570 public int getRealUid() { 571 return mRealUid; 572 } 573 574 /** 575 * Similar to {@link #getRealUid}, it's the kernel user identifier that is assigned at the 576 * package installation time. 577 * 578 * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> 579 */ getPackageUid()580 public int getPackageUid() { 581 return mPackageUid; 582 } 583 584 /** 585 * Return the defining kernel user identifier, maybe different from {@link #getRealUid} and 586 * {@link #getPackageUid}, if an external service has the {@link 587 * android.R.styleable#AndroidManifestService_useAppZygote android:useAppZygote} set to <code> 588 * true</code> and was bound with the flag {@link android.content.Context#BIND_EXTERNAL_SERVICE} 589 * - in this case, this field here will be the kernel user identifier of the external service 590 * provider. 591 * 592 * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> 593 */ getDefiningUid()594 public int getDefiningUid() { 595 return mDefiningUid; 596 } 597 598 /** 599 * Name of first package running in this process; 600 * 601 * @hide 602 */ getPackageName()603 public String getPackageName() { 604 return mPackageName; 605 } 606 607 /** 608 * The actual process name it was running with. 609 * 610 * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> 611 */ getProcessName()612 public @NonNull String getProcessName() { 613 return mProcessName; 614 } 615 616 /** 617 * The reason code of what triggered the process's start. 618 * 619 * Start reason provides granular reasoning on why the app is being started. Start reason should 620 * not be used for distinguishing between the component the app is being started for as some 621 * reasons may overlap with multiple components, see {@link #getStartComponent} for this 622 * functionality instead. 623 * 624 * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> 625 */ getReason()626 public @StartReason int getReason() { 627 return mReason; 628 } 629 630 /** 631 * Various clock monotonic timestamps in nanoseconds throughout the startup process. 632 * 633 * <p class="note"> Note: different timestamps will be available for different values of 634 * {@link #getStartupState}: 635 * 636 * (Subsequent rows contain all timestamps of proceding states.) 637 * 638 * For {@link #STARTUP_STATE_STARTED}, timestamp {@link #START_TIMESTAMP_LAUNCH} will be 639 * available. 640 * For {@link #STARTUP_STATE_ERROR}, no additional timestamps are guaranteed available. 641 * For {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}, timestamps 642 * {@link #START_TIMESTAMP_APPLICATION_ONCREATE}, {@link #START_TIMESTAMP_BIND_APPLICATION}, 643 * and {@link #START_TIMESTAMP_FIRST_FRAME} will additionally be available. 644 * 645 * Timestamp {@link #START_TIMESTAMP_FULLY_DRAWN} is never guaranteed to be available as it is 646 * dependant on devloper calling {@link Activity#reportFullyDrawn}. 647 * </p> 648 */ getStartupTimestamps()649 public @NonNull Map<Integer, Long> getStartupTimestamps() { 650 if (mStartupTimestampsNs == null) { 651 mStartupTimestampsNs = new ArrayMap<Integer, Long>(); 652 } 653 return mStartupTimestampsNs; 654 } 655 656 /** 657 * The state of the app at startup. 658 * 659 * <p class="note"> Note: field will be set for {@link #getStartupState} value 660 * {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}. Not guaranteed for other states.</p> 661 */ getStartType()662 public @StartType int getStartType() { 663 return mStartType; 664 } 665 666 /** 667 * The intent used to launch the application. 668 * 669 * <p class="note"> Note: Intent is stripped and does not include extras.</p> 670 * 671 * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> 672 */ 673 @SuppressLint("IntentBuilderName") 674 @Nullable getIntent()675 public Intent getIntent() { 676 return mStartIntent; 677 } 678 679 /** 680 * An instruction on how the activity should be launched. There are five modes that work in 681 * conjunction with activity flags in Intent objects to determine what should happen when the 682 * activity is called upon to handle an intent. 683 * 684 * Modes: 685 * {@link #LAUNCH_MODE_STANDARD} 686 * {@link #LAUNCH_MODE_SINGLE_TOP} 687 * {@link #LAUNCH_MODE_SINGLE_INSTANCE} 688 * {@link #LAUNCH_MODE_SINGLE_TASK} 689 * {@link #LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK} 690 * 691 * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> 692 */ getLaunchMode()693 public @LaunchMode int getLaunchMode() { 694 return mLaunchMode; 695 } 696 697 /** 698 * Informs whether this is the first process launch for an app since it was 699 * {@link ApplicationInfo#FLAG_STOPPED force-stopped} for some reason. 700 * This allows the app to know if it should re-register for any alarms, jobs and other callbacks 701 * that were cleared when the app was force-stopped. 702 * 703 * @return {@code true} if this is the first process launch of the app after having been 704 * stopped, {@code false} otherwise. 705 */ 706 @FlaggedApi(android.content.pm.Flags.FLAG_STAY_STOPPED) wasForceStopped()707 public boolean wasForceStopped() { 708 return mWasForceStopped; 709 } 710 711 /** 712 * The component type that was being started which triggered the start. 713 * 714 * Start component should be used to accurately distinguish between the 4 component types: 715 * activity, service, broadcast, and content provider. This can be useful for optimizing 716 * startup flow by enabling the caller to only load the necessary dependencies for a specific 717 * component type. For more granular information on why the app is being started, see 718 * {@link #getReason}. 719 * 720 * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> 721 */ 722 @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT) getStartComponent()723 public @StartComponent int getStartComponent() { 724 return mStartComponent; 725 } 726 727 @Override describeContents()728 public int describeContents() { 729 return 0; 730 } 731 732 // LINT.IfChange(write_parcel) 733 @Override writeToParcel(@onNull Parcel dest, int flags)734 public void writeToParcel(@NonNull Parcel dest, int flags) { 735 dest.writeInt(mStartupState); 736 dest.writeInt(mPid); 737 dest.writeInt(mRealUid); 738 dest.writeInt(mPackageUid); 739 dest.writeInt(mDefiningUid); 740 dest.writeString(mPackageName); 741 dest.writeString(mProcessName); 742 dest.writeInt(mReason); 743 dest.writeInt(mStartupTimestampsNs == null ? 0 : mStartupTimestampsNs.size()); 744 if (mStartupTimestampsNs != null) { 745 for (int i = 0; i < mStartupTimestampsNs.size(); i++) { 746 dest.writeInt(mStartupTimestampsNs.keyAt(i)); 747 dest.writeLong(mStartupTimestampsNs.valueAt(i)); 748 } 749 } 750 dest.writeInt(mStartType); 751 dest.writeParcelable(mStartIntent, flags); 752 dest.writeInt(mLaunchMode); 753 dest.writeBoolean(mWasForceStopped); 754 dest.writeLong(mMonotonicCreationTimeMs); 755 dest.writeInt(mStartComponent); 756 } 757 // LINT.ThenChange(:read_parcel) 758 759 /** @hide */ ApplicationStartInfo(long monotonicCreationTimeMs)760 public ApplicationStartInfo(long monotonicCreationTimeMs) { 761 mMonotonicCreationTimeMs = monotonicCreationTimeMs; 762 } 763 764 /** @hide */ ApplicationStartInfo(ApplicationStartInfo other)765 public ApplicationStartInfo(ApplicationStartInfo other) { 766 mStartupState = other.mStartupState; 767 mPid = other.mPid; 768 mRealUid = other.mRealUid; 769 mPackageUid = other.mPackageUid; 770 mDefiningUid = other.mDefiningUid; 771 mPackageName = other.mPackageName; 772 mProcessName = other.mProcessName; 773 mReason = other.mReason; 774 mStartupTimestampsNs = other.mStartupTimestampsNs; 775 mStartType = other.mStartType; 776 mStartIntent = other.mStartIntent; 777 mLaunchMode = other.mLaunchMode; 778 mWasForceStopped = other.mWasForceStopped; 779 mMonotonicCreationTimeMs = other.mMonotonicCreationTimeMs; 780 mStartComponent = other.mStartComponent; 781 } 782 783 /** @hide */ 784 // LINT.IfChange(read_parcel) 785 @VisibleForTesting ApplicationStartInfo(@onNull Parcel in)786 public ApplicationStartInfo(@NonNull Parcel in) { 787 mStartupState = in.readInt(); 788 mPid = in.readInt(); 789 mRealUid = in.readInt(); 790 mPackageUid = in.readInt(); 791 mDefiningUid = in.readInt(); 792 mPackageName = intern(in.readString()); 793 mProcessName = intern(in.readString()); 794 mReason = in.readInt(); 795 int starupTimestampCount = in.readInt(); 796 for (int i = 0; i < starupTimestampCount; i++) { 797 int key = in.readInt(); 798 long val = in.readLong(); 799 addStartupTimestamp(key, val); 800 } 801 mStartType = in.readInt(); 802 mStartIntent = 803 in.readParcelable(Intent.class.getClassLoader(), android.content.Intent.class); 804 mLaunchMode = in.readInt(); 805 mWasForceStopped = in.readBoolean(); 806 mMonotonicCreationTimeMs = in.readLong(); 807 mStartComponent = in.readInt(); 808 } 809 // LINT.ThenChange(:write_parcel) 810 intern(@ullable String source)811 private static String intern(@Nullable String source) { 812 return source != null ? source.intern() : null; 813 } 814 815 public @NonNull static final Creator<ApplicationStartInfo> CREATOR = 816 new Creator<ApplicationStartInfo>() { 817 @Override 818 public ApplicationStartInfo createFromParcel(Parcel in) { 819 return new ApplicationStartInfo(in); 820 } 821 822 @Override 823 public ApplicationStartInfo[] newArray(int size) { 824 return new ApplicationStartInfo[size]; 825 } 826 }; 827 828 private static final String PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS = "timestamps"; 829 private static final String PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP = "timestamp"; 830 private static final String PROTO_SERIALIZER_ATTRIBUTE_KEY = "key"; 831 private static final String PROTO_SERIALIZER_ATTRIBUTE_TS = "ts"; 832 private static final String PROTO_SERIALIZER_ATTRIBUTE_INTENT = "intent"; 833 834 /** 835 * Write to a protocol buffer output stream. Protocol buffer message definition at {@link 836 * android.app.ApplicationStartInfoProto} 837 * 838 * @param proto Stream to write the ApplicationStartInfo object to. 839 * @param fieldId Field Id of the ApplicationStartInfo as defined in the parent message 840 * @hide 841 */ 842 // LINT.IfChange(write_proto) writeToProto(ProtoOutputStream proto, long fieldId, ByteArrayOutputStream byteArrayOutputStream, ObjectOutputStream objectOutputStream, TypedXmlSerializer typedXmlSerializer)843 public void writeToProto(ProtoOutputStream proto, long fieldId, 844 ByteArrayOutputStream byteArrayOutputStream, ObjectOutputStream objectOutputStream, 845 TypedXmlSerializer typedXmlSerializer) throws IOException { 846 final long token = proto.start(fieldId); 847 proto.write(ApplicationStartInfoProto.PID, mPid); 848 proto.write(ApplicationStartInfoProto.REAL_UID, mRealUid); 849 proto.write(ApplicationStartInfoProto.PACKAGE_UID, mPackageUid); 850 proto.write(ApplicationStartInfoProto.DEFINING_UID, mDefiningUid); 851 proto.write(ApplicationStartInfoProto.PROCESS_NAME, mProcessName); 852 proto.write(ApplicationStartInfoProto.STARTUP_STATE, mStartupState); 853 proto.write(ApplicationStartInfoProto.REASON, mReason); 854 if (mStartupTimestampsNs != null && mStartupTimestampsNs.size() > 0) { 855 byteArrayOutputStream = new ByteArrayOutputStream(); 856 objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 857 typedXmlSerializer = Xml.resolveSerializer(objectOutputStream); 858 typedXmlSerializer.startDocument(null, true); 859 typedXmlSerializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS); 860 for (int i = 0; i < mStartupTimestampsNs.size(); i++) { 861 typedXmlSerializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP); 862 typedXmlSerializer.attributeInt(null, PROTO_SERIALIZER_ATTRIBUTE_KEY, 863 mStartupTimestampsNs.keyAt(i)); 864 typedXmlSerializer.attributeLong(null, PROTO_SERIALIZER_ATTRIBUTE_TS, 865 mStartupTimestampsNs.valueAt(i)); 866 typedXmlSerializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP); 867 } 868 typedXmlSerializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS); 869 typedXmlSerializer.endDocument(); 870 proto.write(ApplicationStartInfoProto.STARTUP_TIMESTAMPS, 871 byteArrayOutputStream.toByteArray()); 872 objectOutputStream.close(); 873 } 874 proto.write(ApplicationStartInfoProto.START_TYPE, mStartType); 875 if (mStartIntent != null) { 876 byteArrayOutputStream = new ByteArrayOutputStream(); 877 objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 878 typedXmlSerializer = Xml.resolveSerializer(objectOutputStream); 879 typedXmlSerializer.startDocument(null, true); 880 typedXmlSerializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT); 881 mStartIntent.saveToXml(typedXmlSerializer); 882 typedXmlSerializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT); 883 typedXmlSerializer.endDocument(); 884 proto.write(ApplicationStartInfoProto.START_INTENT, 885 byteArrayOutputStream.toByteArray()); 886 objectOutputStream.close(); 887 } 888 proto.write(ApplicationStartInfoProto.LAUNCH_MODE, mLaunchMode); 889 proto.write(ApplicationStartInfoProto.WAS_FORCE_STOPPED, mWasForceStopped); 890 proto.write(ApplicationStartInfoProto.MONOTONIC_CREATION_TIME_MS, mMonotonicCreationTimeMs); 891 proto.write(ApplicationStartInfoProto.START_COMPONENT, mStartComponent); 892 proto.end(token); 893 } 894 // LINT.ThenChange(:read_proto) 895 896 /** 897 * Read from a protocol buffer input stream. Protocol buffer message definition at {@link 898 * android.app.ApplicationStartInfoProto} 899 * 900 * @param proto Stream to read the ApplicationStartInfo object from. 901 * @param fieldId Field Id of the ApplicationStartInfo as defined in the parent message 902 * @hide 903 */ 904 // LINT.IfChange(read_proto) readFromProto(ProtoInputStream proto, long fieldId, ByteArrayInputStream byteArrayInputStream, ObjectInputStream objectInputStream, TypedXmlPullParser typedXmlPullParser)905 public void readFromProto(ProtoInputStream proto, long fieldId, 906 ByteArrayInputStream byteArrayInputStream, ObjectInputStream objectInputStream, 907 TypedXmlPullParser typedXmlPullParser) 908 throws IOException, WireTypeMismatchException, ClassNotFoundException { 909 final long token = proto.start(fieldId); 910 while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 911 switch (proto.getFieldNumber()) { 912 case (int) ApplicationStartInfoProto.PID: 913 mPid = proto.readInt(ApplicationStartInfoProto.PID); 914 break; 915 case (int) ApplicationStartInfoProto.REAL_UID: 916 mRealUid = proto.readInt(ApplicationStartInfoProto.REAL_UID); 917 break; 918 case (int) ApplicationStartInfoProto.PACKAGE_UID: 919 mPackageUid = proto.readInt(ApplicationStartInfoProto.PACKAGE_UID); 920 break; 921 case (int) ApplicationStartInfoProto.DEFINING_UID: 922 mDefiningUid = proto.readInt(ApplicationStartInfoProto.DEFINING_UID); 923 break; 924 case (int) ApplicationStartInfoProto.PROCESS_NAME: 925 mProcessName = intern(proto.readString(ApplicationStartInfoProto.PROCESS_NAME)); 926 break; 927 case (int) ApplicationStartInfoProto.STARTUP_STATE: 928 mStartupState = proto.readInt(ApplicationStartInfoProto.STARTUP_STATE); 929 break; 930 case (int) ApplicationStartInfoProto.REASON: 931 mReason = proto.readInt(ApplicationStartInfoProto.REASON); 932 break; 933 case (int) ApplicationStartInfoProto.STARTUP_TIMESTAMPS: 934 byteArrayInputStream = new ByteArrayInputStream(proto.readBytes( 935 ApplicationStartInfoProto.STARTUP_TIMESTAMPS)); 936 objectInputStream = new ObjectInputStream(byteArrayInputStream); 937 mStartupTimestampsNs = new ArrayMap<Integer, Long>(); 938 try { 939 typedXmlPullParser = Xml.resolvePullParser(objectInputStream); 940 XmlUtils.beginDocument(typedXmlPullParser, 941 PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS); 942 int depth = typedXmlPullParser.getDepth(); 943 while (XmlUtils.nextElementWithin(typedXmlPullParser, depth)) { 944 if (PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP.equals( 945 typedXmlPullParser.getName())) { 946 int key = typedXmlPullParser.getAttributeInt(null, 947 PROTO_SERIALIZER_ATTRIBUTE_KEY); 948 long ts = typedXmlPullParser.getAttributeLong(null, 949 PROTO_SERIALIZER_ATTRIBUTE_TS); 950 mStartupTimestampsNs.put(key, ts); 951 } 952 } 953 } catch (XmlPullParserException e) { 954 // Timestamps lost 955 } 956 objectInputStream.close(); 957 break; 958 case (int) ApplicationStartInfoProto.START_TYPE: 959 mStartType = proto.readInt(ApplicationStartInfoProto.START_TYPE); 960 break; 961 case (int) ApplicationStartInfoProto.START_INTENT: 962 byteArrayInputStream = new ByteArrayInputStream(proto.readBytes( 963 ApplicationStartInfoProto.START_INTENT)); 964 objectInputStream = new ObjectInputStream(byteArrayInputStream); 965 try { 966 typedXmlPullParser = Xml.resolvePullParser(objectInputStream); 967 XmlUtils.beginDocument(typedXmlPullParser, 968 PROTO_SERIALIZER_ATTRIBUTE_INTENT); 969 mStartIntent = Intent.restoreFromXml(typedXmlPullParser); 970 } catch (XmlPullParserException e) { 971 // Intent lost 972 } 973 objectInputStream.close(); 974 break; 975 case (int) ApplicationStartInfoProto.LAUNCH_MODE: 976 mLaunchMode = proto.readInt(ApplicationStartInfoProto.LAUNCH_MODE); 977 break; 978 case (int) ApplicationStartInfoProto.WAS_FORCE_STOPPED: 979 mWasForceStopped = proto.readBoolean( 980 ApplicationStartInfoProto.WAS_FORCE_STOPPED); 981 break; 982 case (int) ApplicationStartInfoProto.MONOTONIC_CREATION_TIME_MS: 983 mMonotonicCreationTimeMs = proto.readLong( 984 ApplicationStartInfoProto.MONOTONIC_CREATION_TIME_MS); 985 break; 986 case (int) ApplicationStartInfoProto.START_COMPONENT: 987 mStartComponent = proto.readInt(ApplicationStartInfoProto.START_COMPONENT); 988 break; 989 } 990 } 991 proto.end(token); 992 } 993 // LINT.ThenChange(:write_proto) 994 995 /** @hide */ dump(@onNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix, @NonNull SimpleDateFormat sdf)996 public void dump(@NonNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix, 997 @NonNull SimpleDateFormat sdf) { 998 StringBuilder sb = new StringBuilder(); 999 sb.append(prefix) 1000 .append("ApplicationStartInfo ").append(seqSuffix).append(':') 1001 .append('\n') 1002 .append(" monotonicCreationTimeMs=").append(mMonotonicCreationTimeMs) 1003 .append('\n') 1004 .append(" pid=").append(mPid) 1005 .append(" realUid=").append(mRealUid) 1006 .append(" packageUid=").append(mPackageUid) 1007 .append(" definingUid=").append(mDefiningUid) 1008 .append(" user=").append(UserHandle.getUserId(mPackageUid)) 1009 .append('\n') 1010 .append(" package=").append(mPackageName) 1011 .append(" process=").append(mProcessName) 1012 .append(" startupState=").append(mStartupState) 1013 .append(" reason=").append(reasonToString(mReason)) 1014 .append(" startType=").append(startTypeToString(mStartType)) 1015 .append(" launchMode=").append(mLaunchMode) 1016 .append(" wasForceStopped=").append(mWasForceStopped); 1017 if (Flags.appStartInfoComponent()) { 1018 sb.append(" startComponent=").append(startComponentToString(mStartComponent)); 1019 } 1020 sb.append('\n'); 1021 if (mStartIntent != null) { 1022 sb.append(" intent=").append(mStartIntent.toString()) 1023 .append('\n'); 1024 } 1025 if (mStartupTimestampsNs != null && mStartupTimestampsNs.size() > 0) { 1026 sb.append(" timestamps: "); 1027 for (int i = 0; i < mStartupTimestampsNs.size(); i++) { 1028 sb.append(mStartupTimestampsNs.keyAt(i)).append("=").append(mStartupTimestampsNs 1029 .valueAt(i)).append(" "); 1030 } 1031 sb.append('\n'); 1032 } 1033 pw.print(sb.toString()); 1034 } 1035 reasonToString(@tartReason int reason)1036 private static String reasonToString(@StartReason int reason) { 1037 return switch (reason) { 1038 case START_REASON_ALARM -> "ALARM"; 1039 case START_REASON_BACKUP -> "BACKUP"; 1040 case START_REASON_BOOT_COMPLETE -> "BOOT COMPLETE"; 1041 case START_REASON_BROADCAST -> "BROADCAST"; 1042 case START_REASON_CONTENT_PROVIDER -> "CONTENT PROVIDER"; 1043 case START_REASON_JOB -> "JOB"; 1044 case START_REASON_LAUNCHER -> "LAUNCHER"; 1045 case START_REASON_LAUNCHER_RECENTS -> "LAUNCHER RECENTS"; 1046 case START_REASON_OTHER -> "OTHER"; 1047 case START_REASON_PUSH -> "PUSH"; 1048 case START_REASON_SERVICE -> "SERVICE"; 1049 case START_REASON_START_ACTIVITY -> "START ACTIVITY"; 1050 default -> ""; 1051 }; 1052 } 1053 startTypeToString(@tartType int startType)1054 private static String startTypeToString(@StartType int startType) { 1055 return switch (startType) { 1056 case START_TYPE_UNSET -> "UNSET"; 1057 case START_TYPE_COLD -> "COLD"; 1058 case START_TYPE_WARM -> "WARM"; 1059 case START_TYPE_HOT -> "HOT"; 1060 default -> ""; 1061 }; 1062 } 1063 1064 @FlaggedApi(Flags.FLAG_APP_START_INFO_COMPONENT) 1065 private static String startComponentToString(@StartComponent int startComponent) { 1066 return switch (startComponent) { 1067 case START_COMPONENT_ACTIVITY -> "ACTIVITY"; 1068 case START_COMPONENT_BROADCAST -> "BROADCAST"; 1069 case START_COMPONENT_CONTENT_PROVIDER -> "CONTENT PROVIDER"; 1070 case START_COMPONENT_SERVICE -> "SERVICE"; 1071 case START_COMPONENT_OTHER -> "OTHER"; 1072 default -> ""; 1073 }; 1074 } 1075 1076 /** @hide */ 1077 @Override 1078 public boolean equals(@Nullable Object other) { 1079 if (other == null || !(other instanceof ApplicationStartInfo)) { 1080 return false; 1081 } 1082 1083 final ApplicationStartInfo o = (ApplicationStartInfo) other; 1084 1085 boolean intentEquals = true; 1086 if (android.content.flags.Flags.intentSaveToXmlPackage()) { 1087 if (mStartIntent == null) { 1088 intentEquals = o.mStartIntent == null; 1089 } else { 1090 intentEquals = mStartIntent.filterEquals(o.mStartIntent); 1091 } 1092 } 1093 1094 return mPid == o.mPid 1095 && mRealUid == o.mRealUid 1096 && mPackageUid == o.mPackageUid 1097 && mDefiningUid == o.mDefiningUid 1098 && mReason == o.mReason 1099 && mStartupState == o.mStartupState 1100 && mStartType == o.mStartType 1101 && mLaunchMode == o.mLaunchMode 1102 && TextUtils.equals(mPackageName, o.mPackageName) 1103 && TextUtils.equals(mProcessName, o.mProcessName) 1104 && timestampsEquals(o) 1105 && mWasForceStopped == o.mWasForceStopped 1106 && mMonotonicCreationTimeMs == o.mMonotonicCreationTimeMs 1107 && mStartComponent == o.mStartComponent 1108 && intentEquals; 1109 } 1110 1111 @Override 1112 public int hashCode() { 1113 return Objects.hash(mPid, mRealUid, mPackageUid, mDefiningUid, mReason, mStartupState, 1114 mStartType, mLaunchMode, mPackageName, mProcessName, mStartupTimestampsNs, 1115 mMonotonicCreationTimeMs, mStartComponent, 1116 android.content.flags.Flags.intentSaveToXmlPackage() ? mStartIntent : null); 1117 } 1118 1119 private boolean timestampsEquals(@NonNull ApplicationStartInfo other) { 1120 if (mStartupTimestampsNs == null && other.mStartupTimestampsNs == null) { 1121 return true; 1122 } 1123 if (mStartupTimestampsNs == null || other.mStartupTimestampsNs == null) { 1124 return false; 1125 } 1126 return mStartupTimestampsNs.equals(other.mStartupTimestampsNs); 1127 } 1128 } 1129