平台
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(); } }
获取系统存储信息:
final List<VolumeInfo> volumes = mStorageManager.getVolumes();
代码没有任何问题, 在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" };