Android系统启动流程分析之安装应用

来源:互联网 发布:java中ioc是什么 编辑:程序博客网 时间:2024/05/17 04:51

2016
六月
21

Android系统启动流程分析之安装应用

   

跟随上一篇博客Android系统的启动流程简要分析继续分析android系统的启动.上一篇文章里讲了,SystemServer在main方法里创建了一个线程ServerThread,并调用
initAndLoop方法.
[java] view plain copy
  1. ServerThread thr = new ServerThread();  
  2. thr.initAndLoop();  
在initAndLoop方法里加载各种服务,比如WindowManagerService(Wms)、ActivityManagerService(Ams)、PackageManagerService(Pms)等.
看下启动PackageManagerServer的代码
[java] view plain copy
  1. pm = PackageManagerService.main(context, installer, factoryTest != SystemServer.FACTORY_TEST_OFF, onlyCore);  
这个pm是IPackageManager的实例,IPackageManager是由IPackageManager.aidl文件编译生成的.
PackageManagerService继承自IPackageManager.Stub
[java] view plain copy
  1. public class PackageManagerService extends IPackageManager.Stub {  
PackageManagerService调用main方法,传入四个参数
context 上下文
installer 安装器
factoryTest != SystemServer.FACTORY_TEST_OFF 是否为正常的工厂模式
onlyCore 为true表示在加密的设备只启动核心的程序

那么查看PackageManagerService的main方法.

PackageManagerService定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中.

main方法是这样的

[java] view plain copy
  1. public static final IPackageManager main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {  
  2.         PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);  
  3.         ServiceManager.addService("package", m);  
  4.         return m;  
  5.     }  

根据传入的四个参数创建PackageManagerService的实例,
然后通过ServiceManager添加这个PackageManagerService实例.
既然创建了这个实例,那么就调用了它的有参构造函数
1.在构造函数里会扫描制定目录的apk文件
[java] view plain copy
  1. // 扫描基础框架(没有代码的资源包)。                  
  2.                 mFrameworkInstallObserver = new AppDirObserver(frameworkDir.getPath(), OBSERVER_EVENTS, truefalsefalse);  
  3.                 mFrameworkInstallObserver.startWatching();  
  4.                 scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanMode | SCAN_NO_DEX, 0);  
  5.                   
  6.                 // 扫描system/priv-app目录             
  7.                 File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");  
  8.                 mPrivilegedInstallObserver = new AppDirObserver(privilegedAppDir.getPath(), OBSERVER_EVENTS, truetruefalse);  
  9.                 mPrivilegedInstallObserver.startWatching();  
  10.                 scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);  
  11.   
  12.                 // 扫描system/app目录                  
  13.                 File systemAppDir = new File(Environment.getRootDirectory(), "app");  
  14.                 mSystemInstallObserver = new AppDirObserver(systemAppDir.getPath(), OBSERVER_EVENTS, truefalsefalse);  
  15.                 mSystemInstallObserver.startWatching();  
  16.                 scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);  
  17.   
  18.                 // 扫描映射目录  
  19.                 File vendorAppDir = new File("/vendor/app");  
  20.                 mVendorInstallObserver = new AppDirObserver(vendorAppDir.getPath(), OBSERVER_EVENTS, truefalsefalse);  
  21.                 mVendorInstallObserver.startWatching();  
  22.                 scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);  
扫描调用的方法是scanDirLI,传入四个参数,context(上下文),flag(标志),scanMode(扫描模式),currentTime(当前时间).
2.在scanDirLI方法内部会调用
[java] view plain copy
  1. PackageParser.Package pkg = scanPackageLI(file, flags | PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);  
3.scanPackageLI通过解析安装包parsePackage获取到安装包的信息结构
[java] view plain copy
  1. PackageParser pp = new PackageParser(scanPath)  
  2.         pp.setSeparateProcesses(mSeparateProcesses);  
  3.         pp.setOnlyCoreApps(mOnlyCore);  
  4.         final PackageParser.Package pkg = pp.parsePackage(scanFile, scanPath, mMetrics, parseFlags);  
4.之后调用parsePackage的重载方法解析,将应用信息保存在PackageManagerService,比如VersionCode、VersionName等
[java] view plain copy
  1. try {  
  2.            // XXXX todo: need to figure out correct configuration.  
  3.            pkg = parsePackage(res, parser, flags, errorText);  
  4.        } catch (Exception e) {  
  5.            errorException = e;  
  6.            mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;  
  7.        }  
5.回到第3步,调用scanPackageLI的重载方法
[java] view plain copy
  1. PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime, user);6.  
6.然后调用createDataDirsLI方法
[java] view plain copy
  1. // And now re-install the app.  
  2. ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid, pkg.applicationInfo.seinfo);  
7.在createDataDirsLI方法里调用mInstaller的install方法进行安装.
[java] view plain copy
  1. int res = mInstaller.install(packageName, uid, uid, seinfo);  



0 0
原创粉丝点击