• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.CurrentTimeMillisLong;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.app.ActivityManager.RunningAppProcessInfo.Importance;
24 import android.icu.text.SimpleDateFormat;
25 import android.os.Parcel;
26 import android.os.ParcelFileDescriptor;
27 import android.os.Parcelable;
28 import android.os.RemoteException;
29 import android.os.UserHandle;
30 import android.text.TextUtils;
31 import android.util.DebugUtils;
32 import android.util.proto.ProtoInputStream;
33 import android.util.proto.ProtoOutputStream;
34 import android.util.proto.WireTypeMismatchException;
35 
36 import com.android.internal.util.ArrayUtils;
37 
38 import java.io.File;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.io.PrintWriter;
42 import java.lang.annotation.Retention;
43 import java.lang.annotation.RetentionPolicy;
44 import java.util.Date;
45 import java.util.Objects;
46 import java.util.zip.GZIPInputStream;
47 
48 /**
49  * Describes the information of an application process's death.
50  *
51  * <p>
52  * Application process could die for many reasons, for example {@link #REASON_LOW_MEMORY}
53  * when it was killed by the ystem because it was running low on memory. Reason
54  * of the death can be retrieved via {@link #getReason}. Besides the reason, there are a few other
55  * auxiliary APIs like {@link #getStatus} and {@link #getImportance} to help the caller with
56  * additional diagnostic information.
57  * </p>
58  *
59  */
60 public final class ApplicationExitInfo implements Parcelable {
61 
62     /**
63      * Application process died due to unknown reason.
64      */
65     public static final int REASON_UNKNOWN = 0;
66 
67     /**
68      * Application process exit normally by itself, for example,
69      * via {@link java.lang.System#exit}; {@link #getStatus} will specify the exit code.
70      *
71      * <p>Applications should normally not do this, as the system has a better knowledge
72      * in terms of process management.</p>
73      */
74     public static final int REASON_EXIT_SELF = 1;
75 
76     /**
77      * Application process died due to the result of an OS signal; for example,
78      * {@link android.system.OsConstants#SIGKILL}; {@link #getStatus} will specify the signal
79      * number.
80      */
81     public static final int REASON_SIGNALED = 2;
82 
83     /**
84      * Application process was killed by the system low memory killer, meaning the system was
85      * under memory pressure at the time of kill.
86      *
87      * <p class="note">
88      * Not all devices support reporting {@link #REASON_LOW_MEMORY}; on a device with no such
89      * support, when a process is killed due to memory pressure, the {@link #getReason} will return
90      * {@link #REASON_SIGNALED} and {@link #getStatus} will return
91      * the value {@link android.system.OsConstants#SIGKILL}.
92      *
93      * Application should use {@link android.app.ActivityManager#isLowMemoryKillReportSupported()
94      * ActivityManager.isLowMemoryKillReportSupported()} to check
95      * if the device supports reporting {@link #REASON_LOW_MEMORY} or not.
96      * </p>
97      */
98     public static final int REASON_LOW_MEMORY = 3;
99 
100     /**
101      * Application process died because of an unhandled exception in Java code.
102      */
103     public static final int REASON_CRASH = 4;
104 
105     /**
106      * Application process died because of a native code crash.
107      */
108     public static final int REASON_CRASH_NATIVE = 5;
109 
110     /**
111      * Application process was killed due to being unresponsive (ANR).
112      */
113     public static final int REASON_ANR = 6;
114 
115     /**
116      * Application process was killed because of initialization failure,
117      * for example, it took too long to attach to the system during the start,
118      * or there was an error during initialization.
119      */
120     public static final int REASON_INITIALIZATION_FAILURE = 7;
121 
122     /**
123      * Application process was killed due to a runtime permission change.
124      */
125     public static final int REASON_PERMISSION_CHANGE = 8;
126 
127     /**
128      * Application process was killed by the system due to excessive resource usage.
129      */
130     public static final int REASON_EXCESSIVE_RESOURCE_USAGE = 9;
131 
132     /**
133      * Application process was killed because of the user request, for example,
134      * user clicked the "Force stop" button of the application in the Settings,
135      * or removed the application away from Recents.
136      */
137     public static final int REASON_USER_REQUESTED = 10;
138 
139     /**
140      * Application process was killed, because the user it is running as on devices
141      * with mutlple users, was stopped.
142      */
143     public static final int REASON_USER_STOPPED = 11;
144 
145     /**
146      * Application process was killed because its dependency was going away, for example,
147      * a stable content provider connection's client will be killed if the provider is killed.
148      */
149     public static final int REASON_DEPENDENCY_DIED = 12;
150 
151     /**
152      * Application process was killed by the system for various other reasons which are
153      * not by problems in apps and not actionable by apps, for example, the system just
154      * finished updates; {@link #getDescription} will specify the cause given by the system.
155      */
156     public static final int REASON_OTHER = 13;
157 
158     /**
159      * Application process kills subreason is unknown.
160      *
161      * For internal use only.
162      * @hide
163      */
164     public static final int SUBREASON_UNKNOWN = 0;
165 
166     /**
167      * Application process was killed because user quit it on the "wait for debugger" dialog;
168      * this would be set when the reason is {@link #REASON_OTHER}.
169      *
170      * For internal use only.
171      * @hide
172      */
173     public static final int SUBREASON_WAIT_FOR_DEBUGGER = 1;
174 
175     /**
176      * Application process was killed by the activity manager because there were too many cached
177      * processes; this would be set only when the reason is {@link #REASON_OTHER}.
178      *
179      * For internal use only.
180      * @hide
181      */
182     public static final int SUBREASON_TOO_MANY_CACHED = 2;
183 
184     /**
185      * Application process was killed by the activity manager because there were too many empty
186      * processes; this would be set only when the reason is {@link #REASON_OTHER}.
187      *
188      * For internal use only.
189      * @hide
190      */
191     public static final int SUBREASON_TOO_MANY_EMPTY = 3;
192 
193     /**
194      * Application process was killed by the activity manager because there were too many cached
195      * processes and this process had been in empty state for a long time;
196      * this would be set only when the reason is {@link #REASON_OTHER}.
197      *
198      * For internal use only.
199      * @hide
200      */
201     public static final int SUBREASON_TRIM_EMPTY = 4;
202 
203     /**
204      * Application process was killed by the activity manager because system was on memory pressure
205      * and this process took large amount of cached memory;
206      * this would be set only when the reason is {@link #REASON_OTHER}.
207      *
208      * For internal use only.
209      * @hide
210      */
211     public static final int SUBREASON_LARGE_CACHED = 5;
212 
213     /**
214      * Application process was killed by the activity manager because the system was on low memory
215      * pressure for a significant amount of time since last idle;
216      * this would be set only when the reason is {@link #REASON_OTHER}.
217      *
218      * For internal use only.
219      * @hide
220      */
221     public static final int SUBREASON_MEMORY_PRESSURE = 6;
222 
223     /**
224      * Application process was killed by the activity manager due to excessive CPU usage;
225      * this would be set only when the reason is {@link #REASON_EXCESSIVE_RESOURCE_USAGE}.
226      *
227      * For internal use only.
228      * @hide
229      */
230     public static final int SUBREASON_EXCESSIVE_CPU = 7;
231 
232     /**
233      * System update has done (so the system update process should be killed);
234      * this would be set only when the reason is {@link #REASON_OTHER}.
235      *
236      * For internal use only.
237      * @hide
238      */
239     public static final int SUBREASON_SYSTEM_UPDATE_DONE = 8;
240 
241     /**
242      * Kill all foreground services, for now it only occurs when enabling the quiet
243      * mode for the managed profile;
244      * this would be set only when the reason is {@link #REASON_OTHER}.
245      *
246      * For internal use only.
247      * @hide
248      */
249     public static final int SUBREASON_KILL_ALL_FG = 9;
250 
251     /**
252      * All background processes except certain ones were killed, for now it only occurs
253      * when the density of the default display is changed;
254      * this would be set only when the reason is {@link #REASON_OTHER}.
255      *
256      * For internal use only.
257      * @hide
258      */
259     public static final int SUBREASON_KILL_ALL_BG_EXCEPT = 10;
260 
261     /**
262      * The process associated with the UID was explicitly killed, for example,
263      * it could be because of platform compatibility overrides;
264      * this would be set only when the reason is {@link #REASON_OTHER}.
265      *
266      * For internal use only.
267      * @hide
268      */
269     public static final int SUBREASON_KILL_UID = 11;
270 
271     /**
272      * The process was explicitly killed with its PID, typically because of
273      * the low memory for surfaces;
274      * this would be set only when the reason is {@link #REASON_OTHER}.
275      *
276      * For internal use only.
277      * @hide
278      */
279     public static final int SUBREASON_KILL_PID = 12;
280 
281     /**
282      * The start of the process was invalid;
283      * this would be set only when the reason is {@link #REASON_OTHER}.
284      *
285      * For internal use only.
286      * @hide
287      */
288     public static final int SUBREASON_INVALID_START = 13;
289 
290     /**
291      * The process was killed because it's in an invalid state, typically
292      * it's triggered from SHELL;
293      * this would be set only when the reason is {@link #REASON_OTHER}.
294      *
295      * For internal use only.
296      * @hide
297      */
298     public static final int SUBREASON_INVALID_STATE = 14;
299 
300     /**
301      * The process was killed when it's imperceptible to user, because it was
302      * in a bad state;
303      * this would be set only when the reason is {@link #REASON_OTHER}.
304      *
305      * For internal use only.
306      * @hide
307      */
308     public static final int SUBREASON_IMPERCEPTIBLE = 15;
309 
310     /**
311      * The process was killed because it's being moved out from LRU list;
312      * this would be set only when the reason is {@link #REASON_OTHER}.
313      *
314      * For internal use only.
315      * @hide
316      */
317     public static final int SUBREASON_REMOVE_LRU = 16;
318 
319     /**
320      * The process was killed because it's isolated and was in a cached state;
321      * this would be set only when the reason is {@link #REASON_OTHER}.
322      *
323      * For internal use only.
324      * @hide
325      */
326     public static final int SUBREASON_ISOLATED_NOT_NEEDED = 17;
327 
328     // If there is any OEM code which involves additional app kill reasons, it should
329     // be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000.
330 
331     /**
332      * @see #getPid
333      */
334     private int mPid;
335 
336     /**
337      * @see #getRealUid
338      */
339     private int mRealUid;
340 
341     /**
342      * @see #getPackageUid
343      */
344     private int mPackageUid;
345 
346     /**
347      * @see #getDefiningUid
348      */
349     private int mDefiningUid;
350 
351     /**
352      * @see #getProcessName
353      */
354     private String mProcessName;
355 
356     /**
357      * @see #getReason
358      */
359     private @Reason int mReason;
360 
361     /**
362      * @see #getStatus
363      */
364     private int mStatus;
365 
366     /**
367      * @see #getImportance
368      */
369     private @Importance int mImportance;
370 
371     /**
372      * @see #getPss
373      */
374     private long mPss;
375 
376     /**
377      * @see #getRss
378      */
379     private long mRss;
380 
381     /**
382      * @see #getTimestamp
383      */
384     private @CurrentTimeMillisLong long mTimestamp;
385 
386     /**
387      * @see #getDescription
388      */
389     private @Nullable String mDescription;
390 
391     /**
392      * @see #getSubReason
393      */
394     private @SubReason int mSubReason;
395 
396     /**
397      * @see #getConnectionGroup
398      */
399     private int mConnectionGroup;
400 
401     /**
402      * @see #getPackageName
403      */
404     private String mPackageName;
405 
406     /**
407      * @see #getPackageList
408      */
409     private String[] mPackageList;
410 
411     /**
412      * @see #getProcessStateSummary
413      */
414     private byte[] mState;
415 
416     /**
417      * The file to the trace file in the storage;
418      *
419      * for system internal use only, will not retain across processes.
420      *
421      * @see #getTraceInputStream
422      */
423     private File mTraceFile;
424 
425     /**
426      * The Binder interface to retrieve the file descriptor to
427      * the trace file from the system.
428      */
429     private IAppTraceRetriever mAppTraceRetriever;
430 
431     /** @hide */
432     @IntDef(prefix = { "REASON_" }, value = {
433         REASON_UNKNOWN,
434         REASON_EXIT_SELF,
435         REASON_SIGNALED,
436         REASON_LOW_MEMORY,
437         REASON_CRASH,
438         REASON_CRASH_NATIVE,
439         REASON_ANR,
440         REASON_INITIALIZATION_FAILURE,
441         REASON_PERMISSION_CHANGE,
442         REASON_EXCESSIVE_RESOURCE_USAGE,
443         REASON_USER_REQUESTED,
444         REASON_USER_STOPPED,
445         REASON_DEPENDENCY_DIED,
446         REASON_OTHER,
447     })
448     @Retention(RetentionPolicy.SOURCE)
449     public @interface Reason {}
450 
451     /** @hide */
452     @IntDef(prefix = { "SUBREASON_" }, value = {
453         SUBREASON_UNKNOWN,
454         SUBREASON_WAIT_FOR_DEBUGGER,
455         SUBREASON_TOO_MANY_CACHED,
456         SUBREASON_TOO_MANY_EMPTY,
457         SUBREASON_TRIM_EMPTY,
458         SUBREASON_LARGE_CACHED,
459         SUBREASON_MEMORY_PRESSURE,
460         SUBREASON_EXCESSIVE_CPU,
461         SUBREASON_SYSTEM_UPDATE_DONE,
462         SUBREASON_KILL_ALL_FG,
463         SUBREASON_KILL_ALL_BG_EXCEPT,
464         SUBREASON_KILL_UID,
465         SUBREASON_KILL_PID,
466         SUBREASON_INVALID_START,
467         SUBREASON_INVALID_STATE,
468         SUBREASON_IMPERCEPTIBLE,
469         SUBREASON_REMOVE_LRU,
470         SUBREASON_ISOLATED_NOT_NEEDED,
471     })
472     @Retention(RetentionPolicy.SOURCE)
473     public @interface SubReason {}
474 
475     /**
476      * The process id of the process that died.
477      */
getPid()478     public int getPid() {
479         return mPid;
480     }
481 
482     /**
483      * The kernel user identifier of the process, most of the time the system uses this
484      * to do access control checks. It's typically the uid of the package where the component is
485      * running from, except the case of isolated process, where this field identifies the kernel
486      * user identifier that this process is actually running with, while the {@link #getPackageUid}
487      * identifies the kernel user identifier that is assigned at the package installation time.
488      */
getRealUid()489     public int getRealUid() {
490         return mRealUid;
491     }
492 
493     /**
494      * Similar to {@link #getRealUid}, it's the kernel user identifier that is assigned at the
495      * package installation time.
496      */
getPackageUid()497     public int getPackageUid() {
498         return mPackageUid;
499     }
500 
501     /**
502      * Return the defining kernel user identifier, maybe different from {@link #getRealUid} and
503      * {@link #getPackageUid}, if an external service has the
504      * {@link android.R.styleable#AndroidManifestService_useAppZygote android:useAppZygote} set
505      * to <code>true</code> and was bound with the flag
506      * {@link android.content.Context#BIND_EXTERNAL_SERVICE} - in this case, this field here will
507      * be the kernel user identifier of the external service provider.
508      */
getDefiningUid()509     public int getDefiningUid() {
510         return mDefiningUid;
511     }
512 
513     /**
514      * The actual process name it was running with.
515      */
getProcessName()516     public @NonNull String getProcessName() {
517         return mProcessName;
518     }
519 
520     /**
521      * The reason code of the process's death.
522      */
getReason()523     public @Reason int getReason() {
524         return mReason;
525     }
526 
527     /**
528      * The exit status argument of exit() if the application calls it, or the signal
529      * number if the application is signaled.
530      */
getStatus()531     public int getStatus() {
532         return mStatus;
533     }
534 
535     /**
536      * The importance of the process that it used to have before the death.
537      */
getImportance()538     public @Importance int getImportance() {
539         return mImportance;
540     }
541 
542     /**
543      * Last proportional set size of the memory that the process had used in kB.
544      *
545      * <p class="note">Note: This is the value from last sampling on the process,
546      * it's NOT the exact memory information prior to its death; and it'll be zero
547      * if the process died before system had a chance to take the sample. </p>
548      */
getPss()549     public long getPss() {
550         return mPss;
551     }
552 
553     /**
554      * Last resident set size of the memory that the process had used in kB.
555      *
556      * <p class="note">Note: This is the value from last sampling on the process,
557      * it's NOT the exact memory information prior to its death; and it'll be zero
558      * if the process died before system had a chance to take the sample. </p>
559      */
getRss()560     public long getRss() {
561         return mRss;
562     }
563 
564     /**
565      * The timestamp of the process's death, in milliseconds since the epoch,
566      * as returned by {@link java.lang.System#currentTimeMillis() System.currentTimeMillis()}.
567      */
getTimestamp()568     public @CurrentTimeMillisLong long getTimestamp() {
569         return mTimestamp;
570     }
571 
572     /**
573      * The human readable description of the process's death, given by the system; could be null.
574      *
575      * <p class="note">Note: only intended to be human-readable and the system provides no
576      * guarantees that the format is stable across devices or Android releases.</p>
577      */
getDescription()578     public @Nullable String getDescription() {
579         return mDescription;
580     }
581 
582     /**
583      * Return the user id of the record on a multi-user system.
584      */
getUserHandle()585     public @NonNull UserHandle getUserHandle() {
586         return UserHandle.of(UserHandle.getUserId(mRealUid));
587     }
588 
589     /**
590      * Return the state data set by calling
591      * {@link android.app.ActivityManager#setProcessStateSummary(byte[])
592      * ActivityManager.setProcessStateSummary(byte[])} from the process before its death.
593      *
594      * @return The process-customized data
595      * @see ActivityManager#setProcessStateSummary(byte[])
596      */
getProcessStateSummary()597     public @Nullable byte[] getProcessStateSummary() {
598         return mState;
599     }
600 
601     /**
602      * Return the InputStream to the traces that was taken by the system
603      * prior to the death of the process; typically it'll be available when
604      * the reason is {@link #REASON_ANR}, though if the process gets an ANR
605      * but recovers, and dies for another reason later, this trace will be included
606      * in the record of {@link ApplicationExitInfo} still.
607      *
608      * @return The input stream to the traces that was taken by the system
609      *         prior to the death of the process.
610      */
getTraceInputStream()611     public @Nullable InputStream getTraceInputStream() throws IOException {
612         if (mAppTraceRetriever == null) {
613             return null;
614         }
615         try {
616             final ParcelFileDescriptor fd = mAppTraceRetriever.getTraceFileDescriptor(
617                     mPackageName, mPackageUid, mPid);
618             if (fd == null) {
619                 return null;
620             }
621             return new GZIPInputStream(new ParcelFileDescriptor.AutoCloseInputStream(fd));
622         } catch (RemoteException e) {
623             return null;
624         }
625     }
626 
627     /**
628      * Similar to {@link #getTraceInputStream} but return the File object.
629      *
630      * For internal use only.
631      *
632      * @hide
633      */
getTraceFile()634     public @Nullable File getTraceFile() {
635         return mTraceFile;
636     }
637 
638     /**
639      * A subtype reason in conjunction with {@link #mReason}.
640      *
641      * For internal use only.
642      *
643      * @hide
644      */
getSubReason()645     public @SubReason int getSubReason() {
646         return mSubReason;
647     }
648 
649     /**
650      * The connection group this process belongs to, if there is any.
651      * @see android.content.Context#updateServiceGroup
652      *
653      * For internal use only.
654      *
655      * @hide
656      */
getConnectionGroup()657     public int getConnectionGroup() {
658         return mConnectionGroup;
659     }
660 
661     /**
662      * Name of first package running in this process;
663      *
664      * @hide
665      */
getPackageName()666     public String getPackageName() {
667         return mPackageName;
668     }
669 
670     /**
671      * List of packages running in this process;
672      *
673      * For system internal use only, will not retain across processes.
674      *
675      * @hide
676      */
getPackageList()677     public String[] getPackageList() {
678         return mPackageList;
679     }
680 
681     /**
682      * @see #getPid
683      *
684      * @hide
685      */
setPid(final int pid)686     public void setPid(final int pid) {
687         mPid = pid;
688     }
689 
690     /**
691      * @see #getRealUid
692      *
693      * @hide
694      */
setRealUid(final int uid)695     public void setRealUid(final int uid) {
696         mRealUid = uid;
697     }
698 
699     /**
700      * @see #getPackageUid
701      *
702      * @hide
703      */
setPackageUid(final int uid)704     public void setPackageUid(final int uid) {
705         mPackageUid = uid;
706     }
707 
708     /**
709      * @see #getDefiningUid
710      *
711      * @hide
712      */
setDefiningUid(final int uid)713     public void setDefiningUid(final int uid) {
714         mDefiningUid = uid;
715     }
716 
717     /**
718      * @see #getProcessName
719      *
720      * @hide
721      */
setProcessName(final String processName)722     public void setProcessName(final String processName) {
723         mProcessName = processName;
724     }
725 
726     /**
727      * @see #getReason
728      *
729      * @hide
730      */
setReason(final @Reason int reason)731     public void setReason(final @Reason int reason) {
732         mReason = reason;
733     }
734 
735     /**
736      * @see #getStatus
737      *
738      * @hide
739      */
setStatus(final int status)740     public void setStatus(final int status) {
741         mStatus = status;
742     }
743 
744     /**
745      * @see #getImportance
746      *
747      * @hide
748      */
setImportance(final @Importance int importance)749     public void setImportance(final @Importance int importance) {
750         mImportance = importance;
751     }
752 
753     /**
754      * @see #getPss
755      *
756      * @hide
757      */
setPss(final long pss)758     public void setPss(final long pss) {
759         mPss = pss;
760     }
761 
762     /**
763      * @see #getRss
764      *
765      * @hide
766      */
setRss(final long rss)767     public void setRss(final long rss) {
768         mRss = rss;
769     }
770 
771     /**
772      * @see #getTimestamp
773      *
774      * @hide
775      */
setTimestamp(final @CurrentTimeMillisLong long timestamp)776     public void setTimestamp(final @CurrentTimeMillisLong long timestamp) {
777         mTimestamp = timestamp;
778     }
779 
780     /**
781      * @see #getDescription
782      *
783      * @hide
784      */
setDescription(final String description)785     public void setDescription(final String description) {
786         mDescription = description;
787     }
788 
789     /**
790      * @see #getSubReason
791      *
792      * @hide
793      */
setSubReason(final @SubReason int subReason)794     public void setSubReason(final @SubReason int subReason) {
795         mSubReason = subReason;
796     }
797 
798     /**
799      * @see #getConnectionGroup
800      *
801      * @hide
802      */
setConnectionGroup(final int connectionGroup)803     public void setConnectionGroup(final int connectionGroup) {
804         mConnectionGroup = connectionGroup;
805     }
806 
807     /**
808      * @see #getPackageName
809      *
810      * @hide
811      */
setPackageName(final String packageName)812     public void setPackageName(final String packageName) {
813         mPackageName = packageName;
814     }
815 
816     /**
817      * @see #getPackageList
818      *
819      * @hide
820      */
setPackageList(final String[] packageList)821     public void setPackageList(final String[] packageList) {
822         mPackageList = packageList;
823     }
824 
825     /**
826      * @see #getProcessStateSummary
827      *
828      * @hide
829      */
setProcessStateSummary(final byte[] state)830     public void setProcessStateSummary(final byte[] state) {
831         mState = state;
832     }
833 
834     /**
835      * @see #getTraceFile
836      *
837      * @hide
838      */
setTraceFile(final File traceFile)839     public void setTraceFile(final File traceFile) {
840         mTraceFile = traceFile;
841     }
842 
843     /**
844      * @see #mAppTraceRetriever
845      *
846      * @hide
847      */
setAppTraceRetriever(final IAppTraceRetriever retriever)848     public void setAppTraceRetriever(final IAppTraceRetriever retriever) {
849         mAppTraceRetriever = retriever;
850     }
851 
852     @Override
describeContents()853     public int describeContents() {
854         return 0;
855     }
856 
857     @Override
writeToParcel(@onNull Parcel dest, int flags)858     public void writeToParcel(@NonNull Parcel dest, int flags) {
859         dest.writeInt(mPid);
860         dest.writeInt(mRealUid);
861         dest.writeInt(mPackageUid);
862         dest.writeInt(mDefiningUid);
863         dest.writeString(mProcessName);
864         dest.writeString(mPackageName);
865         dest.writeInt(mConnectionGroup);
866         dest.writeInt(mReason);
867         dest.writeInt(mSubReason);
868         dest.writeInt(mStatus);
869         dest.writeInt(mImportance);
870         dest.writeLong(mPss);
871         dest.writeLong(mRss);
872         dest.writeLong(mTimestamp);
873         dest.writeString(mDescription);
874         dest.writeByteArray(mState);
875         if (mAppTraceRetriever != null) {
876             dest.writeInt(1);
877             dest.writeStrongBinder(mAppTraceRetriever.asBinder());
878         } else {
879             dest.writeInt(0);
880         }
881     }
882 
883     /** @hide */
ApplicationExitInfo()884     public ApplicationExitInfo() {
885     }
886 
887     /** @hide */
ApplicationExitInfo(ApplicationExitInfo other)888     public ApplicationExitInfo(ApplicationExitInfo other) {
889         mPid = other.mPid;
890         mRealUid = other.mRealUid;
891         mPackageUid = other.mPackageUid;
892         mDefiningUid = other.mDefiningUid;
893         mProcessName = other.mProcessName;
894         mPackageName = other.mPackageName;
895         mConnectionGroup = other.mConnectionGroup;
896         mReason = other.mReason;
897         mStatus = other.mStatus;
898         mSubReason = other.mSubReason;
899         mImportance = other.mImportance;
900         mPss = other.mPss;
901         mRss = other.mRss;
902         mTimestamp = other.mTimestamp;
903         mDescription = other.mDescription;
904         mPackageName = other.mPackageName;
905         mPackageList = other.mPackageList;
906         mState = other.mState;
907         mTraceFile = other.mTraceFile;
908         mAppTraceRetriever = other.mAppTraceRetriever;
909     }
910 
ApplicationExitInfo(@onNull Parcel in)911     private ApplicationExitInfo(@NonNull Parcel in) {
912         mPid = in.readInt();
913         mRealUid = in.readInt();
914         mPackageUid = in.readInt();
915         mDefiningUid = in.readInt();
916         mProcessName = in.readString();
917         mPackageName = in.readString();
918         mConnectionGroup = in.readInt();
919         mReason = in.readInt();
920         mSubReason = in.readInt();
921         mStatus = in.readInt();
922         mImportance = in.readInt();
923         mPss = in.readLong();
924         mRss = in.readLong();
925         mTimestamp = in.readLong();
926         mDescription = in.readString();
927         mState = in.createByteArray();
928         if (in.readInt() == 1) {
929             mAppTraceRetriever = IAppTraceRetriever.Stub.asInterface(in.readStrongBinder());
930         }
931     }
932 
933     public @NonNull static final Creator<ApplicationExitInfo> CREATOR =
934             new Creator<ApplicationExitInfo>() {
935         @Override
936         public ApplicationExitInfo createFromParcel(Parcel in) {
937             return new ApplicationExitInfo(in);
938         }
939 
940         @Override
941         public ApplicationExitInfo[] newArray(int size) {
942             return new ApplicationExitInfo[size];
943         }
944     };
945 
946     /** @hide */
dump(@onNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix, @NonNull SimpleDateFormat sdf)947     public void dump(@NonNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix,
948             @NonNull SimpleDateFormat sdf) {
949         pw.println(prefix + "ApplicationExitInfo " + seqSuffix + ":");
950         pw.println(prefix + "  timestamp=" + sdf.format(new Date(mTimestamp)));
951         pw.println(prefix + "  pid=" + mPid);
952         pw.println(prefix + "  realUid=" + mRealUid);
953         pw.println(prefix + "  packageUid=" + mPackageUid);
954         pw.println(prefix + "  definingUid=" + mDefiningUid);
955         pw.println(prefix + "  user=" + UserHandle.getUserId(mPackageUid));
956         pw.println(prefix + "  process=" + mProcessName);
957         pw.println(prefix + "  reason=" + mReason + " (" + reasonCodeToString(mReason) + ")");
958         pw.println(prefix + "  status=" + mStatus);
959         pw.println(prefix + "  importance=" + mImportance);
960         pw.print(prefix + "  pss="); DebugUtils.printSizeValue(pw, mPss << 10); pw.println();
961         pw.print(prefix + "  rss="); DebugUtils.printSizeValue(pw, mRss << 10); pw.println();
962         pw.println(prefix + "  description=" + mDescription);
963         pw.println(prefix + "  state=" + (ArrayUtils.isEmpty(mState)
964                 ? "empty" : Integer.toString(mState.length) + " bytes"));
965         pw.println(prefix + "  trace=" + mTraceFile);
966     }
967 
968     @Override
toString()969     public String toString() {
970         StringBuilder sb = new StringBuilder();
971         sb.append("ApplicationExitInfo(timestamp=");
972         sb.append(new SimpleDateFormat().format(new Date(mTimestamp)));
973         sb.append(" pid=").append(mPid);
974         sb.append(" realUid=").append(mRealUid);
975         sb.append(" packageUid=").append(mPackageUid);
976         sb.append(" definingUid=").append(mDefiningUid);
977         sb.append(" user=").append(UserHandle.getUserId(mPackageUid));
978         sb.append(" process=").append(mProcessName);
979         sb.append(" reason=").append(mReason).append(" (")
980                 .append(reasonCodeToString(mReason)).append(")");
981         sb.append(" status=").append(mStatus);
982         sb.append(" importance=").append(mImportance);
983         sb.append(" pss="); DebugUtils.sizeValueToString(mPss << 10, sb);
984         sb.append(" rss="); DebugUtils.sizeValueToString(mRss << 10, sb);
985         sb.append(" description=").append(mDescription);
986         sb.append(" state=").append(ArrayUtils.isEmpty(mState)
987                 ? "empty" : Integer.toString(mState.length) + " bytes");
988         sb.append(" trace=").append(mTraceFile);
989         return sb.toString();
990     }
991 
reasonCodeToString(@eason int reason)992     private static String reasonCodeToString(@Reason int reason) {
993         switch (reason) {
994             case REASON_EXIT_SELF:
995                 return "EXIT_SELF";
996             case REASON_SIGNALED:
997                 return "SIGNALED";
998             case REASON_LOW_MEMORY:
999                 return "LOW_MEMORY";
1000             case REASON_CRASH:
1001                 return "APP CRASH(EXCEPTION)";
1002             case REASON_CRASH_NATIVE:
1003                 return "APP CRASH(NATIVE)";
1004             case REASON_ANR:
1005                 return "ANR";
1006             case REASON_INITIALIZATION_FAILURE:
1007                 return "INITIALIZATION FAILURE";
1008             case REASON_PERMISSION_CHANGE:
1009                 return "PERMISSION CHANGE";
1010             case REASON_EXCESSIVE_RESOURCE_USAGE:
1011                 return "EXCESSIVE RESOURCE USAGE";
1012             case REASON_USER_REQUESTED:
1013                 return "USER REQUESTED";
1014             case REASON_USER_STOPPED:
1015                 return "USER STOPPED";
1016             case REASON_DEPENDENCY_DIED:
1017                 return "DEPENDENCY DIED";
1018             case REASON_OTHER:
1019                 return "OTHER KILLS BY SYSTEM";
1020             default:
1021                 return "UNKNOWN";
1022         }
1023     }
1024 
1025     /** @hide */
subreasonToString(@ubReason int subreason)1026     public static String subreasonToString(@SubReason int subreason) {
1027         switch (subreason) {
1028             case SUBREASON_WAIT_FOR_DEBUGGER:
1029                 return "WAIT FOR DEBUGGER";
1030             case SUBREASON_TOO_MANY_CACHED:
1031                 return "TOO MANY CACHED PROCS";
1032             case SUBREASON_TOO_MANY_EMPTY:
1033                 return "TOO MANY EMPTY PROCS";
1034             case SUBREASON_TRIM_EMPTY:
1035                 return "TRIM EMPTY";
1036             case SUBREASON_LARGE_CACHED:
1037                 return "LARGE CACHED";
1038             case SUBREASON_MEMORY_PRESSURE:
1039                 return "MEMORY PRESSURE";
1040             case SUBREASON_EXCESSIVE_CPU:
1041                 return "EXCESSIVE CPU USAGE";
1042             case SUBREASON_SYSTEM_UPDATE_DONE:
1043                 return "SYSTEM UPDATE_DONE";
1044             case SUBREASON_KILL_ALL_FG:
1045                 return "KILL ALL FG";
1046             case SUBREASON_KILL_ALL_BG_EXCEPT:
1047                 return "KILL ALL BG EXCEPT";
1048             case SUBREASON_KILL_UID:
1049                 return "KILL UID";
1050             case SUBREASON_KILL_PID:
1051                 return "KILL PID";
1052             case SUBREASON_INVALID_START:
1053                 return "INVALID START";
1054             case SUBREASON_INVALID_STATE:
1055                 return "INVALID STATE";
1056             case SUBREASON_IMPERCEPTIBLE:
1057                 return "IMPERCEPTIBLE";
1058             case SUBREASON_REMOVE_LRU:
1059                 return "REMOVE LRU";
1060             case SUBREASON_ISOLATED_NOT_NEEDED:
1061                 return "ISOLATED NOT NEEDED";
1062             default:
1063                 return "UNKNOWN";
1064         }
1065     }
1066 
1067     /**
1068      * Write to a protocol buffer output stream.
1069      * Protocol buffer message definition at {@link android.app.ApplicationExitInfoProto}
1070      *
1071      * @param proto    Stream to write the ApplicationExitInfo object to.
1072      * @param fieldId  Field Id of the ApplicationExitInfo as defined in the parent message
1073      * @hide
1074      */
writeToProto(ProtoOutputStream proto, long fieldId)1075     public void writeToProto(ProtoOutputStream proto, long fieldId) {
1076         final long token = proto.start(fieldId);
1077         proto.write(ApplicationExitInfoProto.PID, mPid);
1078         proto.write(ApplicationExitInfoProto.REAL_UID, mRealUid);
1079         proto.write(ApplicationExitInfoProto.PACKAGE_UID, mPackageUid);
1080         proto.write(ApplicationExitInfoProto.DEFINING_UID, mDefiningUid);
1081         proto.write(ApplicationExitInfoProto.PROCESS_NAME, mProcessName);
1082         proto.write(ApplicationExitInfoProto.CONNECTION_GROUP, mConnectionGroup);
1083         proto.write(ApplicationExitInfoProto.REASON, mReason);
1084         proto.write(ApplicationExitInfoProto.SUB_REASON, mSubReason);
1085         proto.write(ApplicationExitInfoProto.STATUS, mStatus);
1086         proto.write(ApplicationExitInfoProto.IMPORTANCE, mImportance);
1087         proto.write(ApplicationExitInfoProto.PSS, mPss);
1088         proto.write(ApplicationExitInfoProto.RSS, mRss);
1089         proto.write(ApplicationExitInfoProto.TIMESTAMP, mTimestamp);
1090         proto.write(ApplicationExitInfoProto.DESCRIPTION, mDescription);
1091         proto.write(ApplicationExitInfoProto.STATE, mState);
1092         proto.write(ApplicationExitInfoProto.TRACE_FILE,
1093                 mTraceFile == null ? null : mTraceFile.getAbsolutePath());
1094         proto.end(token);
1095     }
1096 
1097     /**
1098      * Read from a protocol buffer input stream.
1099      * Protocol buffer message definition at {@link android.app.ApplicationExitInfoProto}
1100      *
1101      * @param proto   Stream to read the ApplicationExitInfo object from.
1102      * @param fieldId Field Id of the ApplicationExitInfo as defined in the parent message
1103      * @hide
1104      */
readFromProto(ProtoInputStream proto, long fieldId)1105     public void readFromProto(ProtoInputStream proto, long fieldId)
1106             throws IOException, WireTypeMismatchException {
1107         final long token = proto.start(fieldId);
1108         while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
1109             switch (proto.getFieldNumber()) {
1110                 case (int) ApplicationExitInfoProto.PID:
1111                     mPid = proto.readInt(ApplicationExitInfoProto.PID);
1112                     break;
1113                 case (int) ApplicationExitInfoProto.REAL_UID:
1114                     mRealUid = proto.readInt(ApplicationExitInfoProto.REAL_UID);
1115                     break;
1116                 case (int) ApplicationExitInfoProto.PACKAGE_UID:
1117                     mPackageUid = proto.readInt(ApplicationExitInfoProto.PACKAGE_UID);
1118                     break;
1119                 case (int) ApplicationExitInfoProto.DEFINING_UID:
1120                     mDefiningUid = proto.readInt(ApplicationExitInfoProto.DEFINING_UID);
1121                     break;
1122                 case (int) ApplicationExitInfoProto.PROCESS_NAME:
1123                     mProcessName = proto.readString(ApplicationExitInfoProto.PROCESS_NAME);
1124                     break;
1125                 case (int) ApplicationExitInfoProto.CONNECTION_GROUP:
1126                     mConnectionGroup = proto.readInt(ApplicationExitInfoProto.CONNECTION_GROUP);
1127                     break;
1128                 case (int) ApplicationExitInfoProto.REASON:
1129                     mReason = proto.readInt(ApplicationExitInfoProto.REASON);
1130                     break;
1131                 case (int) ApplicationExitInfoProto.SUB_REASON:
1132                     mSubReason = proto.readInt(ApplicationExitInfoProto.SUB_REASON);
1133                     break;
1134                 case (int) ApplicationExitInfoProto.STATUS:
1135                     mStatus = proto.readInt(ApplicationExitInfoProto.STATUS);
1136                     break;
1137                 case (int) ApplicationExitInfoProto.IMPORTANCE:
1138                     mImportance = proto.readInt(ApplicationExitInfoProto.IMPORTANCE);
1139                     break;
1140                 case (int) ApplicationExitInfoProto.PSS:
1141                     mPss = proto.readLong(ApplicationExitInfoProto.PSS);
1142                     break;
1143                 case (int) ApplicationExitInfoProto.RSS:
1144                     mRss = proto.readLong(ApplicationExitInfoProto.RSS);
1145                     break;
1146                 case (int) ApplicationExitInfoProto.TIMESTAMP:
1147                     mTimestamp = proto.readLong(ApplicationExitInfoProto.TIMESTAMP);
1148                     break;
1149                 case (int) ApplicationExitInfoProto.DESCRIPTION:
1150                     mDescription = proto.readString(ApplicationExitInfoProto.DESCRIPTION);
1151                     break;
1152                 case (int) ApplicationExitInfoProto.STATE:
1153                     mState = proto.readBytes(ApplicationExitInfoProto.STATE);
1154                     break;
1155                 case (int) ApplicationExitInfoProto.TRACE_FILE:
1156                     final String path = proto.readString(ApplicationExitInfoProto.TRACE_FILE);
1157                     if (!TextUtils.isEmpty(path)) {
1158                         mTraceFile = new File(path);
1159                     }
1160                     break;
1161             }
1162         }
1163         proto.end(token);
1164     }
1165 
1166     @Override
equals(Object other)1167     public boolean equals(Object other) {
1168         if (other == null || !(other instanceof ApplicationExitInfo)) {
1169             return false;
1170         }
1171         ApplicationExitInfo o = (ApplicationExitInfo) other;
1172         return mPid == o.mPid && mRealUid == o.mRealUid && mPackageUid == o.mPackageUid
1173                 && mDefiningUid == o.mDefiningUid
1174                 && mConnectionGroup == o.mConnectionGroup && mReason == o.mReason
1175                 && mSubReason == o.mSubReason && mImportance == o.mImportance
1176                 && mStatus == o.mStatus && mTimestamp == o.mTimestamp
1177                 && mPss == o.mPss && mRss == o.mRss
1178                 && TextUtils.equals(mProcessName, o.mProcessName)
1179                 && TextUtils.equals(mDescription, o.mDescription);
1180     }
1181 
1182     @Override
hashCode()1183     public int hashCode() {
1184         int result = mPid;
1185         result = 31 * result + mRealUid;
1186         result = 31 * result + mPackageUid;
1187         result = 31 * result + mDefiningUid;
1188         result = 31 * result + mConnectionGroup;
1189         result = 31 * result + mReason;
1190         result = 31 * result + mSubReason;
1191         result = 31 * result + mImportance;
1192         result = 31 * result + mStatus;
1193         result = 31 * result + (int) mPss;
1194         result = 31 * result + (int) mRss;
1195         result = 31 * result + Long.hashCode(mTimestamp);
1196         result = 31 * result + Objects.hashCode(mProcessName);
1197         result = 31 * result + Objects.hashCode(mDescription);
1198         return result;
1199     }
1200 }
1201