淘先锋技术网

首页 1 2 3 4 5 6 7

平台

RK3288 + Android 7.1

问题描述

设置中的存储信息显示与实际EMMC的大小相差太大. 如下图所示(16GB):
在这里插入图片描述
实际的显示效果应该是:
在这里插入图片描述

分析

在RK3368 Android7.1上, 显示的正是预期效果, 开始比对设置部分代码:
packages/apps/Settings/src/com/android/settings/deviceinfo/StorageSettings.java

    private void refresh() {
        final Context context = getPrefContext();

        getPreferenceScreen().removeAll();
        mInternalCategory.removeAll();
        mExternalCategory.removeAll();

        mInternalCategory.addPreference(mInternalSummary);

        int privateCount = 0;
        long privateUsedBytes = 0;
        long privateTotalBytes = 0;

        final List<VolumeInfo> volumes = mStorageManager.getVolumes();
        Collections.sort(volumes, VolumeInfo.getDescriptionComparator());
		//重点解读下面的代码, 结果发现, 代码3368与3288看不出区别.
        for (VolumeInfo vol : volumes) {//遍历所有的存储
            android.util.Log.d("StorageSettings", "ALog vol(" + vol.getPath() + ")");
            if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
                final long volumeTotalBytes = PrivateStorageInfo.getTotalSize(vol,
                        sTotalInternalStorage);
                final int color = COLOR_PRIVATE[privateCount++ % COLOR_PRIVATE.length];
                mInternalCategory.addPreference(
                        new StorageVolumePreference(context, vol, color, volumeTotalBytes));
                if (vol.isMountedReadable()) {
                    final File path = vol.getPath();
                    privateUsedBytes += (volumeTotalBytes - path.getFreeSpace());
                    privateTotalBytes += volumeTotalBytes;
                    //统计大小并显示.
                }
            } else if (vol.getType() == VolumeInfo.TYPE_PUBLIC) {
                mExternalCategory.addPreference(
                        new StorageVolumePreference(context, vol, COLOR_PUBLIC, 0));
            }
        }

        // Show missing private volumes
        final List<VolumeRecord> recs = mStorageManager.getVolumeRecords();
        for (VolumeRecord rec : recs) {
            if (rec.getType() == VolumeInfo.TYPE_PRIVATE
                    && mStorageManager.findVolumeByUuid(rec.getFsUuid()) == null) {
                // TODO: add actual storage type to record
                final Drawable icon = context.getDrawable(R.drawable.ic_sim_sd);
                icon.mutate();
                icon.setTint(COLOR_PUBLIC);

                final Preference pref = new Preference(context);
                pref.setKey(rec.getFsUuid());
                pref.setTitle(rec.getNickname());
                pref.setSummary(com.android.internal.R.string.ext_media_status_missing);
                pref.setIcon(icon);
                mInternalCategory.addPreference(pref);
            }
        }

        // Show unsupported disks to give a chance to init
        final List<DiskInfo> disks = mStorageManager.getDisks();
        for (DiskInfo disk : disks) {
            if (disk.volumeCount == 0 && disk.size > 0) {
                final Preference pref = new Preference(context);
                pref.setKey(disk.getId());
                pref.setTitle(disk.getDescription());
                pref.setSummary(com.android.internal.R.string.ext_media_status_unsupported);
                pref.setIcon(R.drawable.ic_sim_sd);
                mExternalCategory.addPreference(pref);
            }
        }

        final BytesResult result = Formatter.formatBytes(getResources(), privateUsedBytes, 0);
        mInternalSummary.setTitle(TextUtils.expandTemplate(getText(R.string.storage_size_large),
                result.value, result.units));
        mInternalSummary.setSummary(getString(R.string.storage_volume_used_total,
                Formatter.formatFileSize(context, privateTotalBytes)));
        if (mInternalCategory.getPreferenceCount() > 0) {
            getPreferenceScreen().addPreference(mInternalCategory);
        }
        if (mExternalCategory.getPreferenceCount() > 0) {
            getPreferenceScreen().addPreference(mExternalCategory);
        }

        if (mInternalCategory.getPreferenceCount() == 2
                && mExternalCategory.getPreferenceCount() == 0) {
            // Only showing primary internal storage, so just shortcut
            final Bundle args = new Bundle();
            args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
            PrivateVolumeSettings.setVolumeSize(args, sTotalInternalStorage);
            Intent intent = Utils.onBuildStartFragmentIntent(getActivity(),
                    PrivateVolumeSettings.class.getName(), args, null, R.string.apps_storage, null,
                    false);
            intent.putExtra(SettingsDrawerActivity.EXTRA_SHOW_MENU, true);
            getActivity().startActivity(intent);
            finish();
        }
    }

获取系统存储信息:

代码没有任何问题, 在LOG中输出privateTotalBytes的最终结果上看正是UI中显示的大小信息.

大小计算:

final long volumeTotalBytes = PrivateStorageInfo.getTotalSize(vol,
                        sTotalInternalStorage);

//frameworks/base/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
    /**
     * Returns the total size in bytes for a given volume info.
     * @param info Info of the volume to check.
     * @param totalInternalStorage Total number of bytes in the internal storage to use if the
     *                             volume is the internal disk.
     */
    public static long getTotalSize(VolumeInfo info, long totalInternalStorage) {
        // Device could have more than one primary storage, which could be located in the
        // internal flash (UUID_PRIVATE_INTERNAL) or in an external disk.
        // If it's internal, try to get its total size from StorageManager first
        // (totalInternalStorage), because that size is more precise because it accounts for
        // the system partition.
        if (info.getType() == VolumeInfo.TYPE_PRIVATE
                && Objects.equals(info.getFsUuid(), StorageManager.UUID_PRIVATE_INTERNAL)
                && totalInternalStorage > 0) {
            return totalInternalStorage;
        } else {
            final File path = info.getPath();
            if (path == null) {
                // Should not happen, caller should have checked.
                Log.e(TAG, "info's path is null on getTotalSize(): " + info);
                return 0;
            }
            return path.getTotalSpace();
        }
    }
}
                        

由于 File.getTotalSpace() 所得出的大小始终不对, 于是, 从上面的函数入口, 着手查privateTotalBytes的值
当然, 从上面的代码和注释已可基本推断: privateTotalBytes 应该是要找的正确的值.


        if (sTotalInternalStorage <= 0) {
            sTotalInternalStorage = mStorageManager.getPrimaryStorageSize();
        }

frameworks/base/core/java/android/os/storage/StorageManager.java

    // TODO: the location of the primary storage block varies from device to device, so we need to
    // try the most likely candidates - a long-term solution would be a device-specific vold
    // function that returns the calculated size.
    private static final String[] INTERNAL_STORAGE_SIZE_PATHS = {
            //"/sys/block/mmcblk0/size",
            //"/sys/block/sda/size"
    };
    private static final String[] INTERNAL_STORAGE_SIZE_PATHS_ALTERNATIVE = {
            "/sys/block/mmcblk1/size",
            "/sys/block/sda/size",
	    "/sys/block/rknand_userdata/size"
    };

	//从这里我感觉, 3288被鄙视了
    private static boolean alternative_path=platform.equals("rk3368")||platform.equals("rk3399");

    /** {@hide} */
    public long getPrimaryStorageSize() {
        if(alternative_path){//RK3368 和 RK3399
            for (String path : INTERNAL_STORAGE_SIZE_PATHS_ALTERNATIVE) {
                final long numberBlocks = readLong(path);
                if (numberBlocks > 0) {
                    return numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE;
                }
            }
        }
        else{//RK3288
        	//INTERNAL_STORAGE_SIZE_PATHS 这个数组是空的, 元素被注释掉.
            for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
                final long numberBlocks = readLong(path);
                if (numberBlocks > 0) {
                    return numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE;
                }
            }
        }
        return 0;
    }

    private long readLong(String path) {
        try (final FileInputStream fis = new FileInputStream(path);
                final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
            return Long.parseLong(reader.readLine());
        } catch (Exception e) {
            Slog.w(TAG, "Could not read " + path, e);
            return 0;
        }
    }

getPrimaryStorageSize 在RK3368返回正确的存储大小, RK3288返回0

再来确认下, 对应的size文件在3288上是否存在或有效:

rk3288:/ # ll /sys/block/
total 0
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 loop0 -> ../devices/virtual/block/loop0
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 loop1 -> ../devices/virtual/block/loop1
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 loop2 -> ../devices/virtual/block/loop2
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 loop3 -> ../devices/virtual/block/loop3
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 loop4 -> ../devices/virtual/block/loop4
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 loop5 -> ../devices/virtual/block/loop5
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 loop6 -> ../devices/virtual/block/loop6
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 loop7 -> ../devices/virtual/block/loop7
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 mmcblk2 -> ../devices/platform/ff0f0000.dwmmc/mmc_host/mmc2/mmc2:0001/block/mmcblk2
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 mmcblk2boot0 -> ../devices/platform/ff0f0000.dwmmc/mmc_host/mmc2/mmc2:0001/block/mmcblk2/mmcblk2boot0
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 mmcblk2boot1 -> ../devices/platform/ff0f0000.dwmmc/mmc_host/mmc2/mmc2:0001/block/mmcblk2/mmcblk2boot1
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 mmcblk2rpmb -> ../devices/platform/ff0f0000.dwmmc/mmc_host/mmc2/mmc2:0001/block/mmcblk2/mmcblk2rpmb
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram0 -> ../devices/virtual/block/ram0
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram1 -> ../devices/virtual/block/ram1
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram10 -> ../devices/virtual/block/ram10
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram11 -> ../devices/virtual/block/ram11
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram12 -> ../devices/virtual/block/ram12
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram13 -> ../devices/virtual/block/ram13
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram14 -> ../devices/virtual/block/ram14
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram15 -> ../devices/virtual/block/ram15
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram2 -> ../devices/virtual/block/ram2
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram3 -> ../devices/virtual/block/ram3
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram4 -> ../devices/virtual/block/ram4
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram5 -> ../devices/virtual/block/ram5
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram6 -> ../devices/virtual/block/ram6
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram7 -> ../devices/virtual/block/ram7
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram8 -> ../devices/virtual/block/ram8
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 ram9 -> ../devices/virtual/block/ram9
lrwxrwxrwx 1 root root 0 2017-01-01 21:55 zram0 -> ../devices/virtual/block/zram0
rk3288:/ # 
/ff0f0000.dwmmc/mmc_host/mmc2/mmc2:0001/block/mmcblk2/size                    <
30535680

30535680 * 512 = 15634268160 = 14.56GB

于是, 改下代码:

    private static final String[] INTERNAL_STORAGE_SIZE_PATHS = {
            "/sys/block/mmcblk1/size",//8GB
            "/sys/block/mmcblk2/size",//16GB
            //"/sys/block/sda/size"
    };