`
dengzhangtao
  • 浏览: 678918 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

系统移植之为Android启动加速

 
阅读更多

Android的启动速度一直以来是他的诟病,虽然现在Android设备的硬件速度越来越快,但是随着新版本的出现,其启动速度一直都比较慢,当然,作为程序员,我们是可以理解的,智能手机本身就要启动很多服务来支持应用的功能,并且Android系统大部分还是使用的Java语言编写的,必然要运行在Java虚拟机里,这也决定了它运行速度和启动速度都相对较慢。同时,Android系统为了在执行用户应用程序时提高用户体验,还做了一些预加载机制,这也牺牲了开机启动时间。

根据Android启动过程的分析可知,我们可以进行定制加速如下:

Ø  定制本地服务

Ø  定制Android系统服务

Ø  优化ZygoteInit的类预加载preloadClasses和资源预加载preloadResources机制

Ø  PackageManagerService扫描、检查APK安装包信息

下面我们依次来分析其实现步骤。

 

1. 定制本地服务

由第二章,第2节可知,本地服务都是由C或C++编写,它们都执行在Linux空间,在init进程的启动过程中启动了很多本地服务,如果我们的设备中没有电话模块、蓝牙模块,我们可以将这些没用的本地服务在init.rc里注释掉。/system/core/rootdir/init.rc

 

  1. 396 #service ril-daemon /system/bin/rild  
  2. 397#     class main  
  3. 398#     socket rild stream 660 root radio  
  4. 399#     socket rild-debug stream 660 radio system  
  5. 400#     user root  
  6. 401#     group radio cache inet misc audio sdcard_rw log  
  7.   
  8. 435 service dbus /system/bin/dbus-daemon --system --nofork  
  9. 436     class main  
  10. 437 #    socket dbus stream 660 bluetooth bluetooth  
  11. 438     user bluetooth  
  12. 439     group bluetooth net_bt_admin  
  13.   
  14.  441 #service bluetoothd /system/bin/bluetoothd -n  
  15. 442 #    class main  
  16. 443 #    socket bluetooth stream 660 bluetooth bluetooth  
  17. 444 #    socket dbus_bluetooth stream 660 bluetooth bluetooth  
  18. 445     # init.rc does not yet support applying capabilities, so run as root and  
  19. 446     # let bluetoothd drop uid to bluetooth with the right linux capabilities  
  20. 447 #    group bluetooth net_bt_admin misc  
  21. 448 #    disabled  

重新编译system.img然后启动模拟器即可。

笔者做了对比,去掉上述几个本地服务与没有去掉本地服务,二者在开机时间上几乎没有减少多少,这也可以理解,因为本地服务就是几个程序,少执行和多执行几个程序对于总体开机时间没有多大影响,不过,去掉没有使用的本地服务,对整个系统性能来说,会有微不足道的提升。

如果去掉开机动画服务可以大大的提高系统的启动速度:

  1. 433 #service bootanim /system/bin/bootanimation  
  2. 434 #    class main  
  3. 435 #    user graphics  
  4. 436 #    group graphics  
  5. 437 #    disabled  
  6. 438 #    oneshot  

 

2. 定制Android系统服务

Android的启动过程可知,init进程启动了app_process作为zygote,在app_process里启动了Dalvik虚拟机,然后加载执行了第一个Java程序ZygoteInit作为Dalvik主线程,在ZygoteInitfork了第一个Java程序SystemServer,在SystemServer里启动了大量的Android的核心服务,通常来说这些服务一般不要去动,如果我们的设备里没有使用过某些服务,并且将来也明确不使用,可以将其去掉。

\frameworks\base\preloaded-classes

我们先来看看SystemServer启动了哪些Android服务:

[plain] view plaincopy
  1. EntropyService:熵(shang)服务,用于产生随机数  
  2. PowerManagerService:电源管理服务  
  3. ActivityManagerService:最核心服务之一,Activity管理服务  
  4. TelephonyRegistry:电话服务,电话底层通知服务  
  5. PackageManagerService:程序包管理服务  
  6. AccountManagerService:联系人帐户管理服务  
  7. ContentService:内容提供器的服务,提供跨进程数据交换  
  8. LightsService:光感应传感器服务  
  9. BatteryService:电池服务,当电量不足时发广播  
  10. VibratorService:震动器服务  
  11. AlarmManagerService:闹钟服务  
  12. WindowManagerService:窗口管理服务  
  13. BluetoothService:蓝牙服务  
  14. InputMethodManagerService:输入法服务,打开关闭输入法  
  15. AccessibilityManagerService:辅助管理程序截获所有的用户输入,并根据这些输入给用户一些额外的反馈,起到辅助的效果,View的点击、焦点等事件分发管理服务  
  16. DevicePolicyManagerService:提供一些系统级别的设置及属性  
  17. StatusBarManagerService:状态栏管理服务  
  18. ClipboardService:粘贴板服务  
  19. NetworkManagementService:手机网络管理服务  
  20. TextServicesManagerService:  
  21. NetworkStatsService:手机网络状态服务  
  22. NetworkPolicyManagerService:  
  23. WifiP2pService:Wifi点对点直联服务  
  24. WifiService:WIFI服务  
  25. ConnectivityService:网络连接状态服务  
  26. ThrottleService:modem节流阀控制服务  
  27. MountService:磁盘加载服务,通常也mountd和vold服务结合  
  28. NotificationManagerService:通知管理服务,通常和StatusBarManagerService  
  29. DeviceStorageMonitorService:存储设备容量监听服务  
  30. LocationManagerService:位置管理服务  
  31. CountryDetectorService:检查当前用户所在的国家  
  32. SearchManagerService:搜索管理服务  
  33. DropBoxManagerService:系统日志文件管理服务(大部分程序错误信息)  
  34. WallpaperManagerService:壁纸管理服务  
  35. AudioService:AudioFlinger上层的封装的音量控制管理服务  
  36. UsbService:USB Host和device管理服务  
  37. UiModeManagerService:UI模式管理服务,监听车载、座机等场合下UI的变化  
  38. BackupManagerService:备份服务  
  39. AppWidgetService:应用桌面部件服务  
  40. RecognitionManagerService:身份识别服务  
  41. DiskStatsService:磁盘统计服务  
  42. SamplingProfilerService:性能统计服务  
  43. NetworkTimeUpdateService:网络时间更新服务  

天啊,43Android服务,

除了对原生的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。

  1. public static final IPackageManager main(Context context, boolean factoryTest) {  
  2.         PackageManagerService m = new PackageManagerService(context, factoryTest);  
  3.         ServiceManager.addService("package", m);  
  4.         return m;  
  5. }  

3.2  PackageManagerService构造方法中,首先会进行一些成员变量的初始化,比如mContext, mFactoryTest, mMetrics, mSettings等。
最重要的是初始化mInstaller这个变量。Installer是一个很重要的类,所有对apk的install, uninstall,move等操作,都是通过它进行的。

  1. Installer installer = new Installer();  
  2.     if (installer.ping() && Process.supportsProcesses()) {  
  3.         mInstaller = installer;  
  4.     } else {  
  5.         mInstaller = null;  
  6.     }  

3.3  建立PackageHandler消息循环,用于处理外部的apk安装请求消息,如adb install,packageinstaller安装apk时会发送消息

  1. mHandlerThread.start();  
  2.     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进行签名和证书校验,进行完整性验证。

3.9  将解析的每个apk的信息保存到packages.xml和packages.list文件里,packages.list记录了如下数据:pkgName,userId,debugFlag,dataPath(包的数据路径)

 

其中对/system/framework,/system/app,/data/app,/data/app-private目录中的APK扫描耗费了大量的时间,通过下面的笔者的实验结果可以看得出来。


 无优化时的APK总计有50个,减少APK时APK只有5个,包扫描的时间减少了4秒,Android服务启动的时间减少了近10秒,整个系统的启动时间减少了15秒左右

在减少APK的情况下,然后将开机动画关闭了,本地服务启动时间略有减少,预加载类与资源时减少了近10秒,包扫描时间减少了0.5秒左右,Android服务启动时间减少近4秒,整个系统启动时间减少了近15秒。

由此可见,减少APK的数量关闭开机动画可以明显的提高Android的启动速度。

至于关闭其它本地服务对启动时间影响不大的原因,我的感觉是本地服务注册到Binder之后就等待框架客户端的连接,而关闭开机动画对启动速度影响之大,通过分析bootanim可知,在开启动画时要开启一个线程,mask图片在前面作为幕布,shine图片在后面每隔一定时间重新绘制一次,每次绘制时通过调用OPENGL的api调用2D加速来绘制图片,而我们使用的模拟器,全部操作通过软件来模拟,所以对系统怕启动速度影响比较大。如果在具体的设备上执行对启动速度的影响应该比这要小,具体硬件设备上优化,后续会有博文推出。

 

4. Android系统企业级定制

在做Android产品开发的过程中,经常会有客户说:“我们不想让我们的产品开机后看到Android系统的桌面,我们希望设备开机会直接进入我们自己的程序“。“我们的产品就是直接面对最终用户的,其它的无关的功能不需要。”比如说,之前我们开发的一款社区医疗软件,通过蓝牙和心电仪、血糖仪等采集外设通信,客户要求开机进入医疗软件,通过底层蓝牙通信,我们采用的就是定制的Android平板的桌面。

通常定制应用程序开机启动有两种实现方式:

Ø  接收系统启动广播:BOOT_COMPLETED,在广播接收器代码里实现应用程序的启动。

Ø  编写一个桌面程序,替换掉系统默认的Launcher应用。

第一种方式实现简单,但是这个应用程序是在Android系统桌面出现之后再启动的,不是真正意义上的产品定制,并且,如果当前的应用程序崩溃了退出后,会回到桌面上,当然我们可以实现崩溃后再次重新启动,但是,这终究不是真正意义上的定制。

第二种实现方式思路:当系统启动完毕之后,系统会发出一个Actionandroid.intent.action.MAINcategoryandroid.intent.category.HOMEIntent,默认系统的Launcher桌面会响应这个Intent,那么,我们可以编写一个应用程序,让它去响应这个Intent,然后我们将这个应用程序替换掉系统默认的Launcher桌面。系统重新启动之后,会自动启动我们自己的应用。但是,如果一些非法程序也响应这个Intent,那么照样不能达到客户的目的。这个时候,我们就要去修改系统框架代码,让Android系统启动完毕之后发送我们自己定义的Intent而不是公开的categoryHOME Intent

思路如下:

Ø  添加一个新的categoryandroid.intent.category.FS_HOME

Ø  将框架里面所有发送android.intent.category.HOMEIntent全部改成android.intent.category.FS_HOME

category的定义文件在:

@ frameworks/base/core/java/android/content/Intent.java

[java] view plaincopy
  1. 2218     /** 
  2. 2219      * This is the home activity, that is the first activity that is displayed 
  3. 2220      * when the device boots. 
  4. 2221      */  
  5. 2222     @SdkConstant(SdkConstantType.INTENT_CATEGORY)  
  6. 2223     public static final String CATEGORY_HOME = "android.intent.category.HOME";  

CATEGORY_HOME后面添加下面两行代码:

[java] view plaincopy
  1. 2224     @SdkConstant(SdkConstantType.INTENT_CATEGORY)  
  2. 2225     public static final String CATEGORY_FS_HOME = "android.intent.category.FS_HOME";  

通过grep CATEGORY_HOME frameworks/ -R命令查找所有使用CATEGORY_HOME的文件:

[plain] view plaincopy
  1. ./frameworks/ex/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java  
  2. ./frameworks/base/services/java/com/android/server/am/ActivityManagerService.java  
  3. ./frameworks/base/services/java/com/android/server/am/ActivityRecord.java  
  4. ./frameworks/base/services/java/com/android/server/UiModeManagerService.java  
  5. ./frameworks/base/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java  
  6. ./frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java  
  7. ./frameworks/base/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java  
  8. ./frameworks/base/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java  

将文件里使用CATEGORY_HOME常量的地方全部改为CATEGORY_FS_HOME

新建一个Android应用:MyLauncher,在其AndroidManifest.xml里,<intent-filter>标签里添加上响应CATEGORY_FS_HOME的代码:

[html] view plaincopy
  1. <span style="font-size:10px;"><activity android:name=".MyLauncherActivity">  
  2.         <intent-filter>  
  3.                 <action android:name="android.intent.action.MAIN" />  
  4.                 <category android:name="android.intent.category.FS_HOME" />  
  5.                    <category android:name="android.intent.category.DEFAULT" />  
  6.         </intent-filter>  
  7. </activity></span>  

重新编译frameworks/baseframeworks/ex

[plain] view plaincopy
  1. $ source build/envsetup.sh  
  2. $ make  

重新运行模拟器,使用新编译的Android系统,可以看到系统启动起来就进入我们的MyLauncher应用,从实现实现桌面的替换。

 

0
0
分享到:
评论

相关推荐

    android 系统移植讲解

    Android系统移植是一个复杂而精细的过程,它涉及到操作系统内核、硬件驱动、用户界面以及应用程序等多个层面的整合。本文将深入探讨Android系统移植的关键步骤和重要知识点。 首先,我们需要理解Bootloader。...

    xbmc 移植到ANDROID 方法

    XBMC(Xbox Media Center)是一款开源媒体播放器应用,最初为Xbox游戏机开发,后来被移植到了多个操作系统上,包括Android。将XBMC移植到Android平台上需要进行一系列准备工作,包括设置Android开发环境、获取源代码...

    基于SuperH架构的Android系统移植与设计(实用版)

    对于Android系统的移植,主要工作是处理显示模块的加速和其他上层功能的适配。需要配置Init进程和目录结构,并对显示模块进行优化以适应SuperH硬件平台的特性。 整个论文的组织结构清晰,从绪论的研究背景、研究...

    基于Zynq平台的Android操作系统移植.pdf

    通过上述步骤,成功移植Android操作系统到Zynq平台后,开发者可以获得一个功能完善的嵌入式系统,可以用于各种应用,例如工业控制、智能设备、多媒体系统等。这极大地拓展了Zynq平台的应用范围,使其不仅仅局限于无...

    面向S5PV210嵌入式平台的Android系统移植与优化的研究.pdf

    在S5PV210平台上移植Android系统,主要涉及到以下几个关键步骤: 1. **内核移植**:Android系统的运行依赖于特定的Linux内核,因此首先需要将Android的驱动程序集成到S5PV210的Linux内核中。这包括设备树配置、内核...

    基于Android平台的可视对讲系统的设计与实现

    Android系统需经过移植,将U-Boot、Linux内核、根文件系统和Android镜像烧录到SD卡上,通过ATK工具进行下载和启动。 总的来说,基于Android平台的可视对讲系统实现了高效率、高性能的音视频通信,其设计和实现充分...

    android在s3c6410上的移植.doc

    将Android系统移植到S3C6410平台上,不仅能够充分发挥硬件性能,还能利用Android丰富的应用生态,为用户提供更加智能便捷的服务体验。 #### 二、S3C6410平台概述 S3C6410是一款基于ARM1176JZF-S内核的高性能多媒体...

    Android 系统开发讲义

    根据文件内容,我们可以提炼出以下Android系统开发相关的知识点: 1. Android系统概览 Android系统是一个基于Linux内核的开源操作系统,主要应用于移动设备。它由Google公司主导开发,并对其他公司和开发者开源。...

    Androidapp接入PaddleOCR资源

    3. **处理模型**: 使用PaddleInference的工具将模型转换为适用于Android的格式,例如,可以使用`tools/infer_lite/build.sh`脚本进行转换。 **二、Android项目集成** 1. **创建资源文件夹**: 在Android项目的`...

    Android4.4真机移植过程笔记

    ### Android4.4真机移植过程笔记 #### 1. RK 源码编译 在进行Android4.4真机移植过程中,首先需要获取内核源码,并且准备相应的编译环境。以下是对该部分的详细说明: - **获取内核源码**: - 使用`git clone`...

    嵌入式Linux系统中GUI系统的研究与移植.pdf.doc

    应用程序框架则为开发者提供了创建GUI应用程序的工具和指导,例如Android的JNI或Linux下的EFL。 在嵌入式环境中,选择GUI系统时需要考虑以下因素: 1. 性能:嵌入式设备通常资源有限,因此需要选择轻量级且高效的...

    IMX6 android 4.3.1 v1.1.0 docs

    1. **Android_Quick_Start_Guide.pdf**:这份快速入门指南为开发者和用户提供了在i.MX6平台上安装和启动Android 4.3.1 v1.1.0的基本步骤。它可能涵盖了硬件初始化、系统镜像烧录、设备连接以及初步的调试信息。 2. ...

    exrb-boot一键移植

    在IT行业中,特别是Android开发领域,"exrb-boot一键移植"是一个非常实用的工具,它主要涉及到了系统启动流程中的核心组件——boot和recovery的处理。Bootloader、Boot Image(boot)以及Recovery Mode是Android系统...

    android-x86-64-8.1-r6

    为了在PC上体验Android系统,开发者们推出了Android-x86项目,它将Android系统移植到x86平台,让Windows、Linux和Mac OS等系统的用户也能运行Android应用。本文将深入探讨“android-x86-64-8.1-r6”这一特定版本,带...

    我和菜鸟一起学android4.0.3源码之硬件gps简单移植.doc

    Android 系统提供了多种定位方式,包括 GPS 定位、WIFI 定位、基站定位和 AGPS 定位。每种方式都有其特点和适用场景。 1. **Android GPS 定位** - GPS 定位依赖硬件支持,通过直接与卫星通信获取精确的经纬度坐标...

    开始使用 Xamarin.Android 开发 Android 应用

    3. **将 Java 移植到 C#**:将 Java 代码转换为 C#。 4. **绑定 Java 库**: - **绑定 .JAR 文件**:绑定 Java 类库。 - **绑定 .AAR 文件**:绑定 Android 库项目。 - **绑定 Eclipse 库项目**:集成 Eclipse ...

Global site tag (gtag.js) - Google Analytics