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
相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui