但行好事,莫问前程——首段实习总结
写于实习期结束在即,记录实习期间的一点点心得,分享给三个月前的自己与其他同样处境的小白。
5.13—8.15,结束了为期三个月的实习,参加了转正答辩,取得了不错的反馈。作为个人第一段企业实习,从刚进公司什么都不会到慢慢接触代码,配置开发环境,进行业务分析,期间经历了很多心态上的转变与能力上的提升。下面的内容不涉及复杂的专业知识,主要是心态与方法上的总结,期待在下一次实践中复用。
实习心得
入门——重视原理,分清主次
入门一个新领域最好的方式是什么?不论哪个细分方向,在刚来什么都不会的时候,都建议先从效果业务等与日常生活紧密相关的方面开始看。比如,对于影像领域来说,什么是自动对焦?什么是自动白平衡?这些知识一来平时经常接触,容易引起兴趣从而加深记忆,二来与晦涩的代码与xml文件相去甚远,不需要刻意下功夫就可以理解。
后面有机会更新一篇AE相关的内容,是我一个上午对着资料整理出来的学习笔记。
然后就到了看代码的阶段。安卓源码可以在这里查看,影像系统相关的代码分布在framework,hardware这几个仓中,几百万行的代码一开始完全不知道怎么入手,这里的经验是只看皮毛,只懂原理,不要深入,不看细节,这个阶段一旦深入会导致陷入递归的迷惑,最后开一大堆标签页大脑成功overflow,忘了自己最开始想看的是什么😎。
可是即使一开始只看个大概还是很有难度,一上来面临的全是没有听过的名词,不理解的文件夹名、类名,看了后面忘前面,怎么解决呢?这里的经验是多找别人的代码分析,用按流程和按文件夹两种方式尽量多地增加自己对重要组件的印象。按经验像camera_provider和Camera Server这样的组件起码要看5篇别人的分析才能它们有个初步的认知,这期间通过对着别人的代码分析读代码的方式走关键流程,一边读一边记,把看到的类和里面的方法画下来(不需要理解,只做记录),这样就大概知道什么组件会参与什么流程。然后找找有没有对代码目录的介绍,了解一下每个文件夹里放的是做什么的组件,如此反复 ,再结合一些对整体架构介绍的文章,就能逐步入门。度过了最痛苦的这一段,后面遇到新的知识(比如feature2)就会快很多。
比较好的参考资料:
极客笔记
Camera 服务启动流程简析
基于Android Camera2之openCamera 流程
进阶——流程梳理,把握全局
系统这方面的工作可以说是最复杂、最难上手的方向之一,按mentor的话说社招的有5年以上MTK工作经验的员工转Qcom得1年时间才能上手。自己的直观感受就是代码实在太多了,同去实习的算法集成、效果和驱动方向的小伙伴两个月的时候已经可以慢慢上手业务,或者在组会上发表自己的看法了,自己这里还在吭哧吭哧看代码。在上面介绍的看代码的方法中,流程梳理是最关键也最漫长的一个步骤。考虑到尽量让像三个月前的我一样的小白可以看懂,在这里按顺序总结一下需要我们梳理的流程,包括进程启动以及HAL层六大流程,这里只说大白话,可能不准确,但一定够易懂:
- 进程启动:发生在手机开机的时候,完成系统服务的注册和相关组件的建立,即在此之后APP就可以调用系统的相机服务了;
- open:发生在手机点开相机app的时候,完成手机对其上摄像头的检测和上电,即在此之后你的手机就知道自己有几个什么样的摄像头,以及打开它们了;
- configure stream:等下说,先看下一个;
- request:相机app打开后立刻就看到预览画面,这时候看到的就是APP对下层请求得到的返回图像,只不过可能是每秒显示24张图像看起来在动一样。这个图像每看到一张就是APP已经下发了一次请求,而下发的过程就是这里的request。完成每一帧的相关buffer、结构体的创建等;
- result:同样在你看到预览画面的时候进行,是上面说的返回图像的过程,即对request的应答。
- 现在来说configure stream:翻译为配流,发生在request之前open之后,也就是打开相机APP到看到预览画面之间的短时间内,完成与下层对后面将要下发的request的格式信息的约定。即,告诉摄像头,等会APP要什么格式的图像,每秒24帧还是每秒60帧,4K图像还是1080p图像,RAW格式还是YUV格式等等。这里注意,每次打开相机以及切换模式时都会发生一次配流。
- flush:发生在切换相机模式或退出相机的时候,系统需要尽快清理干净buffer里没处理完的请求以便为新请求腾出位置,这个过程就是flush。这里的清理可以是正常处理完请求,也可以是直接丢弃,关键是不能超时。完成buffer清理、相关结构体的刷新。
- close:发生在关闭相机APP的时候。可以是按返回键退出,也可以是按home键挂起,均会发生close流程。完成open阶段建立的数据结构的摧毁回收工作。
上述的这个解释看似粗浅,但网上很难找到这样的解释,很多是本人过了蛮久才理解到这个程度的(比如configure stream)。带着这样的概念去看代码,可能对理解相关的逻辑有一些帮助。
流程梳理的过程中当然要画图,便于后续不看代码也能查阅相关的类和操作。这里的经验是不要画UML图,而是画详细的二维的代码分析图(自己起的名字,我也不知道它叫什么)。
UML图:
二维图:
原因在于UML虽然能清晰看到调用与返回以及它们的时序关系,但对于刚开始梳理的阶段我们往往抓不住重点,将很多不重要的函数放上去使得整个图过于繁冗,极大的影响可读性。而且拓展性差,后续看到什么新的过程想加上去很难。所以就画下面那样的二维图,便于扩展,对于错误以及冗余信息包容度高,而且美观可读,关键类的作用一目了然。
最后,硬着头皮读代码还读不懂还要画图确实是蛮有挑战性的任务(删掉),但真的随着图越来越大,每一个看过的函数、每一段走过的流程都会变成与代码设计者最好的对话,仿佛身处迷宫之中越来越高,直至一眼就能看出每一条通往终点的路。
展望——不啻微芒,造炬成阳
代码梳理的过程要持续很久,后期就可以慢慢上手实战,这之后该干什么呢?
把师兄和导师给的文档保存起来,过一阵看一眼,看不懂就先放着,总有一天突然能看懂了会觉得受益匪浅。比如前面提到的极客笔记,第1周看和第5周、第9周看的感受完全不同。
随着知识的深入明白的越来越多,不明白的也变得更多,对不了解的地方保持敬畏,该查查该问问,切忌主观臆测,不然会出现认知出现重大偏差却不自知的情况。
慢慢积累经验,从经验中总结出可复用的方法论,然后实践,然后修正,不断重复。经验是个很神奇的能力,本人亲自见证前辈依靠经验看着log在一个看上去毫无关联的地方做了修改然后解决了问题。这部分是最重要但教不会的,一定要重视积累。
向别人讲你学到了什么,并尝试回答他们的问题。一起实习的不同方向的小伙伴来问你的方向的问题,要做到能用通俗的语言把它讲清,乃至在答辩上简洁准确地回答leader的问题,需要对知识反复的总结和深入的理解。这可能不是学习新知识最好的办法,但一定是检验旧知识最有效的方法。
最后,实习期间的工作总结可以看看这里:实习工作总结
以上,共勉。