平板实现app2sd功能

来源:互联网 发布:mac谷歌浏览器 编辑:程序博客网 时间:2024/04/29 13:43

平台:android4.0
场景:平板上都默认不插入SD卡,所以会将mnt/sdcard指向flash上分出来的某个块,即使默认的app2sd功能存在,也是一个假象。
时间:2012.5.25

android在2.2后开始支持,专门在vold里面添加了const char *Volume::SEC_STGDIR = “/mnt/secure/staging”。
单独讨论手机的情况,手机的SD卡对应的就是mnt/sdcard.因此在sd卡进行挂载的时候,首先会把sd设备挂载到/mnt/secure/staging下,然后将sd设备上的android_secure文件改成.android_secure文件,同时映射到/mnt/secure/asec下。挂载的最后,将sd卡挂载到mnt/sdcard上,同时移除/mnt/secure/staging,即umount掉。
此时/mnt/secure/asec依然映射到sd卡设备的.android_secure文件。
当进行app2sd操作的时候,会将app移动到.android_secure文件中,同时将.android_secure文件中的apk文件改名为xxxx.asec,并映射到mnt/asec下。(此时.android_secure文件中的apk名字并未变化,mnt/asec下只是改了名字的一个映射,此路径被uri使用)。
上述实现的关键函数是createBindMounts()函数。同时关于asec的操作定义在VolumeManager.cpp中。
其提供给CommandListener::AsecCmd::runCommand()使用。此处为socket调用,client端位于框架的MountService,使得上层可以根据情况进行调用。

关于平板,基本上将flash(即真实flash的一个block区域)挂载到了mnt/sdcard路径,从而上述的相关操作,都在flash上面进行了。因此在平板上的app2sd其实是一个假象。而关于还原其真实情况,需要做的事情比较简单:在vold进行mountVol()的时候,我们可以根据不同的设备(flash,真实sdcard)的label进行区分处理。当是真实的sdcard的时候,我们才使用mnt/secure/staging的相关操作,而关于flash的挂载,我们仅仅直接mount,即使用Fat::doMount(devicePath, getMountpoint()。这样,app2sd功能在平板上就是真实实现了,同时仅仅在平板插入sdcard的时候起作用。当然,还需要记得清理asce相关的操作上进行一次判断。

解决方法:
1、把staging的创建和move的代码都移到sdcard那个if分支里
2、修改清理asec为在sdcard卸载的时候
关于app2sd的框架中的流程,大致如下:
PKMS::movePackage()====>PKMS::copyAPK()====>DefaultContainerService::copyResourceInner()====>FileUtils::copyFile()
在copyResourceInner()中调用FileUtils::copyFile()的关键,是path参数,即newCachePath。而newCachePath的获取,来自于:
PackageHelper::createSdDir()====>MountService::getSecureContainerPath()====>CommandListener::AsecCmd::runCommand()。
看吧,绕回到AsecCmd中了,从而各种调用VolumeManager.cpp中定义的asec相关的函数。

修改后存在的问题:
当一个apk在其AndroidManifest.xml中申明的安装位置为External时,此apk将无法安装。提示报错:INSTALL_FAILED_CONTAINER_ERROR。
报错原因,在安装的过程中获取到的推荐安装位置为External,而此时框架中Environment.java中的External的定义依然是路径“mnt/sdcard”—即为小机器上的falsh。而安装在外部的apk是需要放入到.android_secure文件中的!
因为我们已经把真实的app2sd实现了,此文件已经被建立到真实的SD卡上去了,因此在安装的过程中执行copyAPK()的时候,URI中包含的.android_secure路径在flash上是找不到的。
关键点:我们已经将真实app2sd实现,即.android_secure在真实的SD卡上,而此apk本身是推荐自己安装在外部—在框架中依然还是指向mnt/sdcard对应的flash!
推荐安装到外部,此时的外部应该对应的是sdcard,在没有插入SD卡的情况下,不是应该不推荐外部安装么!?其实系统本身就是这么实现的,而关键点就是系统在判断SD卡的挂载情况时,依然判断的是mnt/sdcard这个flash对应的路径的挂载情况!
—其实这里应该判断SD卡对应的mnt/sdcard2的挂载情况!(按照系统的处理,若SD卡没有挂载,则将推荐到内部安装,此时情况就正常了)
—-在DefaultContainerService.java中修改isUnderExternalThreshold()函数中的if判断,此处应该是判断真实的SD卡是否挂载上!

0 0