Android10 U盘支持EXFAT和NTFS
前言
大家知道目前安卓AOSP只支持FAT32,还不支持EXFAT和NTFS,这两种windows支持的格式使用上还是比较普遍的,所以安卓也能支持那就相当nice了,不然安卓就会提醒让格式化,这是很危险的,格式化后数据就丢失了,目前网上有很多资料可以实现安卓支持EXFAT/NTFS,特别是EXFAT,参照资料就能完美的支持,但是NTFS就没那么明确,我这里根据之前的经验做个总结,方便大家参考
系统信息:
Android10
kernel 4.19
第一步需要kernel支持EXFAT和NTFS
kernel中移植exfat-nofuse
源码:https://github.com/dorimanx/exfat-nofuse
将代码下载解压后,更名exfat放到kernel/fs下, 修改kernel下Kconfig、Makefile:
diff
-git a/kernel/fs/Kconfigb/kernel/fs/Kconfig
index b8d003f. .65ce644 100644
a/kernel/fs/Kconfig
+ b/kernel/fs/Kconfig
60 - 133,10 +133,11 ea endmenu
endif # BLOCK
if BLOCK
source "fs/fat/Kconfig"
source "fs/ntfs/Kconfig"
+source "fs/exfat/Kconfig
endmenu
endif # BLOCK
diff --git a/kernel/fs/Makefile b/kernel/fs/Makefile
index 5030ac9. .d6c02f2 100644
a/kernel/fs/Makefile
+ b/kernel/fs/Makefile
60 -80,6 +80,7 (@ obj -$(CONFIG_HUGETLBFS)+= hugetlbfs/
obj-(CONFIG_MINIX_FS)+= minix/
obj-(CONFIG_FAT_FS)+= fat/
+ obj-(CONFIG_EXFAT_FS)+= exfat/
+ obj-(CONFIG_NTFS_FS)+= ntfs/
obj-(CONFIG_BFS_FS)+= bfs/
obj-(CONFIG_IS09660_FS)+=isofs/
在kernel默认编译配置文件中打开NTFS和EXFAT配置:
@@ -927,3 +927,6 CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_BUG_ON_DATA_CORRUPTION=Y
CONFIG_LEDS_AM20108=y
+CONFIG_NTFS_FS=Y
+CONETG_NTES_BW=Y
+CONFIG_EXFAT_FS=Y
编译kernel,生产的image替换后,通过cat /proc/filesystems查看,有exfat和ntfs就可以了(图片来自网络)
移植fuse:
https://github.com/Shawnsongs/Android_P_external_exfat_ntfs-3g/tree/master/external-exfat-fuse
下载后改名exfat放到external中,编译生成mkfs.exfat和fsck.exfat
目前AOSP已经在system/vold/fs/Exfat.cpp支持EXFAT,所以当上一步kennel已经加载exfat,exfat应该已经可以使用了,如果还是不行就需要看下是不是selinux的问题,selinux的比较简单,只需要针对缺少的权限加上就可以了
但是ntfs的源码是没有的,这里我们可以参考EXFAT来模拟写一份
Ntfs.cpp
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/mount.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <logwrap/logwrap.h>
#include "Ntfs.h"
#include "Utils.h"
using android::base::StringPrintf;
namespace android {
namespace vold {
namespace ntfs {
static const char* kNtfsPath = "/system/bin/ntfs-3g";
bool IsSupported() {
return access(kNtfsPath, X_OK) == 0 &&
IsFilesystemSupported("ntfs");
}
status_t Check(const std::string& source) {
return 0;
}
status_t Mount(const std::string& source, const std::string& target, int ownerUid, int ownerGid,
int permMask) {
int mountFlags = MS_NODEV | MS_NOSUID | MS_DIRSYNC | MS_NOATIME | MS_NOEXEC;
auto mountData = android::base::StringPrintf("uid=%d,gid=%d,fmask=%o,dmask=%o", ownerUid,
ownerGid, permMask, permMask);
if (mount(source.c_str(), target.c_str(), "ntfs", mountFlags, mountData.c_str()) == 0) {
return 0;
}
PLOG(ERROR) << "Mount failed; attempting read-only";
mountFlags |= MS_RDONLY;
if (mount(source.c_str(), target.c_str(), "ntfs", mountFlags, mountData.c_str()) == 0) {
return 0;
}
return -1;
}
status_t Format(const std::string& source) {
return 0;
}
} // namespace exfat
} // namespace vold
} // namespace android
Ntfs.h
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <utils/Errors.h>
#include <string>
namespace android {
namespace vold {
namespace ntfs {
bool IsSupported();
status_t Check(const std::string& source);
status_t Mount(const std::string& source, const std::string& target, int ownerUid, int ownerGid,
int permMask);
status_t Format(const std::string& source);
} // namespace ntfs
} // namespace vold
} // namespace android
#endif
把这两个文件加入到Exfat.cpp同目录下,再修改/system/vold/model/PublicVolume.cpp跟exfat相同的地方加上ntfs,这里我们不支持格式化成ntfs了
status_t PublicVolume::doMount() {
readMetadata();
if (mFsType == "vfat" && vfat::IsSupported()) {
if (vfat::Check(mDevPath)) {
LOG(ERROR) << getId() << " failed filesystem check";
return -EIO;
}
} else if (mFsType == "exfat" && exfat::IsSupported()) {
if (exfat::Check(mDevPath)) {
LOG(ERROR) << getId() << " failed filesystem check";
return -EIO;
}
+} else if (mFsType == "ntfs" && exfat::IsSupported()) {
+ if (exfat::Check(mDevPath)) {
+ LOG(ERROR) << getId() << " failed filesystem check";
+ return -EIO;
+ }
}
......
if (mFsType == "vfat") {
if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007,
true)) {
PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
return -EIO;
}
} else if (mFsType == "exfat") {
if (exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
return -EIO;
}
+}else if (mFsType == "ntfs") {
+ if (ntfs::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
+ PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
+ return -EIO;
+ }
}
ntfs-3g网上可以下载到bin档可以直接使用,并且ntfs支持会有selinux问题,这块需要针对性修改,到此,EXFAT和NTFS就已经支持了,如有问题,可以联系我大家讨论。