1. Introduction
To install the application on the SD card and TF card, the android system does not support it by default. It has only one ASEC mount point:/mnt/secure/ASEC. In my system, this mount point is occupied by/mnt/sdcard, so the TF card is not supported. To solve this problem, there is no other way except to read and understand the code. To facilitate understanding of the following description, Let's first look at the vold (managing peripherals hot swapping) system framework:
For the related class diagram, refer to the diagram of other friends:
2. Procedures for installing applications from a USB flash drive
Packageinstalleractivity. Java: initiateinstall->
: Startinstallconfirm->
Installappprogress: oncreate->
Installappprogress: initview->
Packagemanager: installpackage->
Packagemanagerservice: installpackage->
Installpackagewithverification->
Mhandler. sendmessage (MSG)->
Packagehandler: handlemessage->
Packagehandler: dohandlemessage->
Handlerparams: startcopy->
Installparams: handlestartcopy-> (confirm the installation location based on installlocation. Only the lowthreshold is available for/Data partitions)
Sdinstallargs: copyapk-> (the key points are described below)
Installparams: handlereturncode->
Packagemanagerservice: processpendinginstall->
Packagemanagerservice: installpackageli-> // ARGs, Res Analysis
Packagemanagerservice: installnewpackageli-> // or replacepackageli
Packagemanagerservice: scanpackageli-> (key)-> parsepackage (parsing 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", ID, sizemb, fstype, key, owneruid );)
Nativedaemonconnector: docommandlocked-> (send a command to vold socket and wait for the result)
Nativedaemonconnector: sendcommandlocked-> (socket)
Frameworklistener: ondataavailable-> (receive message) "buffer = ASEC list"
Or "buffer = ASEC create smdl2tmp1 19 fat caf791d0108d682e5b2aafc5439d55a9 10023"
Frameworklistener: dispatchcommand->
Commandlistener: aseccmd: runcommand-> (all Code related to volume: sec_asecdir must be modified)
Volumemanager: createasec (determines the Installation File Path volume: sec_asecdir)
2.2 complex Mount relationships
For detailed code, see volume. cpp ::
The Code does not mount sdcard & udisk to ASEC by default. Therefore, you need to mount the SD card or TF card to the ASEC mount point. Of course, the system only has one/mnt/secure/ASEC by default, you can. create/mnt/secure/asecsd or/mnt/secure/asectf in RC and run mount.
•/Mnt/Secure: the mount point under is the mount point of the physical peripherals
•/Mnt/ASEC: A shared public mount point. It is a mount point of the tmpfs file system. Applications installed on SD or tF can be mounted to the mount point in this directory.
The complex Mount relationship is as follows:
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 (read-only 0-byte tmpfs, hide it, obscuring the ASEC image directory from non root users)
4) Move the subdirectory (. android_secure) under/mnt/secure/staging to/mnt/sdcard
Note:Ms_bind: Run BIND mounting to make the file or subdirectory tree visible on another point in the file system.
Only the root user can view files under/mnt/secure/ASEC. Of course, the TF card can be viewed on widows. under the android_secure directory. ASEC file.
2.3 install the APK on the SD card or TF card
When you install the APK on the SD card or TF card, you will leave it in the following places:
1)/mnt/secure/ASEC: (The. ASEC file generated after installation, which is the real content)
-Rwxrwxr-x system sdcard_rw 20257280 2013-04-07 06:14 com. myarrow. test-1.asec
2)/mnt/ASEC/COM. myarrow. Test-1: (it is mounted. It is a tmpfs and does not really occupy flash space)
Dr-XR-x system root 2013-04-07 06:14 lib
-R-XR-x system root 4973096 pkg.apk
3)/data/COM. myarrow. Test: (it is just a link and does not really occupy flash space)
Lrwxrwxrwx system 2013-04-09 06:51 Lib->/mnt/ASEC/COM. myarrow. Test-1/lib
4)/data/Dalvik-Cache: (contains the DEX file in the APK package, which occupies the flash space of the Data Partition, so the data partition must be reserved)
-RW-r -- System app_58 36608 mnt@asec@com.myarrow.test-1@pkg.apk @ classes. Dex
3. Main files to be modified
1) volume. cpp
Modify mountvol/unmountvol and run bindmount on the SD or TF card.
2) defaultcontainerservice. Java
Modify isunderexternalthreshold. When there is insufficient space, check whether there is sufficient space on the SD or TF card.
3) volumemanager. cpp
Extended the location related to volume: sec_asecdir, because we added a volume: sec_sd_asecdir
4. Mount and unmoun ASEC t Processes
1) Mount:
Mountservice. Java (policyvolumestatechange/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 (policyvolumestatechange/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
The detailed code is as follows:
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; }
Its main functions are as follows:
1) create a. ASEC File
2) Copy APK
3) Copy lib
4) Final. ASEC File
The detailed log information is as follows:
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