Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android系統應用信息中存儲和緩存的計算方法

Android系統應用信息中存儲和緩存的計算方法

編輯:關於Android編程

進行如下操作:

設置->應用->選擇一個應用->應用信息

會到達如下界面:

\

可以看到這個應用占用的磁盤空間。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+z8jLtb3hufujrNXivLjP7rvhvMbL48TE0KnOxLz+o6i80KOpoaM8L3A+CjxwPjxzdHJvbmc+MS7TptPDPC9zdHJvbmc+o6zTycj9z+7P4LzT1+mzyTwvcD4KPHA+PC9wPgoKL2RhdGEvZGF0YS9jb20ubXlhcHAvbGlio6y8tHNvv+LOxLz+vNC089ChL2RhdGEvYXBwL2NvbS5teWFwcC0xLmFwa6Os1K3KvGFwa87EvP61xLi01sYvZGF0YS9kYWx2aWstY2FjaGUvZGF0YUBhcHBAY29tLm15YXBwLTEuYXBrQGNsYXNzZXMuZGV4o6xkYWx2aWvQ6cTiu/q21GRleM7EvP61xLu6tOYKPHA+PC9wPgo8cD48c3Ryb25nPjIuVVNCtOa0oqOo06bTw6OpPC9zdHJvbmc+oaOw0bPM0PLXsLW9o6i78tLGtb2jqXNkv6i687XEtPPQoaGjL3NkY2FyZC9BbmRyb2lkLy4uLqOsss6/vKGw06bTw6Gxz+6hozwvcD4KPHA+PHN0cm9uZz4zLsr9vt08L3N0cm9uZz4gPSAvZGF0YS9kYXRhL2NvbS5teWFwcC/Ev8K8tPPQoSAtIGNhY2hl19PEv8K8tPPQoSAtIGxpYtfTxL/CvLTz0KE8L3A+CjxwPjxzdHJvbmc+NC5TRCC/qDwvc3Ryb25nPiA9IC9zZGNhcmQvQW5kcm9pZC9kYXRhL2NvbS5teWFwcC/Ev8K8tPPQoSAtIC9zZGNhcmQvQW5kcm9pZC9kYXRhL2NvbS5teWFwcC9jYWNoZcS/wry089ChPC9wPgo8cD6jqDxzdHJvbmc+19y8xjwvc3Ryb25nPsrH0tTJzzS49tauus2jqTwvcD4KPHA+PHN0cm9uZz41Lru6tOY8L3N0cm9uZz4gPSAvZGF0YS9kYXRhL2NvbS5teWFwcC9jYWNoZcS/wry089ChICYjNDM7IC9zZGNhcmQvQW5kcm9pZC9kYXRhL2NvbS5teWFwcC9jYWNoZcS/wry089ChPC9wPgo8cD48YnI+CjwvcD4KPHA+z8LD5srHt9bO9kFuZHJvaWQ0LjLUtMLr1PXDtNf2tcSho7HIvc/P6s+4y7W31s72uf2zzKOsu+HA29e40KmjrMra1q7S1NPmsMmhozwvcD4KPHA+uPm+3dOm08PQxc+itcS958PmU2V0dGluZ3PV4rj2w/vX1qOsssKy4rW91LTC6zwvcD4KPHA+YW5kcm9pZDQuMi9wYWNrYWdlcy9hcHBzL1NldHRpbmdzL3NyYy9jb20vYW5kcm9pZC9zZXR0aW5ncy9hcHBsaWNhdGlvbnMvSW5zdGFsbGVkQXBwRGV0YWlscy5qYXZhPC9wPgo8cD64utTwo6y21NOmtcR4bWzKxzwvcD4KPHA+YW5kcm9pZDQuMi9wYWNrYWdlcy9hcHBzL1NldHRpbmdzL3Jlcy9sYXlvdXQvaW5zdGFsbGVkX2FwcF9kZXRhaWxzLnhtbDxicj4KPC9wPgo8cD7LotDCtMXFzNW808O089ChtcS6r8r9ysc8L3A+CjxwPkluc3RhbGxlZEFwcERldGFpbGVkcy5yZWZyZXNoU2l6ZUluZm8oKTwvcD4KPHA+uPm+3bT6wuvP38v3t7Sy6TwvcD4KPHA+bURhdGFTaXplLnNldFRleHQoZ2V0U2l6ZVN0cihkYXRhU2l6ZSkpOzwvcD4KPHA+LT48L3A+CjxwPmxvbmcgZGF0YVNpemUgPSBtQXBwRW50cnkuZGF0YVNpemU7PGJyPgo8L3A+CjxwPi0+PC9wPgo8cD5tQXBwRW50cnkgPSBtU3RhdGUuZ2V0RW50cnkocGFja2FnZU5hbWUpOzxicj4KPC9wPgo8cD4tPjwvcD4KPHA+bVN0YXRlLnJlcXVlc3RTaXplKG1BcHBFbnRyeS5pbmZvLnBhY2thZ2VOYW1lKTs8YnI+CjwvcD4KPHA+QXBwbGljYXRpb25zU3RhdGUgbVN0YXRlPGJyPgo8L3A+CjxwPi0+PC9wPgo8cD5hbmRyb2lkNC4yL3BhY2thZ2VzL2FwcHMvU2V0dGluZ3Mvc3JjL2NvbS9hbmRyb2lkL3NldHRpbmdzL2FwcGxpY2F0aW9ucy9BcHBsaWNhdGlvblN0YXRlLmphdmE8YnI+CjwvcD4KPHA+bVBtLmdldFBhY2thZ2VTaXplSW5mbyhwYWNrYWdlTmFtZSwgbUJhY2tncm91bmRIYW5kbGVyLm1TdGF0c09ic2VydmVyKTs8YnI+CjwvcD4KPHA+ZmluYWwgUGFja2FnZU1hbmFnZXIgbVBtPGJyPgo8L3A+CjxwPi0+PC9wPgo8cD5hbmRyb2lkNC4yL2ZyYW1ld29ya3MvYmFzZS9jb3JlL2phdmEvYW5kcm9pZC9hcHAvQXBwbGljYXRpb25QYWNrYWdlTWFuYWdlci5qYXZhPGJyPgo8L3A+CjxwPnB1YmxpYyB2b2lkIGdldFBhY2thZ2VTaXplSW5mbyhTdHJpbmcgcGFja2FnZU5hbWUsIGludCB1c2VySGFuZGxlLDxicj4KICAgICAgICAgICAgSVBhY2thZ2VTdGF0c09ic2VydmVyIG9ic2VydmVyKSB7PGJyPgo8L3A+CjxwPm1QTS5nZXRQYWNrYWdlU2l6ZUluZm8ocGFja2FnZU5hbWUsIHVzZXJIYW5kbGUsIG9ic2VydmVyKTs8YnI+CjwvcD4KPHA+cHJpdmF0ZSBmaW5hbCBJUGFja2FnZU1hbmFnZXIgbVBNOzxicj4KPC9wPgo8cD4tPjwvcD4KPHA+SVBhY2thZ2VNYW5hZ2Vyyse49r3Tv9qjrNPDsunV0s7EvP7E2sjdtcS3vcq9y9HL98v8tcTKtc/Wo6y4+b7damF2YdPvt6ijrL/J08O52Lz819ahsGV4dGVuZHMgSVBhY2thZ2VNYW5hZ2VyobE8YnI+CjwvcD4KPHA+08NzaGVsbMP8we7Q0L/JtcO1vdXi0fm1xL3hufujujwvcD4KPHA+bGl1aHhAdWMgfi9EZXNrdG9wL2FuZHJvaWQ0LjIgJCBncmVwIC1ybnN3IA=="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);

->

內部類class MeasureParams

void handleStartCopy() throws RemoteException {

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

->

getPackageSizeInfoLI函數

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();

到此很無語,用socket的方式來通信。

->

查找文件內容,關鍵字為 "installd", 注意包含雙引號

得到結果:

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

->

frameworks/base/cmds/installd/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);

frameworks/base/cmds/installd/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);

->

看到在installd.c沒有實現get_size函數。可以根據函數聲明搜索文件內容,不過既然是c語言,那可能是把函數分離實現。

所以在installd.c的目錄下,看到另一個代碼文件裡實現了。轉載請注明出處:http://blog.csdn.net/hursing

->

frameworks/base/cmds/installd/commands.c

這裡就是計算的源碼了。

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;
}
以上是計算了內部磁盤的占用,還不齊,還有線索:

PackageManagerService.java的內部類MeasureParams.handleStartCopy()函數:

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());
            }
        }
這裡計算了sd卡上的磁盤占用。


內部磁盤的計算,是用linux的stat函數。

一些目錄和文件的常量,定義在installd.h

認真看代碼,則會得到文章開頭的結果。

代碼計算的結果得到的是占用磁盤的大小,但由於存儲器有"4K對齊”的概念,所以占用磁盤大小不等於文件大小。例如一個實際為2.98K的文件,會在應用信息裡顯示為4K。


轉載請注明出處:http://blog.csdn.net/hursing

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved