网上查了好几个说可以改的,没有一个完整可以用的,通过日志跟踪熬了个通宵,终于搞定了这个中文汉字卷标问题 。
修改完了后DocumentUI中显示的U盘盘符(卷标)效果如下:

- 方案一:Base64编码解码法
原理:在PublicVolume.cpp中盘符名称mFsLabel在过aidl接口onVolumeMetadataChanged时数据会发生变化,就导致了java侧StorageManagerService.java无法正常以GBK方式解码,我们只需要用Base64编码一下再让其过aidl接口那么数据就不会变化了
修改patch完整内容:
cpp
commit c2533a52677cefaccf2e5bd339bc07dd1b1ccbc1
Author: lyw <lyw@incartech.cn>
Date: Sun May 24 12:22:31 2026 +0800
解决U盘中文盘符(卷标)显示乱码问题-Base64编解码法
M sys/external/e2fsprogs/misc/blkid.c
M sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java
M sys/system/vold/model/PublicVolume.cpp
diff --git a/sys/external/e2fsprogs/misc/blkid.c b/sys/external/e2fsprogs/misc/blkid.c
index 472f0179ee9..e039cb409e0 100644
--- a/sys/external/e2fsprogs/misc/blkid.c
+++ b/sys/external/e2fsprogs/misc/blkid.c
@@ -266,7 +266,11 @@ static void print_tags(blkid_dev dev, char *show[], int numtag, int output)
}
fputs(type, stdout);
fputs("=\"", stdout);
- safe_print(value, -1);
+ if (strcmp(type, "LABEL") == 0 ) {
+ fputs(value, stdout);
+ } else {
+ safe_print(value, -1);
+ }
fputs("\" ", stdout);
}
}
diff --git a/sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java b/sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java
index 7d17b91684d..dada891dd7b 100755
--- a/sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java
+++ b/sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java
@@ -126,6 +126,7 @@ import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.Base64;
import android.util.DataUnit;
import android.util.EventLog;
import android.util.Log;
@@ -174,6 +175,7 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -1653,6 +1655,14 @@ class StorageManagerService extends IStorageManager.Stub
*/
Slog.i(TAG, "Cmd recv onVolumeMetadataChanged " + volId + " " + fsType
+ " " + fsUuid + " " + fsLabel);
+
+ try {
+ fsLabel = new String(Base64.decode(fsLabel, Base64.DEFAULT), "GBK");
+ Log.e(TAG, "onVolumeMetadataChanged GBK str: " + fsLabel);
+ } catch (UnsupportedEncodingException e) {
+ Log.e(TAG, "onVolumeMetadataChanged: " + e);
+ }
+
/** @} */
final VolumeInfo vol = mVolumes.get(volId);
if (vol != null) {
diff --git a/sys/system/vold/model/PublicVolume.cpp b/sys/system/vold/model/PublicVolume.cpp
index fda87661cc6..0c035c8afc8 100755
--- a/sys/system/vold/model/PublicVolume.cpp
+++ b/sys/system/vold/model/PublicVolume.cpp
@@ -79,9 +79,49 @@ PublicVolume::~PublicVolume() {
/* @}*/
}
+std::string base64_encode(const std::string& input) {
+ std::string base64_chars ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ std::string ret;
+ int i = 0;
+ int j = 0;
+ unsigned char char_array_3[3];
+ unsigned char char_array_4[4];
+ size_t in_len = input.size();
+ const char* bytes_to_encode = input.c_str();
+ while (in_len--) {
+ char_array_3[i++] = *(bytes_to_encode++);
+ if (i == 3) {
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+ for(i = 0; i <4; i++)
+ ret += base64_chars[char_array_4[i]];
+ i = 0;
+ }
+ }
+ if (i) {
+ for(j = i; j < 3; j++)
+ char_array_3[j] = '\0';
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+ for (j = 0; j < i + 1; j++)
+ ret += base64_chars[char_array_4[j]];
+ while((i++ < 3))
+ ret += '=';
+ }
+ return ret;
+}
+
status_t PublicVolume::readMetadata() {
status_t res = ReadMetadataUntrusted(mDevPath, &mFsType, &mFsUuid, &mFsLabel);
+ LOG(DEBUG) << "lyw PublicVolume::readMetadata() mFsLabel str= 【" << mFsLabel.c_str() << "】";
+ mFsLabel = base64_encode(mFsLabel);
+ LOG(DEBUG) << "lyw PublicVolume::readMetadata() mFsLabel base64= 【" << mFsLabel.c_str() << "】";
+
auto listener = getListener();
if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel);
日志打印:


- 方案二:查表法
修改patch完整内容:
cpp
commit 95afd3b9876f1b5ddaf1d11f51298ff9b37978a8
Author: lyw <lyw@incartech.cn>
Date: Sun May 24 13:08:54 2026 +0800
解决U盘中文盘符(卷标)显示乱码问题-查表法
M sys/external/e2fsprogs/misc/blkid.c
M sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java
M sys/system/vold/Android.bp
A sys/system/vold/gbk_unicode_map.cpp
A sys/system/vold/gbk_unicode_map.h
M sys/system/vold/model/PublicVolume.cpp
diff --git a/sys/external/e2fsprogs/misc/blkid.c b/sys/external/e2fsprogs/misc/blkid.c
index 472f0179ee9..e039cb409e0 100644
--- a/sys/external/e2fsprogs/misc/blkid.c
+++ b/sys/external/e2fsprogs/misc/blkid.c
@@ -266,7 +266,11 @@ static void print_tags(blkid_dev dev, char *show[], int numtag, int output)
}
fputs(type, stdout);
fputs("=\"", stdout);
- safe_print(value, -1);
+ if (strcmp(type, "LABEL") == 0 ) {
+ fputs(value, stdout);
+ } else {
+ safe_print(value, -1);
+ }
fputs("\" ", stdout);
}
}
diff --git a/sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java b/sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java
index 7d17b91684d..57a26fe21b3 100755
--- a/sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java
+++ b/sys/frameworks/base/services/core/java/com/android/server/StorageManagerService.java
@@ -1652,7 +1652,7 @@ class StorageManagerService extends IStorageManager.Stub
* Unisoc Code @{
*/
Slog.i(TAG, "Cmd recv onVolumeMetadataChanged " + volId + " " + fsType
- + " " + fsUuid + " " + fsLabel);
+ + " " + fsUuid + " " + fsLabel);//mark by lyw
/** @} */
final VolumeInfo vol = mVolumes.get(volId);
if (vol != null) {
diff --git a/sys/system/vold/Android.bp b/sys/system/vold/Android.bp
index 1ccfc097dd9..406c3936ae7 100644
--- a/sys/system/vold/Android.bp
+++ b/sys/system/vold/Android.bp
@@ -117,6 +117,7 @@ cc_library_static {
"EncryptInplace.cpp",
"FileDeviceUtils.cpp",
"FsCrypt.cpp",
+ "gbk_unicode_map.cpp",
"IdleMaint.cpp",
"KeyBuffer.cpp",
"KeyStorage.cpp",
diff --git a/sys/system/vold/gbk_unicode_map.cpp b/sys/system/vold/gbk_unicode_map.cpp
new file mode 100755
index 00000000000..a81869bd2c3
--- /dev/null
+++ b/sys/system/vold/gbk_unicode_map.cpp
@@ -0,0 +1,21926 @@
+#include "gbk_unicode_map.h"
+
+const GbkUnicodeMap gbk_unicode_map[] = {
+ {0x0000, 0x0000},
+/*
+gbk_unicode_map.cpp和gbk_unicode_map.h使用python脚本根据CP936.TXT文件自动生成..
+生成命令:
+python generate_gbk_unicode_map.py CP936.TXT gbk_unicode_map.h gbk_unicode_map.c
+
+https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT
+*/
+
+ {0xFE4F, 0xFA29},
+};
+
+const int gbk_unicode_map_size = sizeof(gbk_unicode_map) / sizeof(GbkUnicodeMap);
diff --git a/sys/system/vold/gbk_unicode_map.h b/sys/system/vold/gbk_unicode_map.h
new file mode 100755
index 00000000000..113eba95e80
--- /dev/null
+++ b/sys/system/vold/gbk_unicode_map.h
@@ -0,0 +1,12 @@
+#ifndef GBK_UNICODE_MAP_H
+#define GBK_UNICODE_MAP_H
+
+typedef struct {
+ unsigned short gbk; // GBK编码
+ unsigned short unicode; // Unicode编码
+} GbkUnicodeMap;
+
+extern const GbkUnicodeMap gbk_unicode_map[];
+extern const int gbk_unicode_map_size;
+
+#endif // GBK_UNICODE_MAP_H
diff --git a/sys/system/vold/model/PublicVolume.cpp b/sys/system/vold/model/PublicVolume.cpp
index fda87661cc6..1bd93c1645a 100755
--- a/sys/system/vold/model/PublicVolume.cpp
+++ b/sys/system/vold/model/PublicVolume.cpp
@@ -22,6 +22,7 @@
#include "fs/Exfat.h"
#include "fs/Vfat.h"
#include "include/hook/vold_interface.h"
+#include "gbk_unicode_map.h"
#include <android-base/logging.h>
#include <android-base/properties.h>
@@ -79,9 +80,68 @@ PublicVolume::~PublicVolume() {
/* @}*/
}
+std::string unicode_to_utf8(uint16_t unicode) {
+ std::string utf8;
+ if (unicode <= 0x7F) {
+ utf8.push_back(static_cast<char>(unicode));
+ } else if (unicode <= 0x7FF) {
+ utf8.push_back(static_cast<char>(0xC0 | (unicode >> 6)));
+ utf8.push_back(static_cast<char>(0x80 | (unicode & 0x3F)));
+ } else {
+ utf8.push_back(static_cast<char>(0xE0 | (unicode >> 12)));
+ utf8.push_back(static_cast<char>(0x80 | ((unicode >> 6) & 0x3F)));
+ utf8.push_back(static_cast<char>(0x80 | (unicode & 0x3F)));
+ }
+ return utf8;
+}
+
+uint16_t find_unicode_by_gbk(uint16_t gbk_code) {
+ size_t left = 0;
+ size_t right = gbk_unicode_map_size - 1;
+ while (left <= right) {
+ size_t mid = left + (right - left) / 2;
+ uint16_t mid_gbk = gbk_unicode_map[mid].gbk;
+ if (mid_gbk == gbk_code) {
+ return gbk_unicode_map[mid].unicode;
+ } else if (mid_gbk < gbk_code) {
+ left = mid + 1;
+ } else {
+ right = mid - 1;
+ }
+ }
+ return 0xFFFD;
+}
+
+std::string gbk_to_utf8(const std::string& gbk_str) {
+ std::string utf8_result;
+ size_t i = 0;
+ size_t len = gbk_str.length();
+ while (i < len) {
+ unsigned char c = static_cast<unsigned char>(gbk_str[i]);
+ if (c <= 0x7F) {
+ utf8_result.push_back(c);
+ i++;
+ } else if (i + 1 < len) {
+ uint16_t gbk_code = (static_cast<uint16_t>(c) << 8) |
+ static_cast<unsigned char>(gbk_str[i + 1]);
+ uint16_t unicode = find_unicode_by_gbk(gbk_code);
+ utf8_result += unicode_to_utf8(unicode);
+ i += 2;
+ } else {
+ utf8_result += unicode_to_utf8(0xFFFD);
+ i++;
+ }
+ }
+ return utf8_result;
+}
+
status_t PublicVolume::readMetadata() {
status_t res = ReadMetadataUntrusted(mDevPath, &mFsType, &mFsUuid, &mFsLabel);
+ LOG(DEBUG) << "no_iconv_lyw PublicVolume::readMetadata() mFsLabel = 【" << mFsLabel.c_str() << "】";
+ mFsLabel = gbk_to_utf8(mFsLabel);
+ LOG(DEBUG) << "no_iconv_lyw PublicVolume::readMetadata() mFsLabel utf8 = 【" << mFsLabel.c_str() << "】";
+
auto listener = getListener();
if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel);
gbk_unicode_map.cpp和gbk_unicode_map.h生成脚本:
python
import sys
def main():
if len(sys.argv) != 4:
print("Usage: python generate_gbk_unicode_map.py <input_file> <header_file> <source_file>")
sys.exit(1)
input_file = sys.argv[1]
header_file = sys.argv[2]
source_file = sys.argv[3]
mappings = []
with open(input_file, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
# 使用制表符分割,但有些行可能用空格,我们尝试分割
parts = line.split()
if len(parts) < 2:
continue
# 两个部分应该是十六进制字符串,例如:0x8140 和 0x4E00
gbk_hex = parts[0]
unicode_hex = parts[1]
# 去掉开头的0x,并转换为整数
try:
gbk_val = int(gbk_hex, 16)
unicode_val = int(unicode_hex, 16)
except ValueError:
continue
# 保存为元组
mappings.append((gbk_val, unicode_val))
# 按gbk_val排序
mappings.sort(key=lambda x: x[0])
# 写入头文件
with open(header_file, 'w', encoding='utf-8') as f_h:
f_h.write("#ifndef GBK_UNICODE_MAP_H\n")
f_h.write("#define GBK_UNICODE_MAP_H\n\n")
f_h.write("typedef struct {\n")
f_h.write(" unsigned short gbk; // GBK编码\n")
f_h.write(" unsigned short unicode; // Unicode编码\n")
f_h.write("} GbkUnicodeMap;\n\n")
f_h.write("extern const GbkUnicodeMap gbk_unicode_map[];\n")
f_h.write("extern const int gbk_unicode_map_size;\n\n")
f_h.write("#endif // GBK_UNICODE_MAP_H\n")
# 写入源文件
with open(source_file, 'w', encoding='utf-8') as f_s:
f_s.write('#include "gbk_unicode_map.h"\n\n')
f_s.write("const GbkUnicodeMap gbk_unicode_map[] = {\n")
for gbk, unicode in mappings:
f_s.write(" {0x%04X, 0x%04X},\n" % (gbk, unicode))
f_s.write("};\n\n")
f_s.write("const int gbk_unicode_map_size = sizeof(gbk_unicode_map) / sizeof(GbkUnicodeMap);\n")
if __name__ == '__main__':
main()
问题分配与解决过程中涉及到的一些文件:
bash
sys\packages\apps\DocumentsUI\src\com\android\documentsui\sidebar\RootsFragment.java
sys\packages\apps\DocumentsUI\src\com\android\documentsui\roots\RootsLoader.java
sys\packages\apps\DocumentsUI\src\com\android\documentsui\roots\ProvidersCache.java
sys\packages\apps\DocumentsUI\src\com\android\documentsui\base\RootInfo.java
sys\packages\apps\DocumentsUI\src\com\android\documentsui\base\DocumentInfo.java
sys\external\e2fsprogs\lib\blkid\Android.bp
sys\external\e2fsprogs\misc\blkid.c
sys\external\e2fsprogs\lib\blkid\probe.c
sys\system\vold\Android.bp
sys\system\vold\Utils.cpp
sys\system\vold\model\PublicVolume.cpp
sys\frameworks\base\services\core\java\com\android\server\StorageManagerService.java
可能会用到的一些命令:
bash
adb connect 192.168.137.107
adb disconnect 192.168.137.10
adb shell am start com.android.settings/.Settings
adb root
adb remount
cd sys && source build/envsetup.sh && export OUT_DIR=out_system && lunch ussi_arm64_full-userdebug-native
make blkid -j70
make vold -j70
make services -j70