Vold(volume Daemon),即Volume守护进程,用来管理Android中存储类的热拔插事件,处于Kernel和Framework之间,是两个层级连接的桥梁。vold 代码路径为: system/vold 和 /system/core/libsysutils/src
分析代码时,首先要看编译脚本即Android.bp,通过Android.bp 可以看出代码的组织关系,如何编译的。可以看出核心是 vold 这个可执行文件,主要入口为main.cpp,那我们就分析 main.cpp
Android.bp 文件
cc_binary {
name: "vold",
defaults: [
"vold_default_flags",
"vold_default_libs",
],
srcs: ["main.cpp"],
static_libs: ["libvold"],
init_rc: [
"vold.rc",
"wait_for_keymaster.rc",
],
}
可以看出,主要实例化 VolumeManager NetlinkManager,并调用 VolumeManager NetlinkManager VoldNativeService onStart() 方法。
main.cpp
int main(int argc, char** argv) {
// log初始化
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
VolumeManager *vm;
NetlinkManager *nm;
parse_args(argc, argv);//参数解析
mkdir("/dev/block/vold", 0755);
// 获取实例,并调用 start() 方法
vm = VolumeManager::Instance();
nm = NetlinkManager::Instance();
vm->start();
android::vold::VoldNativeService::start();
nm->start();
android::IPCThreadState::self()->joinThreadPool();
}
system/vold/VolumeManager.cpp
int VolumeManager::start() {
unmountAll();
Devmapper::destroyAll();
Loop::destroyAll();
// 通过 EmulatedVolume 完成对 "/data/media" 初始化
mInternalEmulated = std::shared_ptr(
new android::vold::EmulatedVolume("/data/media"));
mInternalEmulated->create();
updateVirtualDisk();
}
通过 Netlink 与 kernel 进行通信,并new NetlinkHandler对象,并调用 start()方法。
重点在 NetlinkHandler,该类集成关系如下:NetlinkHandler -> NetlinkListener -> SocketListener
system/vold/NetlinkManager.cpp
NetlinkManager *NetlinkManager::sInstance = NULL;
NetlinkManager *NetlinkManager::Instance() {
if (!sInstance)
sInstance = new NetlinkManager();
return sInstance;
}
int NetlinkManager::start() {
//PF_NETLINK: Netlink 用于在内核模块与在用户地址空间中的进程之间传递消息
mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC,
NETLINK_KOBJECT_UEVENT)
setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz);
setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz);
setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)
bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr);
//重点,new NetlinkHandler对象,并调用 start()方法
mHandler = new NetlinkHandler(mSock);
mHandler->start();
}
NetlinkHandler 继承于 NetlinkListener,而NetlinkHandler start() 方法,调用 this->startListener();
该方法必然是父类 NetlinkListener 的方法,继续跟踪代码。
system/vold/NetlinkHandler.h
class NetlinkHandler: public NetlinkListener {
public:
int start(void);
int stop(void);
private:
virtual void onEvent(NetlinkEvent *evt);
}
system/vold/NetlinkHandler.cpp
NetlinkHandler::NetlinkHandler(int listenerSocket) :
NetlinkListener(listenerSocket) {
}
int NetlinkHandler::start() {
return this->startListener();
}
int NetlinkHandler::stop() {
return this->stopListener();
}
void NetlinkHandler::onEvent(NetlinkEvent *evt) {
VolumeManager *vm = VolumeManager::Instance();
const char *subsys = evt->getSubsystem();
if (std::string(subsys) == "block") {
vm->handleBlockEvent(evt);
}
}
NetlinkListener 继承于 NetlinkListener,而且NetlinkListener 没有实现 startListener方法,那么该方法应该是其父类实现,继续跟踪。
system/core/libsysutils/include/sysutils/NetlinkListener.h
class NetlinkListener : public SocketListener {
virtual bool onDataAvailable(SocketClient *cli);
virtual void onEvent(NetlinkEvent *evt) = 0;
}
system/core/libsysutils/src/NetlinkListener.cpp
NetlinkListener::NetlinkListener(int socket) :
SocketListener(socket, false) {
mFormat = NETLINK_FORMAT_ASCII;
}
bool NetlinkListener::onDataAvailable(SocketClient *cli){
int socket = cli->getSocket();
count = TEMP_FAILURE_RETRY(uevent_kernel_recv(socket,
mBuffer, sizeof(mBuffer), require_group, &uid));
NetlinkEvent *evt = new NetlinkEvent();
if (evt->decode(mBuffer, count, mFormat)) {
onEvent(evt);
}
}
终于找到 startListener()方法的实现类。startListener() 方法通过 pthread_create(&mThread, NULL, SocketListener::threadStart, this) 创建单独线程,线程执行方法为 threadStart(),所以会走到 threadStart()方法。
threadStart() 方法有调用 SocketListener类的 runListener() 方法,runListener() 方法主要通过 select() read() 方法 获取事件信息,并放入 pendingList 链表中,最后逐个调用链表元素中的 onDataAvailable() 方法,而该方法在 SocketListener 类中是纯虚函数,必须由子类进行实现,所以到 NetlinkListener 继续分析。
由 NetlinkListener 分析可知,其实现了 onDataAvailable() 方法,该方法 通过uevent_kernel_recv 获取 kernel 的uevent 事件,并最终调用 onEvent() 方法。同样 onEvent() 方法在 NetlinkListener 类中是纯虚函数,所以必须由其子类 NetlinkHandler 实现,所以到 NetlinkHandler 继续分析。
由 NetlinkHandler 分析可知,其实现了 onEvent() 方法,并通过 VolumeManager实例调用其 handleBlockEvent() 方法,我们到 VolumeManager类继续分析。
system/core/libsysutils/include/sysutils/SocketListener.h
class SocketListener {
public:
int startListener();
int stopListener();
protected:
virtual bool onDataAvailable(SocketClient *c) = 0;
private:
static void *threadStart(void *obj);
void runListener();
void init(const char *socketName, int socketFd, bool listen, bool useCmdNum);
}
system/core/libsysutils/src/SocketListener.cpp
void SocketListener::runListener() {
SocketClientCollection pendingList;
while(1){
for (it = mClients->begin(); it != mClients->end(); ++it) {
int fd = (*it)->getSocket();
FD_SET(fd, &read_fds);
}
rc = select(max + 1, &read_fds, NULL, NULL, NULL)
TEMP_FAILURE_RETRY(accept4(mSock, nullptr, nullptr, SOCK_CLOEXEC));
mClients->push_back(new SocketClient(c, true, mUseCmdNum));
for (it = mClients->begin(); it != mClients->end(); ++it) {
SocketClient* c = *it;
int fd = c->getSocket();
if (FD_ISSET(fd, &read_fds)) {
pendingList.push_back(c);
}
}
while (!pendingList.empty()) {
it = pendingList.begin();
SocketClient* c = *it;
onDataAvailable(c))
}
}
}
void *SocketListener::threadStart(void *obj) {
SocketListener *me = reinterpret_cast(obj);
me->runListener();
}
int SocketListener::startListener(int backlog) {
if (mListen && listen(mSock, backlog) < 0)
mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
pthread_create(&mThread, NULL, SocketListener::threadStart, this)
}
VolumeManager 类 handleBlockEvent 根据 NetlinkEvent 类型不同调用不同的方法。类型有kAdd,kChange,kRemove,分别对应设备新增,设备变更,设备移除操作。以kAdd 为例分析,其调用 handleDiskAdded() 方法,该方法调用
system/vold/VolumeManager.cpp
void VolumeManager::handleDiskAdded(const std::shared_ptr& disk) {
disk->create();
mDisks.push_back(disk);
}
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
switch (evt->getAction()) {
case NetlinkEvent::Action::kAdd: {
auto disk = new android::vold::Disk(eventPath, device,source->getNickname(), flags);
handleDiskAdded(std::shared_ptr(disk));
}
case NetlinkEvent::Action::kChange: {
handleDiskChanged(device);
}
case NetlinkEvent::Action::kRemove: {
handleDiskRemoved(device);
}
}
}
其中 create() 方法通过 VolumeManager::Instance()->getListener() 获取 listener 并调用 onDiskCreated() 通知到 java StorageManagerService中,这是如何实现的我们继续分析。
system/vold/model/Disk.cpp
status_t Disk::create() {
CHECK(!mCreated);
mCreated = true;
auto listener = VolumeManager::Instance()->getListener();
if (listener) listener->onDiskCreated(getId(), mFlags);
readMetadata();
readPartitions();
return OK;
}
可以看到 VolumeManager 中实现 getListener() 方法,但是也仅是返回了 mListerner 变量,该变量是在 setListener() 中设置的,通过函数参数可以看出其通过 AIDL 实现了这样的调用。
system/vold/VolumeManager.h
void setListener(android::sp listener) { mListener = listener; }
android::sp getListener() { return mListener; }
void handleBlockEvent(NetlinkEvent *evt);
system/vold/binder/android/os/IVold.aidl
package android.os;
import android.os.IVoldListener;
import android.os.IVoldTaskListener;
interface IVold {
void setListener(IVoldListener listener);
void onUserAdded(int userId, int userSerial);
void onUserRemoved(int userId);
void mount(@utf8InCpp String volId, int mountFlags, int mountUserId);
void unmount(@utf8InCpp String volId);
void format(@utf8InCpp String volId, @utf8InCpp String fsType);
void checkEncryption(@utf8InCpp String volId);
void mkdirs(@utf8InCpp String path);
void fbeEnable();
void mountDefaultEncrypted();
void unlockUserKey(int userId, int userSerial, @utf8InCpp String token, @utf8InCpp String secret);
void lockUserKey(int userId);
}
StorageManagerServie 在connect() 方法中,通过ServiceManager获取 vold 服务,并获取到binder 对象 ,最后通过 setListener(mListener)方法,其中 mListener 为 private final IVoldListener mListener = new IVoldListener.Stub() ,所以在 Disk.cpp 中 listener 为 StorageManagerService 设置的 listener,其 listener->onDiskCreated(getId(), mFlags) 也会调用到 StorageManagerService 中 IVoldListener.Stub 中方法。
frameworks/base/services/core/java/com/android/server/StorageManagerService.java
import android.os.IVold;
import android.os.IVoldListener;
import android.os.IVoldTaskListener;
private void connect() {
IBinder binder = ServiceManager.getService("storaged");
mStoraged = IStoraged.Stub.asInterface(binder);
binder = ServiceManager.getService("vold");
mVold = IVold.Stub.asInterface(binder);
mVold.setListener(mListener);
onDaemonConnected();
}
private final IVoldListener mListener = new IVoldListener.Stub() {
@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;
}
mDisks.put(diskId, new DiskInfo(diskId, flags));
}
}
@Override
public void onDiskScanned(String diskId) {
synchronized (mLock) {
final DiskInfo disk = mDisks.get(diskId);
if (disk != null) {
onDiskScannedLocked(disk);
}
}
}
@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);
}
}
}
@Override
public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
synchronized (mLock) {
final DiskInfo disk = mDisks.get(diskId);
final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
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);
}
}
}
}