Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
2107 lines (1909 loc) · 112 KB
/
Copy pathindex.html
File metadata and controls
2107 lines (1909 loc) · 112 KB
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
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="zh-CN">
<!-- title -->
<!-- keywords -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="author" content="Gracker">
<meta name="renderer" content="webkit">
<meta name="copyright" content="Gracker">
<meta name="keywords" content="Android,Performance,AndroidPerformance,性能,优化,性能优化,Perf,Flutter,Linux,LinuxPerformance,AndroidFramework,Framework,Android Performance,Flutter,Kotlin,Memory,内存,流畅性,卡顿,响应速度,Jank,Smooth,Android Framework,ANR,Crash,Dalvik,ART,Jetpack,Compose,启动优化,Startup,Perfetto,Systrace,RenderThread,Java">
<meta name="description" content="Focus On Android Performance">
<meta name="description" content="Focus On Android Performance">
<meta property="og:type" content="website">
<meta property="og:title" content="Android Performance">
<meta property="og:url" content="https://androidperformance.com/index.html">
<meta property="og:site_name" content="Android Performance">
<meta property="og:description" content="Focus On Android Performance">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="Gracker">
<meta name="twitter:card" content="summary">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="icon" href="/assets/favicon.ico">
<title>
Android Performance
</title>
<link rel="canonical" href="https://androidperformance.com/">
<style type="text/css">
@font-face {
font-family: 'Oswald-Regular';
src: url("/font/Oswald-Regular.woff2") format('woff2'),
url("/font/Oswald-Regular.ttf") format('truetype');
font-display: swap;
}
body {
margin: 0;
}
/* Removed initial hide to show content immediately */
.site-intro {
position: relative;
z-index: 3;
width: 100%;
/* height: 50vh; */
overflow: hidden;
}
.site-intro-placeholder {
position: absolute;
z-index: -2;
top: 0;
left: 0;
width: calc(100% + 300px);
height: 100%;
background: repeating-linear-gradient(
-45deg,
#444 0,
#444 80px,
#333 80px,
#333 160px
);
background-position: center center;
transform: translate3d(-226px, 0, 0);
animation: gradient-move 2.5s ease-out 0s infinite;
}
@keyframes gradient-move {
0% {
transform: translate3d(-226px, 0, 0);
}
100% {
transform: translate3d(0, 0, 0);
}
}
</style>
<link id="stylesheet-base" rel="stylesheet" href="/css/style.css">
<link id="stylesheet-mobile" rel="stylesheet" href="/css/mobile.css" media="screen and (max-width: 960px)">
<link id="stylesheet-theme-dark" rel="stylesheet" href="/css/dark.css">
<link id="stylesheet-custom" rel="stylesheet" href="/css/custom.css">
<link rel="preload" href="/lib/jquery.min.js" as="script">
<link rel="preload" href="/scripts/main.js" as="script">
<!-- algolia -->
<!-- Language alternatives share the same route contract as the header. -->
<link rel="alternate" hreflang="zh-CN" href="https://androidperformance.com/" />
<link rel="alternate" hreflang="en" href="https://androidperformance.com/en/" />
<link rel="alternate" hreflang="x-default" href="https://androidperformance.com/en/" />
<meta name="generator" content="Hexo 6.3.0"><link rel="alternate" href="/atom.xml" title="Android Performance" type="application/atom+xml">
</head>
<body class="home-body">
<!-- header -->
<header class="header header-mobile index-header">
<!-- top read progress line -->
<div class="header-element">
<div class="read-progress"></div>
</div>
<!-- sidebar menu button -->
<div class="header-element">
<div
class="header-sidebar-menu">
<div style="padding-left: 1px;"></div>
</div>
</div>
<!-- header actions -->
<div class="header-actions">
<!-- search button -->
<span class="header-search-btn header-element popup-trigger" role="button" aria-label="Search" data-tooltip="Search">
<span class="iconfont-archer search-icon" aria-hidden="true"></span>
</span>
<!-- theme mode switch button -->
<span class="header-theme-btn header-element" role="button" aria-label="Theme" data-tooltip="Theme">
<span aria-hidden="true">◐</span>
</span>
<!-- A real link works without JavaScript and supports opening a new tab. -->
<span class="header-lang-btn header-element" data-tooltip="Read in English">
<a href="/en/" class="lang-text" aria-label="Read in English">EN</a>
</span>
<!-- home button -->
<span class="home-link header-element">
<a href="/" aria-label="Home" data-tooltip="Home">
<svg class="home-icon" aria-hidden="true" viewBox="0 0 24 24">
<path d="m3 10.5 9-7 9 7"></path>
<path d="M5 9.5V21h14V9.5"></path>
<path d="M10 21v-6h4v6"></path>
</svg>
</a>
</span>
</div>
<!-- toggle banner -->
<div class="banner">
<div class="blog-title header-element">
<a href="/">
Android Performance
</a>
</div>
<div class="post-title header-element">
<a href="#" class="post-name"></a>
</div>
</div>
</header>
<!-- fixed footer -->
<footer class="footer-fixed index-footer-fixed">
<!-- donate button -->
<!-- back to top button -->
<div class="footer-fixed-btn footer-fixed-btn--hidden back-top">
<div></div>
</div>
</footer>
<!-- wrapper -->
<div class="wrapper">
<div class="site-intro" style=" height:50vh;
">
<!-- 主页 -->
<!-- 文章页 -->
<div class="site-intro-placeholder"></div>
<picture>
<img class="site-intro-img"
src="/intro/index-bg.webp"
alt=""
decoding="async"
fetchpriority="high"
sizes="100vw">
</picture>
<div class="site-intro-meta">
<!-- 标题 -->
<h1 class="intro-title">
<!-- 主页 -->
Android Performance
<!-- 文章页 -->
</h1>
<!-- 副标题 -->
<p class="intro-subtitle">
<!-- 主页副标题 -->
闻道有先后,术业有专攻,如是而已
<!-- 文章页 -->
</p>
<!-- 文章页 meta -->
</div>
</div>
<script>
(function () {
var done = false
function fontLoaded() {
if (done) return
done = true
var introTitle = document.getElementsByClassName('intro-title')[0]
var introSubtitle = document.getElementsByClassName('intro-subtitle')[0]
var postIntros = document.getElementsByClassName('post-intros')[0]
if (introTitle) introTitle.classList.add('intro-fade-in')
if (introSubtitle) introSubtitle.classList.add('intro-fade-in')
if (postIntros) postIntros.classList.add('post-fade-in')
}
function waitForLocalFont() {
if (document.fonts && document.fonts.load) {
Promise.race([
document.fonts.load('1em Oswald-Regular'),
new Promise(function (resolve) { setTimeout(resolve, 1000) })
]).then(fontLoaded, fontLoaded)
} else {
fontLoaded()
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', waitForLocalFont, false)
} else {
waitForLocalFont()
}
})()
</script>
<img class="loading" src="/assets/loading.svg" style="display: block; margin: 6rem auto 0 auto; width: 6rem; height: 6rem;" alt="loading">
<div class="container container-unloaded">
<main class="main index-page">
<article class="index-post">
<a class="abstract-title" href="/2026/09/19/AIW-Open-Source-Android-Internals-Wiki/">
<span class="iconfont-archer stick-top"></span>
<span class="abstract-title-text">耗时大半年,开源一本 Android 电子书《Android 技术内幕:系统机制、性能优化与工具实战》</span>
</a>
<div class="abstract-content">
<p>Android 内部机制的资料,网上不缺。AOSP、官方文档、博客、论文、trace 讨论,想找都找得到。麻烦的是各说各的版本:这篇是 Android 12 的结论,那篇没写版本,再一篇是某台机器上的现象。</p>
<p>AIW 想补的就是这个缺口。全称 Android Internal Wiki,中文书名是《Android 技术内幕:系统机制、性能优化与工具实战》,五部分二十六章,正文钉在 Android 17。仓库现已公开:</p>
<p><a target="_blank" rel="noopener" href="https://github.com/Gracker/android-internals-wiki">https://github.com/Gracker/android-internals-wiki</a></p>
<p>打开仓库能拿到的是二十六章正文、一份完整目录,和每周编一次的 EPUB。</p>
<p>这二十六章现在到了可以拿出来给人读的程度。读到哪一段和源码对不上,欢迎提 issue 或者 PR。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/11/03">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/09/19</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="AOSP">AOSP</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Framework">Framework</a>
<a class="post-tag" href="javascript:void(0);" data-tags="AIW">AIW</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Open Source">Open Source</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2019/12/01/BlogMap/">
<span class="iconfont-archer stick-top"></span>
<span class="abstract-title-text">「置顶」博客文章目录 + 个人项目</span>
</a>
<div class="abstract-content">
<p>本博客内容主要集中在 Android 开发和优化相关的话题,包括一些性能工具的使用、Android App 优化知识、Android Framework 知识讲解,性能理论知识讲解等,这里整理了一份目录供大家参考,大家可以挑感兴趣的部分来看。这里不仅仅包含博客中的内容,一些我在 <a target="_blank" rel="noopener" href="https://www.zhihu.com/people/gracker">知乎</a> 或者已停止运营的 The Performance 社群中的历史回答也会放到这里,不过这个目录里面放的都是我原创的博客,另外还收集了一些优秀文章,我也会不定期更新 <a href="https://androidperformance.com/2018/05/07/Android-performance-optimization-skills-and-tools/">Android 性能优化必知必会</a>。</p>
<p>文章索引在前,工具、App 和内容项目集中在后面的<a href="/2019/12/01/BlogMap/#%E4%B8%AA%E4%BA%BA%E9%A1%B9%E7%9B%AE">个人项目</a>。新增:<a target="_blank" rel="noopener" href="https://www.androidperformance.com/2026/09/19/AIW-Open-Source-Android-Internals-Wiki/">AIW 开源介绍</a> · <a target="_blank" rel="noopener" href="https://github.com/Gracker/android-internals-wiki">AIW GitHub 仓库</a>。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/11/05">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2019/12/01</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="读书笔记">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
读书笔记
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Systrace">Systrace</a>
<a class="post-tag" href="javascript:void(0);" data-tags="RenderThread">RenderThread</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2018/05/07/Android-performance-optimization-skills-and-tools/">
<span class="iconfont-archer stick-top"></span>
<span class="abstract-title-text">「置顶」Android 性能优化必知必会</span>
</a>
<div class="abstract-content">
<p>这篇文章记录了 Android 性能优化所必须掌握的知识(主要是对应的优秀文章、公众号、博客、技术团队等),涵盖性能优化相关的方方面面。本文会持续更新,欢迎各位自荐或者推荐。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/10/13">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2018/05/07</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Startup">Startup</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Memory">Memory</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Jank">Jank</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/10/06/SmartPerfetto-v1.15.1-Release-Notes/">
<span class="abstract-title-text">SmartPerfetto 更新记录</span>
</a>
<div class="abstract-content">
<p>SmartPerfetto 的版本更新以后集中写在这一篇,新的记录放在最前面。这里合并了此前几篇更新文章,主要保留版本范围、时间和重要变化。</p>
<p>目前整理到 <strong>v1.15.1(2026-10-06)</strong>。这是本文覆盖的版本,不代表项目的最新发行版;下载请看 <a target="_blank" rel="noopener" href="https://github.com/Gracker/SmartPerfetto/releases">GitHub Releases</a>。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/11/05">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/10/06</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Open Source">Open Source</a>
<a class="post-tag" href="javascript:void(0);" data-tags="AI Agent">AI Agent</a>
<a class="post-tag" href="javascript:void(0);" data-tags="SmartPerfetto">SmartPerfetto</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/05/05/What-I-Am-Building/">
<span class="abstract-title-text">我做了什么</span>
</a>
<div class="abstract-content">
<p>这篇文章只做一件事:把我长期维护、正在推进、已经公开和暂未公开的项目集中到一个地方。范围包括 Android 性能分析、Perfetto 工具、AI 自动化、iOS App、Android Demo、测试套件、博客系列、社群和各个平台账号。</p>
<p>第一次来到这个博客,可以按需求直接跳转:学 Android 性能分析,看 Perfetto / Systrace 系列;找工具项目,看 SmartPerfetto、TraceFix、Android App Memory Analysis;了解 AI 如何参与知识管理和日常工作,看 OpenClaw 与 AI Field Notes;联系我或查看其它平台账号,看文末。</p>
<p>项目按四条线划:性能分析方向有 SmartPerfetto、Android App Memory Analysis、TraceFix、Perfetto Auto-Pin 这类工具,以及 High Performance Friends Circle 测试平台;AI 与自动化方向有 OpenClaw、AI Field Notes、Gracker Skills、Open Design;个人 App 包括 100Years、iBattery 两个 iOS 项目和 Android 项目 Juju;内容项目则是博客和 Android Weekly 两处主阵地。下面每个项目都会注明状态:日常维护、近期重点、还是已经暂停。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/10/15">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/05/05</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="个人页">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
个人页
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Open Source">Open Source</a>
<a class="post-tag" href="javascript:void(0);" data-tags="AI Agent">AI Agent</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Gracker">Gracker</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/05/04/Android-Perfetto-18-Input-Response-Latency/">
<span class="abstract-title-text">Android Perfetto 系列 18:响应速度实战,从输入事件到首帧反馈</span>
</a>
<div class="abstract-content">
<p>按钮按下后,按压态何时出现?滑动列表时,内容何时第一次跟着手指移动?这两个问题都要找到输入事件和对应的第一帧反馈;启动总耗时与后续动画帧率回答的是别的问题。</p>
<p>本文用 Perfetto 把 InputReader 读到事件、InputDispatcher 派发、App 处理、帧提交和 SurfaceFlinger 呈现分开计时。每一步的起止点要能回到 Trace 核对。</p>
<p>从 InputReader 的 <code>read_time</code> 到关联帧 present,可以得到系统内部延迟的候选值 <code>estimated_input_to_present_ms</code>。只有确认目标 layer、业务状态确实在那一帧发生视觉变化,才把它写成 <code>input_to_present_ms</code>。这段时间不包含触控 IC、驱动上报前延迟、显示扫描和面板响应。</p>
<p>点击和滑动还需要不同的终点定义:按压态、转场首帧和内容第一次位移不能混成一个数。App marker 能说明业务动作,高速相机可补外部可见时点。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/11/03">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/05/04</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Input">Input</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Latency">Latency</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/05/04/Android-Perfetto-17-Engineering-Domain-And-Platform-Tracing/">
<span class="abstract-title-text">Android Perfetto 系列 17:专项场景自动化、问题清单与平台体系</span>
</a>
<div class="abstract-content">
<p>Camera 打开慢要区分 API 返回、HAL 首个 Buffer 和预览画面显示;Audio underrun 要看 App 写入与 mixer 周期是否稳定。这些事件分散在 App、系统服务、HAL 和调度轨道里,单列一张 Top slice 表还原不了顺序。</p>
<p>这里用 Camera 和 Audio 两个场景说明:先确认一次操作涉及哪些进程和线程,再按阶段或真实周期计算耗时,最后把异常时间点、来源轨道和质量限制写进报告。平台侧还要维护稳定的事件名和采集配置,下一次 Trace 才能复用查询。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/10/15">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/05/04</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Camera">Camera</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Audio">Audio</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/05/04/Android-Perfetto-16-GPU-Power-Counters/">
<span class="abstract-title-text">Android Perfetto 系列 16:GPU、Power Counters 与硬件瓶颈分析</span>
</a>
<div class="abstract-content">
<p>FrameTimeline 标出一帧晚了,主线程和 RenderThread 没有明显长任务,下一步可以查 GPU 工作与 fence。GPU 频率、电池电流和电源轨只能提供同一窗口的硬件状态,不能单独证明某个 App 帧为何晚呈现。</p>
<p>这篇把 GPU render stages、devfreq、电池计数器和电源轨放到同一段 Trace 窗口里,说明各自能回答什么、设备不支持时报告该怎么写。帧和线程的判读可接着<a target="_blank" rel="noopener" href="https://www.androidperformance.com/2025/08/02/Android-Perfetto-07-MainThread-And-RenderThread/">第 7 篇</a>与<a target="_blank" rel="noopener" href="https://www.androidperformance.com/2025/08/05/Android-Perfetto-08-Vsync/">第 8 篇</a>的例子读。</p>
<p>Counter 名称、单位和采样周期由设备 producer 决定。跨设备比较前先核对 descriptor;同一设备上也要确认目标帧与 GPU 工作是否能通过 token、layer 或 fence 关联。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/11/03">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/05/04</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="GPU">GPU</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Power">Power</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/05/04/Android-Perfetto-15-Boot-And-Long-Running-Field-Tracing/">
<span class="abstract-title-text">Android Perfetto 系列 15:Boot Trace、长时间现场 Trace 与偶发问题抓取</span>
</a>
<div class="abstract-content">
<p>开机慢、亮屏后偶发卡顿或几小时后才出现的音频断续,通常等不到工程师连上电脑再按「开始录制」。要保留问题发生前的调度、帧或音频事件,采集配置必须提前在设备上运行。</p>
<p>现场抓取要先确定触发点前后各保留多久,再选 Ring Buffer、周期写文件或 trigger。文件写出后,还要确认问题窗口没有被覆盖、关键数据源没有丢失。设备开机属于更早的特殊窗口,单独处理。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/11/03">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/05/04</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Trace">Trace</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Field">Field</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/05/04/Android-Perfetto-14-Native-Heap-Heapprofd/">
<span class="abstract-title-text">Android Perfetto 系列 14:heapprofd 与内存 Profiling</span>
</a>
<div class="abstract-content">
<p><code>dumpsys meminfo</code> 显示进程内存上涨,Java heap dump 却没有对应的对象增长时,下一步先查上涨落在 Native Heap、图形 Buffer,还是其他映射。若可疑部分来自 malloc/new,heapprofd 可以把分配与调用栈对应起来。</p>
<p>heapprofd 的分配、释放和调用栈记录能与业务事件放在同一条 Perfetto 时间轴上,便于核对一次操作前后哪些分配仍未释放。</p>
<p>heapprofd 是采样工具,看到的 native allocation 不能直接当作 RSS,也不覆盖 Java 对象引用或所有图形 backing 内存。先分清内存账,再决定是否抓 profile。我更倾向先用 meminfo 和 smaps 把上涨来源拆开,再打开 flamegraph;若涨的是 GraphicBuffer,盯着 malloc 调用栈改代码就找错了方向。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/11/03">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/05/04</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Memory">Memory</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="heapprofd">heapprofd</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/05/04/Android-Perfetto-13-Track-Event-SDK/">
<span class="abstract-title-text">Android Perfetto 系列 13:Perfetto SDK、Track Event 与 App 现场 Trace</span>
</a>
<div class="abstract-content">
<p>系统 Trace 能显示线程、CPU、帧和 Binder 等系统事件;播放器的 frame id、游戏 scene 名称或业务队列里的等待时间,需要应用自己提供。缺少这些标记时,一段主线程耗时只能定位到系统活动,难以对应业务阶段。</p>
<p>Perfetto SDK 的 Track Event 可以记录解码、纹理上传、队列深度和跨线程任务 ID。与系统轨道放在同一个时间窗口后,能先找到业务候选阶段,再用 RenderThread、GPU 和 FrameTimeline 验证它是否影响了可见帧。</p>
<p>接入前要先定事件名称、参数单位和采样频率。否则埋点虽然能显示在 UI 中,后续 SQL 仍无法稳定地按业务阶段聚合。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/10/15">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/05/04</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="SDK">SDK</a>
<a class="post-tag" href="javascript:void(0);" data-tags="TraceEvent">TraceEvent</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/05/04/Android-Perfetto-12-Trace-Dataflow-And-Loss/">
<span class="abstract-title-text">Android Perfetto 系列 12:Trace 数据流与丢失排查</span>
</a>
<div class="abstract-content">
<p>一份 Trace 能在 UI 里打开、SQL 也查得到行,仍可能在采集中丢过数据。线程状态缺一段、进程名对不上、Track Event 只有 ID 没有名称时,先查数据丢在哪一层,再决定哪些分析还能继续。</p>
<p>SQL 只能度量留下来的事件。丢失发生在 ftrace、producer 共享内存还是 central buffer,影响的查询不同。看到一条 ftrace loss,我不会立刻扔掉整份 Trace;先查它影响的是调度、业务标记,还是帧数据。</p>
<p>下文沿事件从内核进入 Trace 文件的路径检查 ftrace、producer 共享内存、central buffer、增量状态和 flush。每一处都有对应的 <code>stats</code> 线索和下一次采集时可调整的配置。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/10/15">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/05/04</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Trace">Trace</a>
<a class="post-tag" href="javascript:void(0);" data-tags="DataFlow">DataFlow</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/05/04/Android-Perfetto-11-PerfettoSQL-TraceProcessor-Automation/">
<span class="abstract-title-text">Android Perfetto 系列 11:PerfettoSQL、Trace Processor 与回归检测</span>
</a>
<div class="abstract-content">
<p>在 Perfetto UI 里框出问题窗口,看主线程、RenderThread 和 CPU 状态,再截几张图,单次定位很方便。换一份 Trace 或换一台设备,截图里的判断就难以按同一口径重算。我更关心的是:下次拿到同一类问题,还能不能算出可复查的数字。</p>
<p>PerfettoSQL 与 Trace Processor 可以把时间窗口、线程身份和耗时口径写进查询,再让 Python 对多份 Trace 执行同一段 SQL。这样复测版本时,能回到每份原始 Trace 核对数字。</p>
<p>下面从一条手工判断出发,逐步得到可批量执行的查询和结构化输出。示例代码需要替换目标进程、时间窗口和采集条件后再用于自己的场景。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/10/15">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/05/04</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="SQL">SQL</a>
<a class="post-tag" href="javascript:void(0);" data-tags="TraceProcessor">TraceProcessor</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/04/29/SmartPerfetto-Open-Source-Perfetto-AI-Assistant/">
<span class="abstract-title-text">SmartPerfetto 开源:面向 Android Trace 分析的 Perfetto AI Assistant</span>
</a>
<div class="abstract-content">
<p>SmartPerfetto 已经完整开源。打开仓库能看到当前可运行的主干工程:Perfetto UI fork、后端 agentv3、MCP 工具、YAML Skill、场景策略、脚本和文档。没有保留私有核心模块,也没有只放一层 demo 壳。</p>
<p>这个项目来自一个很具体的日常场景:手里有一条 trace,Perfetto 已经把事实摆出来,但从事实到判断还要翻表、写 SQL、对线程、看 FrameTimeline、找 Binder 对端,再回到时间线上确认一遍。SmartPerfetto 想把这些重复动作固化成工具,让性能工程师把时间花在判断上。</p>
<p>它还处在开发阶段。现在放出来,是因为 trace 分析靠真实样本长出来:真实设备、真实厂商差异、真实业务 trace、真实 PR,都会改变 Skill 和策略该怎么写。等所有能力都稳定后再单向发布,反而会错过最需要样本的阶段。</p>
<p>如果你日常会打开 Perfetto 看滑动卡顿、启动、ANR、Binder、CPU 调度或渲染管线,SmartPerfetto 提供的是一个带 AI Assistant 的 Perfetto UI:加载 trace 后,用自然语言提问,后端查询 <code>trace_processor_shell</code>、调用 YAML Skill、组织证据,再把结论和数据表格流式显示在浏览器里。</p>
<p>项目地址:</p>
<ul>
<li>主仓库:<a target="_blank" rel="noopener" href="https://github.com/Gracker/SmartPerfetto">https://github.com/Gracker/SmartPerfetto</a></li>
<li>Perfetto UI fork:<a target="_blank" rel="noopener" href="https://github.com/Gracker/perfetto">https://github.com/Gracker/perfetto</a></li>
</ul>
<p>普通试用只需要看主仓库。<code>Gracker/perfetto</code> 是 <code>perfetto/</code> submodule 对应的前端 fork,主要给需要改 AI Assistant 插件 UI 的开发者使用。</p>
<p>前两篇技术文档更适合想看工程细节的读者:</p>
<ul>
<li><a target="_blank" rel="noopener" href="https://www.androidperformance.com/2026/04/10/SmartPerfetto-Architecture-Deep-Dive/">从 Trace 到洞察:SmartPerfetto AI Agent 的 Harness Engineering 实战</a>:SmartPerfetto AI Agent 的架构和 Harness Engineering 过程。</li>
<li><a target="_blank" rel="noopener" href="https://www.androidperformance.com/2026/04/10/SmartPerfetto-Architecture-Deep-Dive-QA/">SmartPerfetto 架构文章 Q&A:8 个深度技术问答</a>:围绕 Agent、Workflow、YAML Skill 的问答。</li>
</ul>
<p>前两篇把内部架构讲得比较细,但源码放出来以后,读者更关心的是仓库里到底有什么、能不能跑、哪些地方还没稳。这篇主要补开源这件事:开放了什么、当前能做什么、内部怎么分工、怎样在本地跑起来、哪些地方适合一起改。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/11/03">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/04/29</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="Android">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
Android
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Perfetto">Perfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Performance">Performance</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Open Source">Open Source</a>
<a class="post-tag" href="javascript:void(0);" data-tags="AI Agent">AI Agent</a>
<a class="post-tag" href="javascript:void(0);" data-tags="SmartPerfetto">SmartPerfetto</a>
<a class="post-tag" href="javascript:void(0);" data-tags="MCP">MCP</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<article class="index-post">
<a class="abstract-title" href="/2026/04/28/Agent-OS-Task-Entry/">
<span class="abstract-title-text">万字长文推演:手机不再从 App 开始,Agent OS 如何接管任务入口</span>
</a>
<div class="abstract-content">
<blockquote>
<p>以 2026 年 4 月 27 日郭明錤关于 OpenAI 手机的产业链消息为起点,从 Android 手机从业者视角,推演手机与 AI 融合之后的系统形态。</p>
</blockquote>
<h2><a href="/2026/04/28/Agent-OS-Task-Entry/#引言:这不是一台新手机的问题" class="headerlink" title="引言:这不是一台新手机的问题"></a>引言:这不是一台新手机的问题</h2><p>郭明錤这条消息最值得关注的地方,不在 2028 年量产这个时间点,也不在联发科、Qualcomm、立讯分别处在什么供应位置。</p>
<p>它把问题推到了系统层:</p>
<p>如果用户的主要目的从打开 App 转向完成任务,手机操作系统应该长什么样?</p>
<p>这句话听起来像 UI 变化,但站在 Android 从业者视角,它牵动的是一整套系统结构:Launcher、通知、权限、IPC、App 能力声明、模型运行时、TEE、端云同步、任务状态机、审计记录、支付确认、开发者分成,都会被重新审视。</p>
<p>过去几年,AI 手机的讨论大多停在功能层。厂商讲 AI 修图、AI 消除、AI 摘要、AI 搜索、AI 助手、AI 简报,这些都能放进现有 Android 或 iOS 架构里。</p>
<p>OpenAI 如果真的按 AI Agent 手机去做,它会把问题从“手机里还能塞多少 AI 功能”,推到“手机的第一入口还要不要从 App icon 开始”。</p>
<p>主线是:Agent OS 更像移动 OS 在图形界面之后的一次结构迁移。前台从 App 网格迁移到任务流,后台从 App 独占能力转为可授权能力,系统从管理进程和窗口转向管理任务、上下文与责任。</p>
<p>OpenAI 做手机不一定基于 Android,但概率很高,因为它能继承硬件适配、驱动、应用兼容和供应链经验。但如果 OpenAI 想完全按 Agent OS 设计第一屏、权限和任务流,它也可能走一条“Android 兼容但不完全是 Android”的路,甚至用 Linux 自建系统,再用 Web、云端执行和应用兼容层补齐服务。</p>
<p>不同 OS 选择会改变进入市场的速度,却不会改变 Agent OS 必须解决的五件事:</p>
<ol>
<li>手机要持续理解用户的当前状态。</li>
<li>App 要从前台入口变成后台能力提供者。</li>
<li>系统要有可恢复、可取消、可审计的任务运行时。</li>
<li>端侧与云端要按数据敏感度和实时性分工。</li>
<li>所有跨 App、跨设备、跨云的执行都要有权限、责任和回滚边界。</li>
</ol>
<p>这五件事没有完成,AI 手机就只是“手机里装了一个 AI 助手”;它们一旦形成系统约束,手机才会朝 Agent OS 走。</p>
</div>
<!-- read more -->
<div class="abstract-post-meta">
<!-- date -->
<div class="abstract-date" title="Last updated: 2026/11/03">
<span class="abstract-calander iconfont-archer"></span><span class="abstract-time">2026/04/28</span>
</div>
<!-- tags -->
<div class="abstract-tags" >
<span class="post-category" data-categories="AI">
<span class="iconfont-archer post-category-icon" aria-hidden="true"></span>
<span class="post-category-text">
AI
</span>
</span>
<a class="post-tag" href="javascript:void(0);" data-tags="Android">Android</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Agent OS">Agent OS</a>
<a class="post-tag" href="javascript:void(0);" data-tags="AI">AI</a>
<a class="post-tag" href="javascript:void(0);" data-tags="OpenAI">OpenAI</a>
<a class="post-tag" href="javascript:void(0);" data-tags="Mobile OS">Mobile OS</a>
</div>
</div>
</article>
<div class="index-post-divider"></div>
<!-- paginator -->
<nav class="page-nav">
<span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><span class="space">…</span><a class="page-number" href="/page/9/">9</a><a class="extend next" rel="next" href="/page/2/">NEXT ></a>
</nav>
</main>
<!-- profile -->
<div class="profile">
<img class="profile-avatar" alt="avatar" src="/avatar/favicons.webp" >
<div class="profile-name">Gracker</div>
<div class="profile-signature">
闻道有先后,术业有专攻,如是而已
</div>
<div class="profile-social">
<a href="mailto:Dreamtale.jg@gmail.com" class="iconfont-archer email" title="email" ></a>
<a href="https://github.com/gracker" class="iconfont-archer github" target="_blank" title="github"></a>
<span class="iconfont-archer wechat" title="wechat">
<img class="profile-qr" src="/assets/Wechat.jpeg" />
</span>
<span class="iconfont-archer qq" title="qq: 553000664">
</span>
<a href="https://weibo.com/gracker520" class="iconfont-archer weibo" target="_blank" title="weibo"></a>
<a href="https://www.zhihu.com/people/gracker" class="iconfont-archer zhihu" target="_blank" title="zhihu"></a>
<a href="https://twitter.com/Gracker_Gao" class="iconfont-archer twitter" target="_blank" title="twitter"></a>
<a href="https://juejin.im/user/557b0590e4b052e031453d76" class="iconfont-archer juejin" target="_blank" title="juejin"></a>
<a href="/atom.xml" class="iconfont-archer rss" target="_blank" title="rss"></a>
</div>
<!-- Android Weekly Button -->
<div class="profile-weekly-btn">
<a href="https://androidperformance.cn/" target="_blank" class="weekly-button">
<span class="weekly-icon">📰</span>
<span class="weekly-text">Android Weekly 周刊</span>
</a>
</div>
<!-- About Button -->
<div class="profile-weekly-btn">
<a href="/about" class="weekly-button">
<span class="weekly-icon">👤</span>
<span class="weekly-text">关于博客作者</span>
</a>
</div>
<div class="friends">
<div class="friends-title">
FRIENDS
</div>
<div class="friends-container">
<a class="friend-chip" href="https://blog.csdn.net/innost" target="_blank">邓老师</a>
<a class="friend-chip" href="https://hencoder.com" target="_blank">HenCoder</a>
<a class="friend-chip" href="http://gityuan.com/" target="_blank">Gityuan</a>
<a class="friend-chip" href="https://www.kymjs.com/" target="_blank">张涛-开源实验室</a>
<a class="friend-chip" href="http://yifeiyuan.me/" target="_blank">程序亦非猿</a>
<a class="friend-chip" href="http://weishu.me/" target="_blank">Weishu</a>
<a class="friend-chip" href="https://blog.csdn.net/singwhatiwanna" target="_blank">任玉刚</a>
<a class="friend-chip" href="https://blog.csdn.net/lzyzsd" target="_blank">大头鬼</a>
<a class="friend-chip" href="https://droidyue.com/" target="_blank">技术小黑屋</a>
<a class="friend-chip" href="http://hukai.me/" target="_blank">胡凯</a>
<a class="friend-chip" href="https://www.liaohuqiu.net/cn/" target="_blank">廖祜秋</a>
<a class="friend-chip" href="https://androidweekly.cn/" target="_blank">Android 开发技术周报</a>
<a class="friend-chip" href="https://p.codekk.com" target="_blank">CodeKK</a>
<a class="friend-chip" href="https://www.trinea.cn" target="_blank">Trinea</a>
<a class="friend-chip" href="https://www.gcssloop.com/#blog" target="_blank">GcsSloop</a>
<a class="friend-chip" href="https://juejin.im/user/589549d18d6d810058363474/posts" target="_blank">Android 研习社</a>
<a class="friend-chip" href="https://luyao.tech" target="_blank">秉心说</a>
<a class="friend-chip" href="https://juejin.cn/user/1838039172387262" target="_blank">字节跳动技术团队</a>
<a class="friend-chip" href="https://juejin.cn/user/149189312913511" target="_blank">芦半山</a>
</div>
</div>
<div class="profile-link-item">
<a href="/en/" class="profile-link-English">
<i class="fas fa-globe profile-item-icon"></i>
English
</a>
</div>
</div>
</div>
<footer class="footer footer-unloaded">
<!-- social -->
<div class="social">
<a href="mailto:Dreamtale.jg@gmail.com" class="iconfont-archer email" title="email" ></a>
<a href="https://github.com/gracker" class="iconfont-archer github" target="_blank" title="github"></a>
<span class="iconfont-archer wechat" title="wechat">
<img class="profile-qr" src="/assets/Wechat.jpeg" />
</span>
<span class="iconfont-archer qq" title="qq: 553000664">
</span>
<a href="https://weibo.com/gracker520" class="iconfont-archer weibo" target="_blank" title="weibo"></a>
<a href="https://www.zhihu.com/people/gracker" class="iconfont-archer zhihu" target="_blank" title="zhihu"></a>
<a href="https://twitter.com/Gracker_Gao" class="iconfont-archer twitter" target="_blank" title="twitter"></a>
<a href="https://juejin.im/user/557b0590e4b052e031453d76" class="iconfont-archer juejin" target="_blank" title="juejin"></a>
<a href="/atom.xml" class="iconfont-archer rss" target="_blank" title="rss"></a>
</div>
<!-- powered by Hexo -->
<div class="copyright">
<span id="hexo-power">Powered by <a href="https://hexo.io/" target="_blank">Hexo</a></span><span class="iconfont-archer power"></span><span id="theme-info">theme <a href="https://github.com/fi3ework/hexo-theme-archer" target="_blank">Archer</a></span>
</div>
<!-- website approve for Chinese user -->
<div class="website-approve">
<span id="icp-approve" class="icp-approve">
<a href="https://beian.miit.gov.cn/" target="_blank">蜀 ICP 备 20016190 号</a>
</span>
</div>
</footer>
</div>
<!-- toc -->
<!-- sidebar -->
<div class="sidebar sidebar-hide">
<ul class="sidebar-tabs sidebar-tabs-active-0">
<li class="sidebar-tab-archives"><span class="iconfont-archer"></span><span class="tab-name">Archive</span></li>
<li class="sidebar-tab-tags"><span class="iconfont-archer"></span><span class="tab-name">Tag</span></li>
<li class="sidebar-tab-categories"><span class="iconfont-archer"></span><span class="tab-name">Cate</span></li>
</ul>
<div class="sidebar-content sidebar-content-show-archive">
<div class="sidebar-panel-archives">
<!-- 在 ejs 中将 archive 按照时间排序 -->