首先给大家分享一个巨牛巨牛的人工智能教程,是我无意中发现的。教程不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵段子,像看小说一样,哈哈~我正在学习中,觉得太牛了,所以分享给大家!点这里可以跳转到教程

1. 简介

为了能把应用程序安装到SD卡和TF卡上,Android系统默认是不支持的,它只有一个asec mount点: /mnt/secure/asec,在我的系统中,此mount点由/mnt/sdcard给占用了,所以TF卡就支持不了。为了解决此问题,除了把代码读明白之外,无其它的办法。为了方便理解下面的描述,先看下Vold(管理外设热插拔)的系统框架图:

关于相关类图,引用其他仁兄的图:

2. 从U盘安装应用程序流程

PackageInstallerActivity.java::initiateInstall->
                             ::startInstallConfirm->
                   
InstallAppProgress::onCreate->
InstallAppProgress::initView->

PackageManager::installPackage->

PackageManagerService::installPackage->
 installPackageWithVerification->
       mHandler.sendMessage(msg)->

PackageHandler::handleMessage->
  PackageHandler::doHandleMessage->
  HandlerParams::startCopy->
     InstallParams::handleStartCopy-> (根据installLocation确认安装位置,只有针对/data分区有lowThreshold)
       SdInstallArgs::copyApk-> (关键的地方,下面详解)
     InstallParams::handleReturnCode->
       PackageManagerService::processPendingInstall->
         PackageManagerService::installPackageLI-> //args, res分析
           PackageManagerService::installNewPackageLI->  // or replacePackageLI
             PackageManagerService::scanPackageLI-> (KEY)->parsePackage(解析AndroidManifest.xml)
               Installer::install (mInstaller.install)-> (Socket)--->
               installd(真正做事的地方)

2.1 SdInstallArgs::copyApk

SdInstallArgs::copyApk->
DefaultContainerService::copyResourceInner->
PackageHelper::createSdDir->
MountService::createSecureContainer->

(cmd = String.format(new Locale("en", "Us"),

"asec create %s %d %s %s %d", id, sizeMb, fstype, key, ownerUid);)
NativeDaemonConnector::doCommandLocked->(向"vold" socket发送命令给vold,并等待结果)
NativeDaemonConnector::sendCommandLocked-> (Socket)

FrameworkListener::onDataAvailable-> (receive message)  "buffer=asec list"
                                  或"buffer=asec create smdl2tmp1 19 fat caf791d0426d682e5b2aafc5439d55a9 10023"
FrameworkListener::dispatchCommand->
CommandListener::AsecCmd::runCommand-> (所有与Volume::SEC_ASECDIR相关的代码都需要修改)
VolumeManager::createAsec (决定安装文件的路径Volume::SEC_ASECDIR)

2.2 复杂的mount关系

详细代码参见Volume.cpp::

代码默认不把sdcard && udisk mount为asec,为此需要把SD卡或TF卡mount到asec挂载点,当然系统默认只有一个/mnt/secure/asec,你可以在init.rc中创建一个/mnt/secure/asecsd或/mnt/secure/asectf,并执行mount即可。

• /mnt/secure: 下的mount点为物理外设的mount点

•/mnt/asec: 为公共挂载点,它是一个tmpfs文件系统的挂载点,安装到SD或TF上的应用程序都可以被mount到此目录下的mount点

复杂的mount关系如下所示:

1) /dev/block/vold/31:9    mount to /mnt/secure/staging
   2) /mnt/secure/staging/.android_secure mount to /mnt/secure/asec (MS_BIND)
   3) tmpfs  mount to /mnt/secure/staging/.android_secure (只读0字节tmpfs,把它隐藏起来, obscuring the asec image directory from non root users)
   4) 把/mnt/secure/staging下的子目录(.android_secure)移动到/mnt/sdcard下

   注:MS_BIND: 执行bind挂载,使文件或者子目录树在文件系统内的另一个点上可视。

搞这么复杂的目的只有一个:只有root用户才能查看/mnt/secure/asec下的文件,当然把TF卡取出来,在Widows上可以看到.android_secure目录下的.asec文件。

2.3 把APK安装到SD卡或TF卡上留下的东东

当把APK安装到SD卡或TF卡上时,将在以下地方留下它的东东:

1) /mnt/secure/asec: (安装之后产生的.asec文件,它才是真正的内容)
   -rwxrwxr-x system   sdcard_rw 20257280 2013-04-07 06:14 com.myarrow.test-1.asec

2) /mnt/asec/com.myarrow.test-1: (是被mount上去的,它是一个tmpfs,并不真正占用flash空间)
   dr-xr-xr-x system   root              2013-04-07 06:14 lib
   -r-xr-xr-x system   root      4973096 2013-04-07 06:14 pkg.apk

3) /data/data/com.myarrow.test: (只是一个链接,不真正占用flash空间)
   lrwxrwxrwx system   system            2013-04-09 06:51 lib -> /mnt/asec/com.myarrow.test-1/lib

4) /data/dalvik-cache: (包含apk包中的dex文件,它占用data分区的flash空间, 所以data分区必须预留空间)
   -rw-r--r-- system   app_58      36608 2013-04-07 06:14 mnt@asec@com.myarrow.test-1@pkg.apk@classes.dex

3. 需要修改的主要文件

1) Volume.cpp

修改其中的mountVol/unmountVol,把SD或TF卡也执行bindmount

2) DefaultContainerService.java

修改isUnderExternalThreshold,当空间不足时,看看SD或TF卡上是否有足够的空间

3) VolumeManager.cpp

扩展与Volume::SEC_ASECDIR相关的地方,因为我们增加了一个Volume::SEC_SD_ASECDIR

4. Mount和Unmoun asec t流程

1) Mount:

MountService.java (notifyVolumeStateChange/onEvent)->
MountService.jvav (updatePublicVolumeState) ->
PackageManagerService.java (updateExternalMediaStatus) ->
                          (updateExternalMediaStatusInner) ->
                           (loadMediaPackages) ->
                           SdInstallArgs.doPreInstall->
PackageHelper.java (mountSdDir) ->
MountService.java(mountSecureContainer)->
CommandListener.cpp(CommandListener::AsecCmd::runCommand)

2) Unmount:
MountService.java (notifyVolumeStateChange/onEvent)->
MountService.jvav (updatePublicVolumeState) ->
PackageManagerService.java (updateExternalMediaStatus) ->
                          (updateExternalMediaStatusInner) ->
                           (unloadMediaPackages) ->(send UPDATED_MEDIA_STATUS)
                           PackageHandler.doHandleMessage (get UPDATED_MEDIA_STATUS)->
                           unloadAllContainers ->
                           (SdInstallArgs.doPostDeleteLI)->

PackageHelper.java (unMountSdDir) ->
MountService.java (unmountSecureContainer)->
CommandListener.cpp(CommandListener::AsecCmd::runCommand)

5.  copyResourceInner

其详细代码如下所示:

    private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName) {        // Make sure the sdcard is mounted.        String status = Environment.getExternalStorageState();        if (!status.equals(Environment.MEDIA_MOUNTED)) {            Slog.w(TAG, "Make sure sdcard is mounted.");            return null;        }        // The .apk file        String codePath = packageURI.getPath();        File codeFile = new File(codePath);        // Calculate size of container needed to hold base APK.        int sizeMb;        try {            sizeMb = calculateContainerSize(codeFile);        } catch (FileNotFoundException e) {            Slog.w(TAG, "File does not exist when trying to copy " + codeFile.getPath());            return null;        }        // Create new container        final String newCachePath;        if ((newCachePath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid())) == null) {            Slog.e(TAG, "Failed to create container " + newCid);            return null;        }        /*if (localLOGV)*/ {            Slog.i(TAG, "Created container for " + newCid + " at path : " + newCachePath);        }        final File resFile = new File(newCachePath, resFileName);        if (FileUtils.copyFile(new File(codePath), resFile)) {            /*if (localLOGV)*/ {                Slog.i(TAG, "Copied " + codePath + " to " + resFile);            }        } else {            Slog.e(TAG, "Failed to copy " + codePath + " to " + resFile);            // Clean up container            PackageHelper.destroySdDir(newCid);            return null;        }        final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);        if (sharedLibraryDir.mkdir()) {            int ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(codeFile, sharedLibraryDir);            if (ret != PackageManager.INSTALL_SUCCEEDED) {                Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath());                PackageHelper.destroySdDir(newCid);                return null;            }        } else {            Slog.e(TAG, "Could not create native lib directory: " + sharedLibraryDir.getPath());            PackageHelper.destroySdDir(newCid);            return null;        }        if (!PackageHelper.finalizeSdDir(newCid)) {            Slog.e(TAG, "Failed to finalize " + newCid + " at path " + newCachePath);            // Clean up container            PackageHelper.destroySdDir(newCid);            return null;        }        if (localLOGV) {            Slog.i(TAG, "Finalized container " + newCid);        }        if (PackageHelper.isContainerMounted(newCid)) {            if (localLOGV) {                Slog.i(TAG, "Unmounting " + newCid + " at path " + newCachePath);            }            // Force a gc to avoid being killed.            Runtime.getRuntime().gc();            PackageHelper.unMountSdDir(newCid);        } else {            if (localLOGV) {                Slog.i(TAG, "Container " + newCid + " not mounted");            }        }        return newCachePath;    }

其主要功能为:

1)创建.asec文件

2)copy apk

3)copy lib

4)final .asec文件

其详细log信息如下:

D/VoldVolumeManager(   85):  createAsec(367) call createImageFile   E/Vold    (   85): createImageFile(236) call creat                  E/Vold    (   85): createImageFile(241) call ftruncate              E/Vold    (   85): createImageFile(247) END                         D/VoldVolumeManager(   85): createAsec(374) call asecHash           D/VoldVolumeManager(   85): createAsec(383) call Loop::create       D/VoldVolumeManager(   85): createAsec(397) call Devmapper::create  D/VoldVolumeManager(   85): createAsec(414) call open               D/VoldVolumeManager(   85): createAsec(436) write sb                D/VoldVolumeManager(   85): createAsec(453) Fat::format             D/VoldVolumeManager(   85): createAsec(477) Fat::doMount            D/VoldVolumeManager(   85): createAsec(491) End                                                                                         ****copy apk and lib*****                                                                                                               D/VoldVolumeManager(   85): finalizeAsec(502) start                 D/VoldVolumeManager(   85): finalizeAsec(520) End                   D/VoldVolumeManager(   85): renameAsec:538 Volume::SEC_ASECDIR startD/VoldVolumeManager(   85): renameAsec:538 Volume::SEC_ASECDIR start

浏览人工智能教程

把APK安装到SD卡和TF卡实现方案相关推荐

  1. 硬盘、移动硬盘、内存卡(SD卡、TF卡)、U盘修复,格式化

    文章目录: 1 问题描述 2 硬盘.移动硬盘.内存卡(SD卡.TF卡).U盘修复工具 3 扇区的介绍 1 问题描述 我的是SD卡(就是TF卡)出现了问题,然后在windows系统PC上可以读出来,但是 ...

  2. SD卡、TF卡、SIM卡的区别

    SD卡(Secure Digital Memory Card)是一种基于半导体快闪记忆器的新一代记忆设备.SD卡由日本松下.东芝及美国SanDisk公司于1999年8月共同开发研制.大小犹如一张邮票的 ...

  3. ICMAX八大方法教你快速分清什么是SD卡与TF卡

    很多人搞不清几种内存卡的区别,因为内存卡有好几种,这里说一下sd卡和TF卡的区别,sd卡一般是相机使用的大的内存卡,TF就是手机使用的小的内存卡, 不管是SD卡还是TF卡如果坏了都可以试着用内存卡修复 ...

  4. pcie16x能插1x的卡嘛?_这7个修复工具分享给你:不仅能修复U盘,SD卡、TF卡也能修复!...

    今天小编就一口气把7个修复工具分享给大家,这些修复工具不仅能修复U盘,而且还能修复SD卡和TF卡哦~下面就来看看是哪几个神器吧!(文末提供下载) 在正式操作之前有几点需要提醒一下: 1.修复的过程中不 ...

  5. pcie16x能插1x的卡嘛?_小白把这7个修复工具分享给你:不仅能修复U盘,SD卡、TF卡也能修复!...

    此前分享给大家的U盘量产工具帮助了许多朋友修复了本来不能使用的U盘,但是仍然有不少朋友反映"主控型号无法检测""没有对应的量产工具可以下载""量产后仍 ...

  6. SD NAND 为什么可以完胜T卡(tf卡/sd卡)?

           现在科技发展中,各种电子设备很普及,随处可见,使用率高的情况下,难免会出现一些问题.比如说很多人突然遇到一些设备识别不到T卡(tf卡/sd卡)了?再不然就是T卡突然间崩溃?再比如有的设备 ...

  7. SD卡和TF卡的区别

    源于百度经验 最近看到有些网友经常询问SD卡和TF卡的区别,所以作家俺根据亲身经验给大家说说这个. SD卡和TF卡的区别 1外观区分: SD卡体积为24mm×32mm×2.1mm: TF卡体积为15m ...

  8. CS品牌SD NAND VS TF卡 SD NAND和TF卡的区别

    最近工程师群里都会出现一个CS品牌的SD NAND的存储芯片,那么很多人的疑问什么是SD NAND?今天就带大家详细的了解一下.SD NAND俗称贴片式T卡,贴片式TF卡,贴片式SD卡,贴片式内存卡, ...

  9. 优盘Flash, SD卡, TF 卡 ,CF卡一体黑胶存储颗粒数据恢复专用必备工具合

    优盘Flash, SD卡, TF 卡 ,CF卡一体黑胶存储颗粒数据恢复专用必备工具合集 对于数据的丢失是大家最不想看到的,毕竟 数据无价的道理都懂,但是意外总是没有预兆,目前市场上流通的便携式存储无外 ...

最新文章

  1. 牛客小白月赛5-F题: 圆(circle)
  2. 学习如何写 Bug 的一天! | 每日趣闻
  3. win这个傻逼系统,高PPI上默认的情况下是放大的,放大了之后逻辑分辨率不跟着放大。
  4. 中国通货膨胀率2.8%,数据分析买房风险直线上升
  5. 使用pip安装python库的几种方式,解决pip安装python库慢的问题
  6. fpga如何约束走线_FPGA设计约束技巧之XDC约束之I/O篇 (上)
  7. 世界首富比尔盖茨花钱全过程!
  8. git clone大文件EOF错误
  9. 五大步骤快速搭建个人网站
  10. kafkatemplate无法注入_SpringBoot 整合 Spring-Kafka 深度踩坑实战
  11. 基于STM32F103自制CMSIS-DAP下载器
  12. Cisco ASA 5505 (Version 9.X)的 LAN上网和NAT的配置
  13. Google完整安装包下载
  14. pp助手苹果版_iOS 版 PP 助手下线,再见了
  15. 一篇文章带你入门python基础开发
  16. 服务认证的介绍-实施依据及作用
  17. 商业仲裁与诉讼律师Katherine Cheung加入德汇香港担任合伙人
  18. java 获取年和季度_java获取当前时间的年周月季度等的开始结束时间
  19. sif4j 字符串拼接和占位符的区别
  20. V 社秘密开发 Steam 跨系统兼容工具;甲骨文开源 GraphPipe,机器学习模型标准

热门文章

  1. ORA-03135 connections lost contact Process ID:0
  2. 【Java常用工具类汇总 2,零基础如何成为高级Java开发
  3. 如何用Arduino IDE开发9.9元的合宙LuatOS ESP32C3开发板?
  4. 常用连接嵌入式设备的工具方法
  5. HTML5CSS3特效-上下跳动的小球-遁地龙卷风
  6. 机器学习算法之监督学习与非监督学习
  7. Apache httpd.conf详解
  8. 解读乔新亮的《看透本质:研发出了生产事故,到底要不要罚钱?》
  9. 抖音养号教程技巧,做抖音怎么养号上热门!
  10. 怎么学Python能够高薪就业 需要掌握哪些技术