平台
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"
};