-
Notifications
You must be signed in to change notification settings - Fork 610
/
XCrash.java
926 lines (842 loc) 路 33.7 KB
/
XCrash.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
// Copyright (c) 2019-present, iQIYI, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Created by caikelun on 2019-03-07.
package xcrash;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
/**
* xCrash is a crash reporting library for Android APP.
*/
@SuppressWarnings("unused")
public final class XCrash {
private static boolean initialized = false;
private static String appId = null;
private static String appVersion = null;
private static String logDir = null;
private static ILogger logger = new DefaultLogger();
public static String nativeLibDir = null;
private XCrash() {
}
/**
* Initialize xCrash with default parameters.
*
* <p>Note: This is a synchronous operation.
*
* @param ctx The context of the application object of the current process.
* @return Return zero if successful, non-zero otherwise. The error code is defined in: {@link xcrash.Errno}.
*/
@SuppressWarnings("unused")
public static int init(Context ctx) {
return init(ctx, null);
}
/**
* Initialize xCrash with custom parameters.
*
* <p>Note: This is a synchronous operation.
*
* @param ctx The context of the application object of the current process.
* @param params An initialization parameter set.
* @return Return zero if successful, non-zero otherwise. The error code is defined in: {@link xcrash.Errno}.
*/
@SuppressWarnings("unused")
public static synchronized int init(Context ctx, InitParameters params) {
if (XCrash.initialized) {
return Errno.OK;
}
XCrash.initialized = true;
if (ctx == null) {
return Errno.CONTEXT_IS_NULL;
}
//make sure to get the instance of android.app.Application
Context appContext = ctx.getApplicationContext();
if (appContext != null) {
ctx = appContext;
}
//use default parameters
if (params == null) {
params = new InitParameters();
}
//set logger
if (params.logger != null) {
XCrash.logger = params.logger;
}
//save app id
String packageName = ctx.getPackageName();
XCrash.appId = packageName;
if (TextUtils.isEmpty(XCrash.appId)) {
XCrash.appId = "unknown";
}
//save app version
if (TextUtils.isEmpty(params.appVersion)) {
params.appVersion = Util.getAppVersion(ctx);
}
XCrash.appVersion = params.appVersion;
XCrash.nativeLibDir = ctx.getApplicationInfo().nativeLibraryDir;
//save log dir
if (TextUtils.isEmpty(params.logDir)) {
params.logDir = ctx.getFilesDir() + "/tombstones";
}
XCrash.logDir = params.logDir;
//get PID and process name
int pid = android.os.Process.myPid();
String processName = null;
if (params.enableJavaCrashHandler || params.enableAnrHandler) {
processName = Util.getProcessName(ctx, pid);
//capture only the ANR of the main process
if (params.enableAnrHandler) {
if (TextUtils.isEmpty(processName) || !processName.equals(packageName)) {
params.enableAnrHandler = false;
}
}
}
//init file manager
FileManager.getInstance().initialize(
params.logDir,
params.javaLogCountMax,
params.nativeLogCountMax,
params.anrLogCountMax,
params.placeholderCountMax,
params.placeholderSizeKb,
params.logFileMaintainDelayMs);
if (params.enableJavaCrashHandler || params.enableNativeCrashHandler || params.enableAnrHandler) {
if (ctx instanceof Application) {
ActivityMonitor.getInstance().initialize((Application) ctx);
}
}
//init java crash handler
if (params.enableJavaCrashHandler) {
JavaCrashHandler.getInstance().initialize(
pid,
processName,
appId,
params.appVersion,
params.logDir,
params.javaRethrow,
params.javaLogcatSystemLines,
params.javaLogcatEventsLines,
params.javaLogcatMainLines,
params.javaDumpFds,
params.javaDumpNetworkInfo,
params.javaDumpAllThreads,
params.javaDumpAllThreadsCountMax,
params.javaDumpAllThreadsWhiteList,
params.javaCallback);
}
//init ANR handler (API level < 21)
if (params.enableAnrHandler && Build.VERSION.SDK_INT < 21) {
AnrHandler.getInstance().initialize(
ctx,
pid,
processName,
appId,
params.appVersion,
params.logDir,
params.anrCheckProcessState,
params.anrLogcatSystemLines,
params.anrLogcatEventsLines,
params.anrLogcatMainLines,
params.anrDumpFds,
params.anrDumpNetworkInfo,
params.anrCallback,
params.anrFastCallback);
}
//init native crash handler / ANR handler (API level >= 21)
int r = Errno.OK;
if (params.enableNativeCrashHandler || (params.enableAnrHandler && Build.VERSION.SDK_INT >= 21)) {
r = NativeHandler.getInstance().initialize(
ctx,
params.libLoader,
appId,
params.appVersion,
params.logDir,
params.enableNativeCrashHandler,
params.nativeRethrow,
params.nativeLogcatSystemLines,
params.nativeLogcatEventsLines,
params.nativeLogcatMainLines,
params.nativeDumpElfHash,
params.nativeDumpMap,
params.nativeDumpFds,
params.nativeDumpNetworkInfo,
params.nativeDumpAllThreads,
params.nativeDumpAllThreadsCountMax,
params.nativeDumpAllThreadsWhiteList,
params.nativeCallback,
params.enableAnrHandler && Build.VERSION.SDK_INT >= 21,
params.anrRethrow,
params.anrCheckProcessState,
params.anrLogcatSystemLines,
params.anrLogcatEventsLines,
params.anrLogcatMainLines,
params.anrDumpFds,
params.anrDumpNetworkInfo,
params.anrCallback,
params.anrFastCallback);
}
//maintain tombstone and placeholder files in a background thread with some delay
FileManager.getInstance().maintain();
return r;
}
/**
* An initialization parameter set.
*/
public static class InitParameters {
//common
String appVersion = null;
String logDir = null;
int logFileMaintainDelayMs = 5000;
ILogger logger = null;
ILibLoader libLoader = null;
/**
* Set App version. You can use this method to set an internal test/gray version number.
* (Default: {@link android.content.pm.PackageInfo#versionName})
*
* @param appVersion App version string.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAppVersion(String appVersion) {
this.appVersion = appVersion;
return this;
}
/**
* Set the directory to save crash log files.
* (Default: {@link android.content.Context#getFilesDir()} + "/tombstones")
*
* @param dir Absolute path to the directory.
* @return The InitParameters object.
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public InitParameters setLogDir(String dir) {
this.logDir = dir;
return this;
}
/**
* Set delay in milliseconds before the log file maintain task is to be executed. (Default: 5000)
*
* @param logFileMaintainDelayMs Delay in milliseconds before the log file maintain task is to be executed.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setLogFileMaintainDelayMs(int logFileMaintainDelayMs) {
this.logFileMaintainDelayMs = (logFileMaintainDelayMs < 0 ? 0 : logFileMaintainDelayMs);
return this;
}
/**
* Set a logger implementation for xCrash to log message and exception.
*
* @param logger An instance of {@link xcrash.ILogger}.
* @return The InitParameters object.
*/
public InitParameters setLogger(ILogger logger) {
this.logger = logger;
return this;
}
/**
* Set a libLoader implementation for xCrash to load native library.
*
* @param libLoader An instance of {@link xcrash.ILibLoader}.
* @return The InitParameters object.
*/
public InitParameters setLibLoader(ILibLoader libLoader) {
this.libLoader = libLoader;
return this;
}
//placeholder
int placeholderCountMax = 0;
int placeholderSizeKb = 128;
/**
* Set the maximum number of placeholder files in the log directory. (Default: 0)
*
* <p>Note: Set this value to 0 means disable the placeholder feature.
*
* @param countMax The maximum number of placeholder files.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setPlaceholderCountMax(int countMax) {
this.placeholderCountMax = (countMax < 0 ? 0 : countMax);
return this;
}
/**
* Set the KB of each placeholder files in the log directory. (Default: 128)
*
* @param sizeKb The KB of each placeholder files.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setPlaceholderSizeKb(int sizeKb) {
this.placeholderSizeKb = (sizeKb < 0 ? 0 : sizeKb);
return this;
}
//java crash
boolean enableJavaCrashHandler = true;
boolean javaRethrow = true;
int javaLogCountMax = 10;
int javaLogcatSystemLines = 50;
int javaLogcatEventsLines = 50;
int javaLogcatMainLines = 200;
boolean javaDumpFds = true;
boolean javaDumpNetworkInfo = true;
boolean javaDumpAllThreads = true;
int javaDumpAllThreadsCountMax = 0;
String[] javaDumpAllThreadsWhiteList = null;
ICrashCallback javaCallback = null;
/**
* Enable the Java exception capture feature. (Default: enable)
*
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters enableJavaCrashHandler() {
this.enableJavaCrashHandler = true;
return this;
}
/**
* Disable the Java exception capture feature. (Default: enable)
*
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters disableJavaCrashHandler() {
this.enableJavaCrashHandler = false;
return this;
}
/**
* Set whether xCrash should rethrow the Java exception to system
* after it has been handled. (Default: true)
*
* @param rethrow If <code>true</code>, the Java exception will be rethrown to Android System.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaRethrow(boolean rethrow) {
this.javaRethrow = rethrow;
return this;
}
/**
* Set the maximum number of Java crash log files to save in the log directory. (Default: 10)
*
* @param countMax The maximum number of Java crash log files.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaLogCountMax(int countMax) {
this.javaLogCountMax = (countMax < 1 ? 1 : countMax);
return this;
}
/**
* Set the maximum number of rows to get from "logcat -b system" when a Java exception occurred. (Default: 50)
*
* @param logcatSystemLines The maximum number of rows.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaLogcatSystemLines(int logcatSystemLines) {
this.javaLogcatSystemLines = logcatSystemLines;
return this;
}
/**
* Set the maximum number of rows to get from "logcat -b events" when a Java exception occurred. (Default: 50)
*
* @param logcatEventsLines The maximum number of rows.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaLogcatEventsLines(int logcatEventsLines) {
this.javaLogcatEventsLines = logcatEventsLines;
return this;
}
/**
* Set the maximum number of rows to get from "logcat -b main" when a Java exception occurred. (Default: 200)
*
* @param logcatMainLines The maximum number of rows.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaLogcatMainLines(int logcatMainLines) {
this.javaLogcatMainLines = logcatMainLines;
return this;
}
/**
* Set if dumping FD list when a java crash occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaDumpFds(boolean flag) {
this.javaDumpFds = flag;
return this;
}
/**
* Set if dumping network info when a java crash occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaDumpNetworkInfo(boolean flag) {
this.javaDumpNetworkInfo = flag;
return this;
}
/**
* Set if dumping threads info (stacktrace) for all threads (not just the thread that has crashed)
* when a Java exception occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public InitParameters setJavaDumpAllThreads(boolean flag) {
this.javaDumpAllThreads = flag;
return this;
}
/**
* Set the maximum number of other threads to dump when a Java exception occurred.
* "0" means no limit. (Default: 0)
*
* <p>Note: This option is only useful when "JavaDumpAllThreads" is enabled by calling {@link InitParameters#setJavaDumpAllThreads(boolean)}.
*
* @param countMax The maximum number of other threads to dump.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaDumpAllThreadsCountMax(int countMax) {
this.javaDumpAllThreadsCountMax = (countMax < 0 ? 0 : countMax);
return this;
}
/**
* Set a thread name (regular expression) whitelist to filter which threads need to be dumped when a Java exception occurred.
* "null" means no filtering. (Default: null)
*
* <p>Note: This option is only useful when "JavaDumpAllThreads" is enabled by calling {@link InitParameters#setJavaDumpAllThreads(boolean)}.
*
* @param whiteList A thread name (regular expression) whitelist.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaDumpAllThreadsWhiteList(String[] whiteList) {
this.javaDumpAllThreadsWhiteList = whiteList;
return this;
}
/**
* Set a callback to be executed when a Java exception occurred. (If not set, nothing will be happened.)
*
* @param callback An instance of {@link xcrash.ICrashCallback}.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaCallback(ICrashCallback callback) {
this.javaCallback = callback;
return this;
}
//native crash
boolean enableNativeCrashHandler = true;
boolean nativeRethrow = true;
int nativeLogCountMax = 10;
int nativeLogcatSystemLines = 50;
int nativeLogcatEventsLines = 50;
int nativeLogcatMainLines = 200;
boolean nativeDumpElfHash = true;
boolean nativeDumpMap = true;
boolean nativeDumpFds = true;
boolean nativeDumpNetworkInfo = true;
boolean nativeDumpAllThreads = true;
int nativeDumpAllThreadsCountMax = 0;
String[] nativeDumpAllThreadsWhiteList = null;
ICrashCallback nativeCallback = null;
/**
* Enable the native crash capture feature. (Default: enable)
*
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters enableNativeCrashHandler() {
this.enableNativeCrashHandler = true;
return this;
}
/**
* Disable the native crash capture feature. (Default: enable)
*
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters disableNativeCrashHandler() {
this.enableNativeCrashHandler = false;
return this;
}
/**
* Set whether xCrash should rethrow the crash native signal to system
* after it has been handled. (Default: true)
*
* @param rethrow If <code>true</code>, the native signal will be rethrown to Android System.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeRethrow(boolean rethrow) {
this.nativeRethrow = rethrow;
return this;
}
/**
* Set the maximum number of native crash log files to save in the log directory. (Default: 10)
*
* @param countMax The maximum number of native crash log files.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeLogCountMax(int countMax) {
this.nativeLogCountMax = (countMax < 1 ? 1 : countMax);
return this;
}
/**
* Set the maximum number of rows to get from "logcat -b system" when a native crash occurred. (Default: 50)
*
* @param logcatSystemLines The maximum number of rows.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeLogcatSystemLines(int logcatSystemLines) {
this.nativeLogcatSystemLines = logcatSystemLines;
return this;
}
/**
* Set the maximum number of rows to get from "logcat -b events" when a native crash occurred. (Default: 50)
*
* @param logcatEventsLines The maximum number of rows.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeLogcatEventsLines(int logcatEventsLines) {
this.nativeLogcatEventsLines = logcatEventsLines;
return this;
}
/**
* Set the maximum number of rows to get from "logcat -b main" when a native crash occurred. (Default: 200)
*
* @param logcatMainLines The maximum number of rows.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeLogcatMainLines(int logcatMainLines) {
this.nativeLogcatMainLines = logcatMainLines;
return this;
}
/**
* Set if dumping ELF file's MD5 hash in Build-Id section when a native crash occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeDumpElfHash(boolean flag) {
this.nativeDumpElfHash = flag;
return this;
}
/**
* Set if dumping memory map when a native crash occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeDumpMap(boolean flag) {
this.nativeDumpMap = flag;
return this;
}
/**
* Set if dumping FD list when a native crash occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeDumpFds(boolean flag) {
this.nativeDumpFds = flag;
return this;
}
/**
* Set if dumping network info when a native crash occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeDumpNetwork(boolean flag) {
this.nativeDumpNetworkInfo = flag;
return this;
}
/**
* Set if dumping threads info (registers, backtrace and stack) for all threads (not just the thread that has crashed)
* when a native crash occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public InitParameters setNativeDumpAllThreads(boolean flag) {
this.nativeDumpAllThreads = flag;
return this;
}
/**
* Set the maximum number of other threads to dump when a native crash occurred.
* "0" means no limit. (Default: 0)
*
* <p>Note: This option is only useful when "NativeDumpAllThreads" is enabled by calling {@link InitParameters#setNativeDumpAllThreads(boolean)}.
*
* @param countMax The maximum number of other threads to dump.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeDumpAllThreadsCountMax(int countMax) {
this.nativeDumpAllThreadsCountMax = (countMax < 0 ? 0 : countMax);
return this;
}
/**
* Set a thread name (regular expression) whitelist to filter which threads need to be dumped when a native crash occurred.
* "null" means no filtering. (Default: null)
*
* <p>Note: This option is only useful when "NativeDumpAllThreads" is enabled by calling {@link InitParameters#setNativeDumpAllThreads(boolean)}.
*
* <p>Warning: The regular expression used here only supports POSIX ERE (Extended Regular Expression).
* Android bionic's regular expression is different from Linux libc's regular expression.
* See: https://android.googlesource.com/platform/bionic/+/refs/heads/master/libc/include/regex.h .
*
* @param whiteList A thread name (regular expression) whitelist.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeDumpAllThreadsWhiteList(String[] whiteList) {
this.nativeDumpAllThreadsWhiteList = whiteList;
return this;
}
/**
* Set a callback to be executed when a native crash occurred. (If not set, nothing will be happened.)
*
* @param callback An instance of {@link xcrash.ICrashCallback}.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeCallback(ICrashCallback callback) {
this.nativeCallback = callback;
return this;
}
//anr
boolean enableAnrHandler = true;
boolean anrRethrow = true;
boolean anrCheckProcessState = true;
int anrLogCountMax = 10;
int anrLogcatSystemLines = 50;
int anrLogcatEventsLines = 50;
int anrLogcatMainLines = 200;
boolean anrDumpFds = true;
boolean anrDumpNetworkInfo = true;
ICrashCallback anrCallback = null;
ICrashCallback anrFastCallback = null;
/**
* Enable the ANR capture feature. (Default: enable)
*
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters enableAnrCrashHandler() {
this.enableAnrHandler = true;
return this;
}
/**
* Disable the ANR capture feature. (Default: enable)
*
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters disableAnrCrashHandler() {
this.enableAnrHandler = false;
return this;
}
/**
* Set whether xCrash should rethrow the ANR native signal to system
* after it has been handled. (Default: true)
*
* <p>Note: This option is only valid if Android API level greater than or equal to 21.
*
* <p>Warning: It is highly recommended NOT to modify the default value (true) in most cases unless you know that you are doing.
*
* @param rethrow If <code>true</code>, the native signal will be rethrown to Android System.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrRethrow(boolean rethrow) {
this.anrRethrow = rethrow;
return this;
}
/**
* Set whether the process error state (from "ActivityManager#getProcessesInErrorState()") is a necessary condition for ANR. (Default: true)
*
* <p>Note: On some Android TV box devices and on most Oppo phones, the ANR is not reflected by process error state. In this case, set this option to false.
*
* @param checkProcessState If <code>true</code>, process state error will be a necessary condition for ANR.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrCheckProcessState(boolean checkProcessState) {
this.anrCheckProcessState = checkProcessState;
return this;
}
/**
* Set the maximum number of ANR log files to save in the log directory. (Default: 10)
*
* @param countMax The maximum number of ANR log files.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrLogCountMax(int countMax) {
this.anrLogCountMax = (countMax < 1 ? 1 : countMax);
return this;
}
/**
* Set the maximum number of rows to get from "logcat -b system" when an ANR occurred. (Default: 50)
*
* @param logcatSystemLines The maximum number of rows.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrLogcatSystemLines(int logcatSystemLines) {
this.anrLogcatSystemLines = logcatSystemLines;
return this;
}
/**
* Set the maximum number of rows to get from "logcat -b events" when an ANR occurred. (Default: 50)
*
* @param logcatEventsLines The maximum number of rows.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrLogcatEventsLines(int logcatEventsLines) {
this.anrLogcatEventsLines = logcatEventsLines;
return this;
}
/**
* Set the maximum number of rows to get from "logcat -b main" when an ANR occurred. (Default: 200)
*
* @param logcatMainLines The maximum number of rows.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrLogcatMainLines(int logcatMainLines) {
this.anrLogcatMainLines = logcatMainLines;
return this;
}
/**
* Set if dumping FD list when an ANR occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrDumpFds(boolean flag) {
this.anrDumpFds = flag;
return this;
}
/**
* Set if dumping network info when an ANR occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrDumpNetwork(boolean flag) {
this.anrDumpNetworkInfo = flag;
return this;
}
/**
* Set a callback to be executed when an ANR occurred. (If not set, nothing will be happened.)
*
* @param callback An instance of {@link xcrash.ICrashCallback}.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrCallback(ICrashCallback callback) {
this.anrCallback = callback;
return this;
}
/**
* Set a fast callback to be executed when an ANR occurred.
* This callback is called before ANR trace dump
* (If not set, nothing will be happened.)
*
* @param fastCallback An instance of {@link xcrash.ICrashCallback}.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrFastCallback(ICrashCallback fastCallback) {
this.anrFastCallback = fastCallback;
return this;
}
}
static String getAppId() {
return appId;
}
static String getAppVersion() {
return appVersion;
}
public static String getLogDir() {
return logDir;
}
static ILogger getLogger() {
return logger;
}
/**
* Force a java exception.
*
* <p>Warning: This method is for testing purposes only. Don't call it in a release version of your APP.
*
* @param runInNewThread Whether it is triggered in the current thread.
* @throws RuntimeException This exception will terminate current process.
*/
@SuppressWarnings("unused")
public static void testJavaCrash(boolean runInNewThread) throws RuntimeException {
if (runInNewThread) {
Thread thread = new Thread() {
@Override
public void run() {
throw new RuntimeException("test java exception");
}
};
thread.setName("xcrash_test_java_thread");
thread.start();
} else {
throw new RuntimeException("test java exception");
}
}
/**
* Force a native crash.
*
* <p>Warning: This method is for testing purposes only. Don't call it in a release version of your APP.
*
* @param runInNewThread Whether it is triggered in the current thread.
*/
@SuppressWarnings("unused")
public static void testNativeCrash(boolean runInNewThread) {
NativeHandler.getInstance().testNativeCrash(runInNewThread);
}
}