Android Install应用过程分析

一,PackageManagerService启动时所做的部分工作分析

● 构造线程对象mHandlerThread对象,构造时传递参数PackageManager,定义PackageHandler变量对象。

 final HandlerThread mHandlerThread =             newHandlerThread("PackageManager",Process.THREAD_PRIORITY_BACKGROUND);   

final PackageHandler mHandler;

● 在PackageManagerService构造的时候执行以下操作,

1 启动带Looper循环的线程mHandlerThread。    

  mHandlerThread.start();

2 构造PackageHandler 对象,传进去的是mHandlerThread.getLooper()对象。即对mHandlerThread线程的消息队列进行处理。mHandler = new PackageHandler(mHandlerThread.getLooper());

 3 将mHandlerThread线程交给看门狗,每隔WATCHDOG_TIMEOUT时间,Watchdog会检查该线程是否存在,不存在就立即启动该线程。

      Watchdog.getInstance().addThread(mHandler,mHandlerThread.getName(),

                    WATCHDOG_TIMEOUT);

二,安装应用的过程分析

 ● 当点击install按钮时,系统的调用堆栈如下:

           

● 最终会调到    PackageManagerService$DefaultContainerConnection.onServiceConnected(ComponentName name, IBinderservice),此时会向mHandlerThread线程发送MCS_BOUND消息。

              

● mHandlerThread线程启动的时候,HandlerThread.run()方法调用。进入Looper.loop()循环,如下图:

          

● 接着调用PackageManagerService$PackageHandler(Handler).dispatchMessage(Message)即调用PackageHandler父类Handler的dispatchMessage,

     

● 接着调用PackageManagerService$PackageHandler.handleMessage(Message),如下图:

    

● doHandleMessage()中对MCS_BOUND消息进行处理如下:  


● startCopy()执行


●handleStartCopy()执行,接下来会通过binder通信调用DefaultContainerService中第一个匿名内部类中的getMinimalPackageInfo方法。

● 在getMinimalPackageInfo方法中调用 PackageParser.parsePackageLite对APK进行解析。


● 在其重载的方法parsePackageLite里对AndroidManifest.xml解析。判断该APKAndroidManifest里是否有installLocation标签属性,有点话就取出来赋给installLocation

● 将解析出的PackageLite pkg对象各成员变量值虎给PackageInfoLite ret 对象各成员。接着调用recommendAppInstallLocation方法对该对象的recommendedInstallLocation成员赋值。最后返回PackageInfoLite 对象ret。

● 以下对recommendAppInstallLocation()分析。


● 首先根据flags做判断,如果设置flags,AndroidManifest.xml中的installLocation标签将失效。没有设置flags的话,检查AndroidManifest.xml中的installLocation标签。如果AndroidManifest.xml中的没设置installLocation标签则检查用户设置 user preference,取SettingProvider中的DEFAULT_INSTALL_LOCATION值。以上各种判断都为了设置prefer值。以下会根据prefer值返回PackageHelpe中的某一个常量值赋给ret.recommendedInstallLocation。最后返回PackageInfoLite 对象ret给handleStartCopy() 的局部变量pkgLite,

● 接下来对(pkgLite.recommendedInstallLocation值做判断。

● 当cpcyResource返回值为INSTALL_SUCCEEDED时,对 pkgLite.recommendedInstallLocation 值做进一步判断。


三 安装百度地图和给力开关两个应用做对比

● 由于百度地图的AndroidManifest.xml中设置有installLocation标签,并且设置值为PackageInfo.INSTALL_LOCATION_AUTO,故其在recommendAppInstallLocation方法中返回prefer=1.即等于PREFER_INTERNAL,安装到内部存贮器。LOG如下:


● 给力开关的AndroidManifest.xml中没有设置installLocation标签,即prefer值等于-1,即是INSTALL_LOCATION_UNSPECIFIED ,进入 Pick user preference流程。此时根据SettingProvider中对DEFAULT_INSTALL_LOCATION的设置值进行处理。如将P660手机人为设置为PREFER_EXTERNAL,prefer==2此时安装失败返回PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGEPM,此时即使插入SD卡也不能完成安装,因为高通释放的Android4.4的代码逻辑是不允许将第三方应用安装到外置SD卡上的。

● 为验证高通Android4.4是否支持第三方应用安装到SD卡,特做如下实验:

1在recommendAppInstallLocation方法中做如下实验,因为在此之前PM做安装与处理的流程是一样的。以下截图中橙色标注的部分,目的是return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;

2Environment.isExternalStorageEmulated()在android4.4逻辑里永远返回true,改用Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())来判断真正的SD卡是否存在。

    

经过以上操作fitsOnS等于true,prefer==2,具体LOG分析如下:

接下来逻辑返回到PackageManagerService中,设置flages标志------>判断是否需要对各种安装参数做校验------->不需要的话直接执行IPC操作:copyApk。

  

copyApk操作所走到流程如下:最终系统调用creat(file, 0600)时失败,提示Error creating imagefile (Read-only file system)。

               









猜你喜欢

转载自blog.csdn.net/zhongfan520520/article/details/80938020