《安卓传奇:Android 缔造团队回忆录》

更新日期: 2022-12-30 阅读次数: 2391 字数: 1102 分类: 读书笔记

本以为我是天选打工人,不会变🐏,没想到我也没挺过 2022 年。在距离新年还有两天的时候,我也阳了。

请了三天假期,连上元旦三天假,大概率也能痊愈,目前症状也比较轻微。

整理了一下前一段时间看过的不错的一本书,《安卓传奇:Android 缔造团队回忆录》

九败一胜

之前一直有个错觉,以为 Android 是一蹴而就的,顺利地成为了与 iOS 比肩的手机操作系统。 没想到这个团队的成员在加入 Android 项目之前,都有过类似的操作系统项目的失败经验。

这个世界就是这样:你从失败中学到的东西可能比从成功中学到的东西更多

在开发 Android 之前,我们中的大多数人都经历过多次失败。因为当时的情况、时机或其他因素都无法让我们取得成功。在开发Android 之前,我曾参与开发3到4个失败的平台。但我们不断尝试,从每一次失败中吸取教训,并利用获得的知识来开发 Android。

大学学位

美国人对大学学位的态度确实更客观冷静一些。

“他十五分钟后给我回了邮件,问我是否需要一份工作。”于是,Brian去了加州,在这家公司进行了一整天的面试,包括与Dominic进行现场调试。就这样,Brian拿下了这份工作。面试之后,他回到家里,收拾好东西,两周后搬到了加利福尼亚。他上大学的目标是开发一个操作系统,而现在立即就有机会了,所以他认为大学学位的事情可以以后再说。

借鉴 Emacs

Zygote 是 Dalvik 小组为 Android 1.0开发的另一个东西。Zygote 就像你做三明治时用的面包片。当然,你也可以在每次做三明治时从头开始烤面包,但如果是这样的话,每次你想吃三明治都要花大量的时间和精力。很明显,如果有现成的面包,你只需要把它切成片,并更快更容易地做出三明治。Zygote 就像做三明治用的面包。Dan 的这个想法来自 Emacs(UNIX系统上的一个非常流行的文本编辑器)的一个特性,我们可以随时转储编辑器的状态,稍后可以从这个保存点启动 Emacs(这个过程被巧妙地称为反转储(undump))。这意味着Emacs可以更快地启动,因为它只需要从磁盘上恢复状态,不需要在启动时重新执行一大堆代码逻辑。“我的想法是我们实现一个具有反转储功能的系统,就像 Emacs 最‘著名’(至少对我来说)的那个特性。Mike Fleming 说:‘我们跳过转储和重新加载这些步骤,怎么样?’说完他就开干了。”

DP 的由来

最初的G1以及Droid之前的Android设备的密度都是每英寸160像素(PPI),也就是说,屏幕的每一英寸都有160个不同的颜色值(垂直和水平)。Droid的密度是265 PPI。更高的密度意味着可以表示更多的信息,可以获得更平滑的曲线和文本,或带有更多细节的图像。为了能够支持各种密度,开发人员需要用一种方法来定义他们的UI。Dianne和Romain实现的系统以DP(与密度无关的像素)为单位,开发人员可以用这个系统来定义UI,并且不依赖设备的实际像素大小。系统将根据设备的实际密度对UI进行适当的伸缩。这种处理屏幕密度的机制、资源系统基于密度提供不同资源的能力和独立于屏幕大小的UI布局系统,在Android的发展过程中起到至关重要的作用。随着厂商不停地为他们的用户推出不同格式的屏幕,Android从只能在一种设备(G1和后续配备了相同尺寸和密度的设备)上运行变成了可以支持各种屏幕尺寸和密度。

Intent 的由来

我曾和 Mike Cleron 一起开发布局系统和View系统,并提供布局和算法(Two-Pass算法)API。我还和 Dianne Hackborn 等人一起开发 Intent 机制。我记得我们在房间里花了好几小时给现在这些叫作 Intent 的东西取名字。我们花了几小时粉刷自行车棚,想找到一个最合适的名字。最后,我们想到了‘Intent’。Intent 机制背后的原理非常有趣:如何让一个应用在不知道另一个应用是否存在的情况下去调用它?这就好像我们问:‘有人能处理这个吗?’如果有人去做了,那么就说明他们能够处理。我们对此感到十分兴奋。”

推送服务也如此狼狈

推送功能是早期的主要问题之一:当一些东西在服务器端发生了变化(例如,用户的收件箱收到了电子邮件或日历事件被更新),服务器需要向设备发送通知,这样才能保持设备和服务器的数据是同步的。Debajit 发明了“挠痒痒”(Tickle)这个词。“我们想要给设备‘挠痒痒’。我们想到了轻挠(Light Tickle),意思是让设备知道有东西发生了变化,需要主动同步以获取具体内容。还有重挠(Heavy Tickle),意思是直接在通知消息里包含消息内容。我们更喜欢轻挠的方式,但具体要视情况而定。”团队想到了一个办法,就是在手机后台与谷歌服务器建立一个专用的连接。这个连接被称为移动连接服务器(Mobile Connection Server,MCS),是一种长连接,可以随时发送或接收消息,确保当服务器上有新消息时,手机就会收到通知。每个应用程序都有自己特定的数据需求,不过它们都共享这个连接,如果服务器有任何变化,都会通过这个连接通知设备。这个连接还被用于实现最初的谷歌Talk功能,用于发送和接收消息。与谷歌服务器建立长连接不只是个技术问题,因为长连接所使用的资源受到了限制。[插图]2008年10月21日,G1上市前一天的Michael Morrissey(图片由Brian Swetland提供)。长连接机制受到了网络运营团队的限制。当时,谷歌假定所有需要网络连接的东西都是基于Web的,传输数据的请求使用的是标准的Web HTTP请求。但是,Android使用了一种完全不同的协议,所以他们需要用到虚拟IP(VIP)。问题是,网络团队不想给他们。“他们给了一大堆无聊的理由。关于谷歌的做事风格,我就不多吐槽了,总之是非常罕见的。当时的网络团队大约有200个VIP,其中的一些已经用掉了,但就是不愿意给我们一个。”Debajit和Michael经常与网络团队会面,尝试说服他们给Android团队一个VIP。这种事情对Michael来说已经是家常便饭了:“我的一大部分工作就是在Gmail、日历、联系人团队和谷歌的其他举足轻重的团队之间斡旋,因为他们应该能够在技术和SRE[插图]方面给我们帮助。”最后,网络团队妥协了,给了Android一个VIP,但有个前提:如果Android在前六个月没有达到100万用户,他们将收回VIP,并且Michael和Debajit将欠他们一箱威士忌。Debajit记得:“他们在谈判时绝对提到了威士忌,那是当时的硬通货。”有了VIP,他们在5228端口上建立起了长连接,并让MCS运行了起来。最终,Android赢得了这场“赌局”,尽管Michael说这取决于时间是从什么时候开始算起的。网络运营团队说从他们提供VIP那一刻开始算起,而Michael说从1.0版本发布那一刻开始算起。无论怎么算,当时的Android都已经足够成功,所以保证了所有的Android设备都不会失去长连接。

因为Android使用了长连接,所以也需要放置在数据中心里的专用服务器上。处理数据的人都知道,为了防止主系统出问题,需要对数据进行备份。这就是为什么我们会有冗余的磁盘阵列和备份存储。这也是为什么许多家庭会有父母双亲,因为如果孩子问的问题其中一方无法回答,那么孩子还可以问另一方。但Android服务的可不只是一两个用户,他们需要一个可以服务更多用户的系统。一个备份站点是不够的,主系统完全可能出问题,而第二个备份系统也有可能出问题,尽管可能性不大。因此,为以防万一,他们启用了第三个数据中心。三个数据中心应该可以覆盖所有的故障情况了。2008年10月22日是G1上市的日子。在上半周,Android的一台服务器发生了宕机,幸好在上市之前及时恢复了过来。但在上市当天,第二台服务器又因“计划外的维护”而宕机。谷歌需要诊断问题,把它从系统里移掉了。所以,在上市当天,Android只剩下两台服务器。幸运的是,两台服务器足以撑起一个强大且无故障的系统。然后,其中的一台服务器着火了。那天,数据中心出现了过热问题,他们不得不把系统关闭。Michael说:“我们真的吓出了一身冷汗——我们只剩下最后一台服务器了!已经没了两台,如果第三台再宕机,所有的同步功能都将无法正常工作,聊天功能也没有了。我们真的很恐慌。”好在最后一台服务器一直正常运行,没有发生宕机。但团队几乎与死神擦肩而过,这是他们之前所没有预料到的。

安全更新策略

最后一个问题是如何保证安全性。更新系统可以修改只读的部分,因为它需要更新设备上的核心操作系统。那么,怎样才能防止一些恶意软件把自己伪装成更新软件对系统进行篡改呢?Dan和他的团队在Android安全团队的帮助下采用了一种方法,即只允许受信任的文件替换系统文件。每个更新模块都需要进行密钥签名,系统将会验证它们是否被Android信任。安全团队还增加了一层保护,除了每个单独的模块有密钥加密,整个更新也有一个额外的密钥加密层。只有有了这些层,系统才是安全的,才能被发布(和更新)。

灰度发布与监控机制

当时,Michael正在从西雅图搬到山景城。他想:“一切似乎都没问题了,我要休一星期假,顺便搬家。几天后,也就是在周二晚上十点,我的电话响了,是Dan Egnor打来的。我接通了电话,问:‘Dan,发生什么事了?’他说:‘首先,我想让你知道,一切都很好。’我的第一感觉是肯定是哪里出问题了。‘只是……我们让很多手机变砖了。’”原来,增量更新镜像与HTC(G1的厂商)安装在手机上的镜像略有不同。只有当系统与镜像完全匹配时,更新系统才能进行增量更新。所以,当增量更新被安装到这些手机上时,系统就被破坏了,设备也就变砖了。好消息是,当时受影响的手机只有129部。但对于那些用户来说,这仍然是一件可怕的事情。他们都通过客服换了新手机。但这129部之外的其他G1手机都在这次灾难性的故障中完好无损。这个问题之所以能够得到如此好的控制,是因为团队使用了分阶段发布和CheckIn服务机制,它们确实发挥了预期的作用。Dan和Doug也一直在监控这些更新,并立即发现了这个问题。他们停止了更新,直到诊断出并解决了这个问题。

谷歌地图

Charles当时对移动技术并不是特别感兴趣。“那时候我还没有手机。我从来都不喜欢手机,它们对我来说就是一种烦恼。人们可以随时打扰你。谁希望这样?”第二年,Charles的妻子怀上了他们的第一个孩子,这让Charles有了开发一款应用程序的想法。“我需要知道她在哪里。如果我要去接她,并把她送去医院,我希望能看到医院的位置。”他想开发一款能够为他提供这些信息的应用程序。

西雅图办公室的Keith Ito正在研究逐向导航。为了解决数据问题,他研究了一种新的显示地图的方法,即使用矢量。[插图]矢量是一种使用几何图形而不是图片来描述图像(如地图)的方法。服务器向手机发送的不是地图的图像(在图片中嵌入了文本),而是地图的几何描述,设备可以基于这些描述通过适当的分辨率和旋转角度绘制出地图,而且数据量比PNG图像要小得多。

中美文化差异

Android 希望通过 Android Market 来解决这个问题。他们希望为开发者提供一个可以上传应用的商店。服务团队负责人Michael Morrissey 向 Nick Sears 描述了他的目标:“我希望能够做到:堪萨斯州的一个14岁的孩子早上开发好应用,下午上传到 Android Market,然后所有的用户都能下载。”

我们则是竭尽所能地阻止个人开发者发布程序。

嵌入式开发经验

Ficus回忆起他在Be和Danger的经历对他在Android的工作产生了怎样的影响:“说到CPU和内存,我们当中有很多人都做过嵌入式系统,都形成了一种极度节约的理念。我觉得这是看待Android早期决策的一个非常有趣的视角。我看到很多这样的工程师,好像他们是在大萧条时期长大似的,已经学会了如何将就过日子。”整个平台团队把性能放在第一位。这是因为早期的设备内存有限,CPU速度慢,缺少GPU渲染(直到发布Honeycomb时,Android才有了用于渲染UI图形的GPU。

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式