Android 14 U盘无法正常显示中文盘符(卷标)问题解决

网上查了好几个说可以改的,没有一个完整可以用的,通过日志跟踪熬了个通宵,终于搞定了这个中文汉字卷标问题 。

修改完了后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
相关推荐
陆业聪1 小时前
Agent智能体:让AI自己调API干活——从Android Service到AI Agent的思维跃迁
android·人工智能·aigc
莞凰11 小时前
昇腾CANN的“灵脉根基“:Runtime仓库探秘
android·人工智能·transformer
NiceCloud喜云12 小时前
Claude Files API 深入:从上传、复用到配额管理的工程化指南
android·java·数据库·人工智能·python·json·飞书
ujainu12 小时前
CANN pto-isa:虚拟指令集如何连接编译与执行
android·ascend
赏金术士13 小时前
第六章:UI组件与Material3主题
android·ui·kotlin·compose
TechMerger14 小时前
Android 17 重磅重构!服役 20 年的 MessageQueue 迎来无锁改造,卡顿大幅优化!
android·性能优化
yuhuofei202116 小时前
【Python入门】Python中字符串相关拓展
android·java·python
dalancon17 小时前
Android Input Spy Window
android
dalancon18 小时前
InputDispatcher派发事件,查找目标窗口
android