Android9.0 外部存储浅析
2020-10-20 本文已影响0人
Boerma
Android9.0 外部存储浅析
vold进程
main函数
初始化VolumeManager,NetlinkManager等一系列基础动作。
int main(int argc, char** argv) {
//......
/* Create our singleton managers */
if (!(vm = VolumeManager::Instance())) {
LOG(ERROR) << "Unable to create VolumeManager";
exit(1);
}
if (!(nm = NetlinkManager::Instance())) {
LOG(ERROR) << "Unable to create NetlinkManager";
exit(1);
}
if (android::base::GetBoolProperty("vold.debug", false)) {
vm->setDebug(true);
}
if (vm->start()) {
PLOG(ERROR) << "Unable to start VolumeManager";
exit(1);
}
//......
ATRACE_BEGIN("NetlinkManager::start");
if (nm->start()) {
PLOG(ERROR) << "Unable to start NetlinkManager";
exit(1);
}
ATRACE_END();
//......
}
vm->start()
进行预制存储的挂载
int VolumeManager::start() {
ATRACE_NAME("VolumeManager::start");
// Always start from a clean slate by unmounting everything in
// directories that we own, in case we crashed.
unmountAll();
Devmapper::destroyAll();
Loop::destroyAll();
// Assume that we always have an emulated volume on internal
// storage; the framework will decide if it should be mounted.
CHECK(mInternalEmulated == nullptr);
//这里是sdcard/emulated分区
mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>(
new android::vold::EmulatedVolume("/data/media"));
mInternalEmulated->create();
// Consider creating a virtual disk
updateVirtualDisk();
return 0;
}
nm->start()
与kennel建立联系
int NetlinkManager::start() {
struct sockaddr_nl nladdr;
//......
//与kennel建立联系
//......
//上报事件关键
mHandler = new NetlinkHandler(mSock);
if (mHandler->start()) {
PLOG(ERROR) << "Unable to start NetlinkHandler";
goto out;
}
//......
}
建立联系后,kennel的事件上报将会回调至NetlinkHandler中的onEvent函数
void NetlinkHandler::onEvent(NetlinkEvent *evt) {
VolumeManager *vm = VolumeManager::Instance();
const char *subsys = evt->getSubsystem();
if (!subsys) {
LOG(WARNING) << "No subsystem found in netlink event";
return;
}
if (std::string(subsys) == "block") {
vm->handleBlockEvent(evt);
}
}
最终回到VolumeManager中的handleBlockEvent(NetlinkEvent *evt)函数
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
std::lock_guard<std::mutex> lock(mLock);
/*
......
创建device信息
......
*/
//区分事件
switch (evt->getAction()) {
case NetlinkEvent::Action::kAdd: { //添加
for (const auto& source : mDiskSources) {
if (source->matches(eventPath)) {
// For now, assume that MMC and virtio-blk (the latter is
// emulator-specific; see Disk.cpp for details) devices are SD,
// and that everything else is USB
int flags = source->getFlags();
if (major == kMajorBlockMmc
|| (android::vold::IsRunningInEmulator()
&& major >= (int) kMajorBlockExperimentalMin
&& major <= (int) kMajorBlockExperimentalMax)) {
flags |= android::vold::Disk::Flags::kSd;
} else {
flags |= android::vold::Disk::Flags::kUsb;
}
auto disk = new android::vold::Disk(eventPath, device,
source->getNickname(), flags);
//添加设备
handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));
break;
}
}
break;
}
case NetlinkEvent::Action::kChange: { //状态改变
LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
handleDiskChanged(device);
break;
}
case NetlinkEvent::Action::kRemove: { ////移除
handleDiskRemoved(device);
break;
}
default: {
LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction();
break;
}
}
}
当一个外部存储插入设备后经过上报及区分后,调用handleDiskAdded函数
void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) {
// For security reasons, if secure keyguard is showing, wait
// until the user unlocks the device to actually touch it
if (mSecureKeyguardShowing) {
LOG(INFO) << "Found disk at " << disk->getEventPath()
<< " but delaying scan due to secure keyguard";
mPendingDisks.push_back(disk);
} else {
//disk进行初始化,disk基础信息,分区挂载等
disk->create();
mDisks.push_back(disk);
}
}
disk->create()
status_t Disk::create() {
CHECK(!mCreated);
mCreated = true;
//从这里将会调用frameworks层StorageManagerService中的实现函数
auto listener = VolumeManager::Instance()->getListener();
if (listener) listener->onDiskCreated(getId(), mFlags);
//检查disk文件系统格式
readMetadata();
//读取分区列表
readPartitions();
return OK;
}
readPartitions()
status_t Disk::readPartitions() {
int maxMinors = getMaxMinors();
if (maxMinors < 0) {
return -ENOTSUP;
}
destroyAllVolumes();
// Parse partition table
//......
if (table == Table::kMbr) {
if (++it == split.end()) continue;
int type = 0;
if (!android::base::ParseInt("0x" + *it, &type)) {
LOG(WARNING) << "Invalid partition type " << *it;
continue;
}
switch (type) {
case 0x06: // FAT16
case 0x07: // HPFS/NTFS/exFAT
case 0x0b: // W95 FAT32 (LBA)
case 0x0c: // W95 FAT32 (LBA)
case 0x0e: // W95 FAT16 (LBA)
//挂载磁盘分区
createPublicVolume(partDevice);
break;
}
} else if (table == Table::kGpt) {
if (++it == split.end()) continue;
auto typeGuid = *it;
if (++it == split.end()) continue;
auto partGuid = *it;
if (android::base::EqualsIgnoreCase(typeGuid, kGptBasicData)) {
createPublicVolume(partDevice);
} else if (android::base::EqualsIgnoreCase(typeGuid, kGptAndroidExpand)) {
createPrivateVolume(partDevice, partGuid);
}
}
//......
}
createPublicVolume
void Disk::createPublicVolume(dev_t device) {
auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device));
if (mJustPartitioned) {
LOG(DEBUG) << "Device just partitioned; silently formatting";
vol->setSilent(true);
vol->create();
vol->format("auto");
vol->destroy();
vol->setSilent(false);
}
mVolumes.push_back(vol);
vol->setDiskId(getId());
//分区初始化
vol->create();
}
vol->create()
status_t VolumeBase::create() {
CHECK(!mCreated);
mCreated = true;
status_t res = doCreate();
auto listener = getListener();
//这里将会回调至frameworks层StorageManagerService中的实现函数,
if (listener) listener->onVolumeCreated(getId(),
static_cast<int32_t>(mType), mDiskId, mPartGuid);
//设置状态
setState(State::kUnmounted);
return res;
}
void VolumeBase::setState(State state) {
mState = state;
auto listener = getListener();
//这里将会回调至frameworks层StorageManagerService中的实现函数,当分区初始化完成后,frameworks会发送mount广播。
if (listener) listener->onVolumeStateChanged(getId(), static_cast<int32_t>(mState));
}
以上即是vold进程对于外部存储设备的大致加载过程。监听kennel事件先创建disk,然后再挂载volume。这里需要注意内置的存储没有disk,只有volume。
StorageManagerService
StorageManagerService是由SystemServer来启动的
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored
* and organized.
*/
private void startOtherServices() {
final Context context = mSystemContext;
//......
IStorageManager storageManager = null;
//......
if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
traceBeginAndSlog("StartStorageManagerService");
try {
/*
* NotificationManagerService is dependant on StorageManagerService,
* (for media / usb notifications) so we must start StorageManagerService first.
*/
mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS);
//获取binder
storageManager = IStorageManager.Stub.asInterface(
ServiceManager.getService("mount"));
} catch (Throwable e) {
reportWtf("starting StorageManagerService", e);
}
traceEnd();
traceBeginAndSlog("StartStorageStatsService");
try {
//启动服务
mSystemServiceManager.startService(STORAGE_STATS_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting StorageStatsService", e);
}
traceEnd();
}
}
//......
}
StorageManagerService启动
@Override
public void onStart() {
mStorageManagerService = new StorageManagerService(getContext());
publishBinderService("mount", mStorageManagerService);
mStorageManagerService.start();
}
//......
private void start() {
connect();
}
//......
private void connect() {
IBinder binder = ServiceManager.getService("storaged");
//......
binder = ServiceManager.getService("vold");
if (binder != null) {
try {
binder.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Slog.w(TAG, "vold died; reconnecting");
mVold = null;
connect();
}
}, 0);
} catch (RemoteException e) {
binder = null;
}
}
if (binder != null) {
mVold = IVold.Stub.asInterface(binder);
try {
//注入回调至vold进程
mVold.setListener(mListener);
} catch (RemoteException e) {
mVold = null;
Slog.w(TAG, "vold listener rejected; trying again", e);
}
} else {
Slog.w(TAG, "vold not found; trying again");
}
}
vold回调
接下来就是最最关键的frameworks层,当存储挂载完成后将由这里发送广播通知到所有监听存储的应用中。例如MediaScanner
private final IVoldListener mListener = new IVoldListener.Stub() {
//磁盘初始化,这里对应的是vold进程中disk->create()函数
@Override
public void onDiskCreated(String diskId, int flags) {
synchronized (mLock) {
final String value = SystemProperties.get(StorageManager.PROP_ADOPTABLE);
switch (value) {
case "force_on":
flags |= DiskInfo.FLAG_ADOPTABLE;
break;
case "force_off":
flags &= ~DiskInfo.FLAG_ADOPTABLE;
break;
}
//该集合就是app通过getDisks()函数所获的的集合(有中间封装,但根本还是从这个集合中获取的)
mDisks.put(diskId, new DiskInfo(diskId, flags));
}
}
//......
@Override
public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
String sysPath) {
synchronized (mLock) {
final DiskInfo disk = mDisks.get(diskId);
if (disk != null) {
disk.size = sizeBytes;
disk.label = label;
disk.sysPath = sysPath;
}
}
}
@Override
public void onDiskDestroyed(String diskId) {
synchronized (mLock) {
final DiskInfo disk = mDisks.remove(diskId);
if (disk != null) {
mCallbacks.notifyDiskDestroyed(disk);
}
}
}
//分区初始化,vol->create()函数
@Override
public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
synchronized (mLock) {
final DiskInfo disk = mDisks.get(diskId);
//这里没有对disk进行非空判断,经实验,设备内置的存储emulated分区没有disk信息。所以不做非空校验
final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
//该集合就是app通过getVolumesList()函数所获的的集合(有中间封装,但根本还是从这个集合中获取的)
mVolumes.put(volId, vol);
onVolumeCreatedLocked(vol);
}
}
@Override
public void onVolumeStateChanged(String volId, int state) {
synchronized (mLock) {
final VolumeInfo vol = mVolumes.get(volId);
if (vol != null) {
final int oldState = vol.state;
final int newState = state;
vol.state = newState;
//分区状态改变。
onVolumeStateChangedLocked(vol, oldState, newState);
}
}
}
//......
@Override
public void onVolumeDestroyed(String volId) {
synchronized (mLock) {
mVolumes.remove(volId);
}
}
};
@GuardedBy("mLock")
private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
//......
mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
//......
}
class StorageManagerServiceHandler extends Handler {
public StorageManagerServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//......
case H_VOLUME_BROADCAST: {
final StorageVolume userVol = (StorageVolume) msg.obj;
final String envState = userVol.getState();
Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
+ userVol.getOwner());
//根据不同状态获取不同广播,挂载成功后就是mounted广播
final String action = VolumeInfo.getBroadcastForEnvironment(envState);
if (action != null) {
final Intent intent = new Intent(action,
Uri.fromFile(userVol.getPathFile()));
intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mContext.sendBroadcastAsUser(intent, userVol.getOwner());
}
break;
}
//......
}
小结
目前个人所看到的大致流程就是这样,vold监听kennel上报事件,创建disk,然后再初始化挂载volume,最终发送广播至上层应用。