Calculation Method for storing and caching app information in Android

Source: Internet
Author: User

Perform the following operations:

Set-> application-> select an application-> application information

The following page is displayed:

The disk space occupied by the application is displayed.

First, let's talk about the results, which files (folders) will be calculated for these items ).

1. Application, Composed of three elements

/Data/com. myapp/lib, that is, the so library folder size/data/app/com.myapp-1.apk, copy the original apk file/data/dalvik-cache/data@app@com.myapp-1.apk @ classes. dex, dalvik VM cache dex files

2. USB storage (Application). The size after the program is installed (or moved to) the SD card. /Sdcard/Android/..., refer to "application.

3. Data=/Data/com. myapp/directory size-cache subdirectory size-lib subdirectory size

4. SD card=/Sdcard/Android/data/com. myapp/directory size-/sdcard/Android/data/com. myapp/cache directory size

(TotalIs the sum of the above four)

5. Cache=/Data/com. myapp/cache directory size +/sdcard/Android/data/com. myapp/cache directory size


The following describes how to do the Android4.2 source code. In more detail, the analysis process will be cumbersome. Let's teach it to fish.

Based on the application information interface Settings name, guess the source code

Android4.2/packages/apps/Settings/src/com/android/settings/applications/InstalledAppDetails. java

Responsible. The corresponding xml is

Android4.2/packages/apps/Settings/res/layout/installed_app_details.xml

The function used to refresh the disk size is

InstalledAppDetaileds. refreshSizeInfo ()

Reverse lookup Based on code clues

MDataSize. setText (getSizeStr (dataSize ));

->

Long dataSize = mAppEntry. dataSize;

->

MAppEntry = mState. getEntry (packageName );

->

MState. requestSize (mAppEntry.info. packageName );

ApplicationsState mState

->

Android4.2/packages/apps/Settings/src/com/android/settings/applications/ApplicationState. java

MPm. getPackageSizeInfo (packageName, mBackgroundHandler. mStatsObserver );

Final PackageManager mPm

->

Android4.2/frameworks/base/core/java/android/app/ApplicationPackageManager. java

Public void getPackageSizeInfo (String packageName, int userHandle,
IPackageStatsObserver observer ){

MPM. getPackageSizeInfo (packageName, userHandle, observer );

Private final IPackageManager mPM;

->

IPackageManager is an interface. It is implemented by searching for file content. According to java syntax, the keyword "extends IPackageManager" can be used"

You can use the shell command line to obtain the following results:

Liuhx @ uc ~ /Desktop/android4.2 $ grep-rnsw "extends IPackageManager "*
Frameworks/base/services/java/com/android/server/pm/PackageManagerService. java: 172: public class PackageManagerService extends IPackageManager. Stub {

->

Android4.2/frameworks/base/services/java/com/android/server/pm/PackageManagerService. java

Public void getPackageSizeInfo (

Message msg = mHandler. obtainMessage (INIT_COPY );
Msg. obj = new MeasureParams (stats, observer );
MHandler. sendMessage (msg );

->

Internal class MeasureParams

Void handleStartCopy () throws RemoteException {

MSuccess = getPackageSizeInfoLI (mStats. packageName, mStats. userHandle, mStats );

->

GetPackageSizeInfoLI Function

Int res = mInstaller. getSizeInfo (packageName, userHandle, p. mPath, publicSrcDir,
AsecPath, pStats );

Final Installer mInstaller

->

Frameworks/base/services/java/com/android/server/pm/Installer. java

Public int getSizeInfo (

String s = transaction (builder. toString ());

->

Private synchronized String transaction (String cmd ){

If (! WriteCommand (cmd )){

->

Private boolean writeCommand (String _ cmd)

MOut. write (buf, 0, 2 );
MOut. write (cmd, 0, len );

->

OutputStream mOut;

LocalSocketAddress address = new LocalSocketAddress ("installd ",
LocalSocketAddress. Namespace. RESERVED );
MSocket. connect (address );
MOut = mSocket. getOutputStream ();

It is speechless and uses socket to communicate.

->

Find the file content. The keyword is "installd". Note that it contains double quotation marks.

Expected result:

Liuhx @ uc ~ /Desktop/android4.2 $ grep-rnsw "\" installd \""*
Cts/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/rootprocess.pdf. java: 33: "installd ",
Frameworks/base/services/java/com/android/server/pm/Installer. java: 51: LocalSocketAddress address = new LocalSocketAddress ("installd ",
Frameworks/base/cmds/installd. h: 18: # define LOG_TAG "installd"
Frameworks/base/cmds/installd. h: 49: # define SOCKET_PATH "installd"
Sdk/files/ant/build. xml: 1355:
Sdk/files/ant/build. xml: 1392:

->

Frameworks/base/cmds/installd. h

Int get_size (const char * pkgname, int persona, const char * apkpath, const char * fwdlock_apkpath,
Const char * asecpath, int64_t * codesize, int64_t * datasize, int64_t * cachesize,
Int64_t * asecsize );

Or

Frameworks/base/cmds/installd. c

Static int do_get_size (char ** arg, char reply [REPLY_MAX])

Res = get_size (arg [0], atoi (arg [1]), arg [2], arg [3], arg [4],
& Codesize, & datasize, & cachesize, & asecsize );

->

The get_size function is not implemented in installd. c. You can search the file content according to the function declaration, but since it is a C language, it may be to implement function separation.

So in the installd. c directory, you can see the implementation in another code file. Reprinted please indicate the source: http://blog.csdn.net/hursing

->

Frameworks/base/cmds/installd/commands. c

Here is the source code for computing.

int get_size(const char *pkgname, int persona, const char *apkpath,             const char *fwdlock_apkpath, const char *asecpath,             int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,             int64_t* _asecsize){    DIR *d;    int dfd;    struct dirent *de;    struct stat s;    char path[PKG_PATH_MAX];    int64_t codesize = 0;    int64_t datasize = 0;    int64_t cachesize = 0;    int64_t asecsize = 0;        /* count the source apk as code -- but only if it's not         * on the /system partition and its not on the sdcard.         */    if (validate_system_app_path(apkpath) &&            strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {        if (stat(apkpath, &s) == 0) {            codesize += stat_size(&s);        }    }        /* count the forward locked apk as code if it is given         */    if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {        if (stat(fwdlock_apkpath, &s) == 0) {            codesize += stat_size(&s);        }    }        /* count the cached dexfile as code */    if (!create_cache_path(path, apkpath)) {        if (stat(path, &s) == 0) {            codesize += stat_size(&s);        }    }        /* add in size of any libraries */    if (!create_pkg_path_in_dir(path, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {        d = opendir(path);        if (d != NULL) {            dfd = dirfd(d);            codesize += calculate_dir_size(dfd);            closedir(d);        }    }        /* compute asec size if it is given         */    if (asecpath != NULL && asecpath[0] != '!') {        if (stat(asecpath, &s) == 0) {            asecsize += stat_size(&s);        }    }    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {        goto done;    }    d = opendir(path);    if (d == NULL) {        goto done;    }    dfd = dirfd(d);    /* most stuff in the pkgdir is data, except for the "cache"     * directory and below, which is cache, and the "lib" directory     * and below, which is code...     */    while ((de = readdir(d))) {        const char *name = de->d_name;        if (de->d_type == DT_DIR) {            int subfd;            int64_t statsize = 0;            int64_t dirsize = 0;                /* always skip "." and ".." */            if (name[0] == '.') {                if (name[1] == 0) continue;                if ((name[1] == '.') && (name[2] == 0)) continue;            }            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {                statsize = stat_size(&s);            }            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);            if (subfd >= 0) {                dirsize = calculate_dir_size(subfd);            }            if(!strcmp(name,"lib")) {                codesize += dirsize + statsize;            } else if(!strcmp(name,"cache")) {                cachesize += dirsize + statsize;            } else {                datasize += dirsize + statsize;            }        } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {            // This is the symbolic link to the application's library            // code.  We'll count this as code instead of data, since            // it is not something that the app creates.            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {                codesize += stat_size(&s);            }        } else {            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {                datasize += stat_size(&s);            }        }    }    closedir(d);done:    *_codesize = codesize;    *_datasize = datasize;    *_cachesize = cachesize;    *_asecsize = asecsize;    return 0;}
The above figure shows the usage of the internal disk, which is not consistent. There are also clues:

The internal class MeasureParams. handleStartCopy () function of PackageManagerService. java:

void handleStartCopy() throws RemoteException {            synchronized (mInstallLock) {                mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);            }            final boolean mounted;            if (Environment.isExternalStorageEmulated()) {                mounted = true;            } else {                final String status = Environment.getExternalStorageState();                mounted = (Environment.MEDIA_MOUNTED.equals(status)                        || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));            }            if (mounted) {                final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);                final File externalCacheDir = userEnv                        .getExternalStorageAppCacheDirectory(mStats.packageName);                final long externalCacheSize = mContainerService                        .calculateDirectorySize(externalCacheDir.getPath());                mStats.externalCacheSize = externalCacheSize;                final File externalDataDir = userEnv                        .getExternalStorageAppDataDirectory(mStats.packageName);                long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir                        .getPath());                if (externalCacheDir.getParentFile().equals(externalDataDir)) {                    externalDataSize -= externalCacheSize;                }                mStats.externalDataSize = externalDataSize;                final File externalMediaDir = userEnv                        .getExternalStorageAppMediaDirectory(mStats.packageName);                mStats.externalMediaSize = mContainerService                        .calculateDirectorySize(externalMediaDir.getPath());                final File externalObbDir = userEnv                        .getExternalStorageAppObbDirectory(mStats.packageName);                mStats.externalObbSize = mContainerService.calculateDirectorySize(externalObbDir                        .getPath());            }        }
The disk usage on the SD card is calculated here.


The linux stat function is used for internal disk computing.

Some directory and file constants are defined in installd. h.

Read the code carefully and you will get the results at the beginning of the article.

The size of the disk occupied by the code calculation result is obtained. However, because the memory has the concept of "4 K alignment", the size of the disk occupied is not equal to the file size. For example, a 2.98K file is displayed as 4 K in the application information.


Reprinted please indicate the source: http://blog.csdn.net/hursing

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.