Android的启动速度一直以来是他的诟病,虽然现在Android设备的硬件速度越来越快,但是随着新版本的出现,其启动速度一直都比较慢,当然,作为程序员,我们是可以理解的,智能手机本身就要启动很多服务来支持应用的功能,并且Android系统大部分还是使用的Java语言编写的,必然要运行在Java虚拟机里,这也决定了它运行速度和启动速度都相对较慢。同时,Android系统为了在执行用户应用程序时提高用户体验,还做了一些预加载机制,这也牺牲了开机启动时间。
根据Android启动过程的分析可知,我们可以进行定制加速如下:
Ø 定制本地服务
Ø 定制Android系统服务
Ø 优化ZygoteInit的类预加载preloadClasses和资源预加载preloadResources机制
Ø PackageManagerService扫描、检查APK安装包信息
下面我们依次来分析其实现步骤。
1. 定制本地服务
由第二章,第2节可知,本地服务都是由C或C++编写,它们都执行在Linux空间,在init进程的启动过程中启动了很多本地服务,如果我们的设备中没有电话模块、蓝牙模块,我们可以将这些没用的本地服务在init.rc里注释掉。
- 396 #service ril-daemon /system/bin/rild
- 397# class main
- 398# socket rild stream 660 root radio
- 399# socket rild-debug stream 660 radio system
- 400# user root
- 401# group radio cache inet misc audio sdcard_rw log
- 435 service dbus /system/bin/dbus-daemon --system --nofork
- 436 class main
- 437 # socket dbus stream 660 bluetooth bluetooth
- 438 user bluetooth
- 439 group bluetooth net_bt_admin
- 441 #service bluetoothd /system/bin/bluetoothd -n
- 442 # class main
- 443 # socket bluetooth stream 660 bluetooth bluetooth
- 444 # socket dbus_bluetooth stream 660 bluetooth bluetooth
- 445 # init.rc does not yet support applying capabilities, so run as root and
- 446 # let bluetoothd drop uid to bluetooth with the right linux capabilities
- 447 # group bluetooth net_bt_admin misc
- 448 # disabled
重新编译system.img然后启动模拟器即可。
笔者做了对比,去掉上述几个本地服务与没有去掉本地服务,二者在开机时间上几乎没有减少多少,这也可以理解,因为本地服务就是几个程序,少执行和多执行几个程序对于总体开机时间没有多大影响,不过,去掉没有使用的本地服务,对整个系统性能来说,会有微不足道的提升。
如果去掉开机动画服务可以大大的提高系统的启动速度:
- 433 #service bootanim /system/bin/bootanimation
- 434 # class main
- 435 # user graphics
- 436 # group graphics
- 437 # disabled
- 438 # oneshot
2. 定制Android系统服务
由Android的启动过程可知,init进程启动了app_process作为zygote,在app_process里启动了Dalvik虚拟机,然后加载执行了第一个Java程序ZygoteInit作为Dalvik主线程,在ZygoteInit里fork了第一个Java程序SystemServer,在SystemServer里启动了大量的Android的核心服务,通常来说这些服务一般不要去动,如果我们的设备里没有使用过某些服务,并且将来也明确不使用,可以将其去掉。
我们先来看看SystemServer启动了哪些Android服务:
- EntropyService:熵(shang)服务,用于产生随机数
- PowerManagerService:电源管理服务
- ActivityManagerService:最核心服务之一,Activity管理服务
- TelephonyRegistry:电话服务,电话底层通知服务
- PackageManagerService:程序包管理服务
- AccountManagerService:联系人帐户管理服务
- ContentService:内容提供器的服务,提供跨进程数据交换
- LightsService:光感应传感器服务
- BatteryService:电池服务,当电量不足时发广播
- VibratorService:震动器服务
- AlarmManagerService:闹钟服务
- WindowManagerService:窗口管理服务
- BluetoothService:蓝牙服务
- InputMethodManagerService:输入法服务,打开关闭输入法
- AccessibilityManagerService:辅助管理程序截获所有的用户输入,并根据这些输入给用户一些额外的反馈,起到辅助的效果,View的点击、焦点等事件分发管理服务
- DevicePolicyManagerService:提供一些系统级别的设置及属性
- StatusBarManagerService:状态栏管理服务
- ClipboardService:粘贴板服务
- NetworkManagementService:手机网络管理服务
- TextServicesManagerService:
- NetworkStatsService:手机网络状态服务
- NetworkPolicyManagerService:
- WifiP2pService:Wifi点对点直联服务
- WifiService:WIFI服务
- ConnectivityService:网络连接状态服务
- ThrottleService:modem节流阀控制服务
- MountService:磁盘加载服务,通常也mountd和vold服务结合
- NotificationManagerService:通知管理服务,通常和StatusBarManagerService
- DeviceStorageMonitorService:存储设备容量监听服务
- LocationManagerService:位置管理服务
- CountryDetectorService:检查当前用户所在的国家
- SearchManagerService:搜索管理服务
- DropBoxManagerService:系统日志文件管理服务(大部分程序错误信息)
- WallpaperManagerService:壁纸管理服务
- AudioService:AudioFlinger上层的封装的音量控制管理服务
- UsbService:USB Host和device管理服务
- UiModeManagerService:UI模式管理服务,监听车载、座机等场合下UI的变化
- BackupManagerService:备份服务
- AppWidgetService:应用桌面部件服务
- RecognitionManagerService:身份识别服务
- DiskStatsService:磁盘统计服务
- SamplingProfilerService:性能统计服务
- NetworkTimeUpdateService:网络时间更新服务
天啊,43个Android服务,
除了对原生的Android系统定制外,还可以通过引入外部技术来提升开机速度,目前有人使用Berkeley Lab Checkpoint/Restart(BLCR)技术给系统做一个快照,类似于Vmware里用的SnapeShot和Windows里的休眠机制,它能将当前Android环境保存在一个文件里,当下次启动的时候从该文件恢复Android运行环境,这种方式可以明显的提升启动速度,其实现过程比较复杂。
BLCR技术细节后续再完善。。。
3. PackageManagerService
PackageManagerService是Android的包管理器,主要用来管理Android系统中的APK文件,在SystemServer里,通过ServerThread调用PackageManagerService.main()启动了包管理服务。
PackageManagerService的主要作用有:
3.1 @PackageManagerService.main()
生成一个IPackageManager接口,也就是PackageManagerService。
- public static final IPackageManager main(Context context, boolean factoryTest) {
- PackageManagerService m = new PackageManagerService(context, factoryTest);
- ServiceManager.addService("package", m);
- return m;
- }
3.2 PackageManagerService构造方法中,首先会进行一些成员变量的初始化,比如mContext, mFactoryTest, mMetrics,
mSettings等。
最重要的是初始化mInstaller这个变量。Installer是一个很重要的类,所有对apk的install, uninstall,move等操作,都是通过它进行的。
- Installer installer = new Installer();
- if (installer.ping() && Process.supportsProcesses()) {
- mInstaller = installer;
- } else {
- mInstaller = null;
- }
3.3 建立PackageHandler消息循环,用于处理外部的apk安装请求消息,如adb install,packageinstaller安装apk时会发送消息
- mHandlerThread.start();
- mHandler = new PackageHandler(mHandlerThread.getLooper());
3.4 解析/system/etc/permission下xml文件(framework/base/data/etc/),包括platform.xml和系统支持的各种硬件模块的feature。
主要工作:
(1)建立底层user ids和group ids 同上层permissions之间的映射;可以指定一个权限与几个组ID对应。当一个APK被授予这个权限时,它也同时属于这几个组。
(2)给一些底层用户分配权限,如给shell授予各种permission权限;把一个权限赋予一个UID,当进程使用这个UID运行时,就具备了这个权限。
(3) library,系统增加的一些应用需要link的扩展jar库;
(4) feature,系统每增加一个硬件,都要添加相应的feature.将解析结果放入mSystemPermissions,mSharedLibraries,mSettings.mPermissions,mAvailableFeatures等几个集合中供系统查询和权限配置使用。
3.5 检查/data/system/packages.xml是否存在,这个文件是在解析apk时由writeLP()创建的,里面记录了系统的permissions,以及每个apk的name,codePath,flags,ts,version,uesrid等信息,这些信息主要通过apk的AndroidManifest.xml解析获取,解析完apk后将更新信息写入这个文件并保
存到flash,下次开机直接从里面读取相关信息添加到内存相关列表中。当有apk升级,安装或删除时会更新这个文件。
3.6 检查BootClassPath,mSharedLibraries及/system/framework下的jar是否需要dexopt,需要的则通过dexopt进行优化。
3.7 启动AppDirObserver线程监测/system/framework,/system/app,/data/app,/data/app-private目录的事件,主要监听add和remove事件。对于目录监听底层通过inotify机制实现,inotify
是一种文件系统的变化通知机制,如文件增加、删除等事件可以立刻让用户态得知,它为用户态监视文件系统的变化提供了强大的支持。
- 当有add event时调用scanPackageLI(File , int , int)处理;
- 当有remove event时调用removePackageLI()处理;
3.8 对于以上几个目录下的apk逐个解析,主要是解析每个apk的AndroidManifest.xml文件,处理asset/res等资源文件,建立起每个apk的配置结构信息,并将每个apk的配置信息添加到全局列表进行管理。调用installer.install()进行安装工作,检查apk里的dex文件是否需要再优化,如果需要优化则通过辅助工具dexopt进行优化处理;将解析出的componet添加到pkg的对应列表里;
对apk进行签名和证书校验,进行完整性验