代码
frameworks/base/services/java/com/android/server/MountService.java
frameworks/base/core/java/android/os/storage/StorageManager.java
frameworks/base/core/java/android/os/storage/StorageVolume.java
frameworks/base/services/java/com/android/server/usb/UsbDeviceManager.java
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
frameworks/base/services/core/java/com/android/server/NativeDaemonConnector.java
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
system/vold
对于Mass Storage,上层软件(kernel之上)只做了两件事
1. Set sys.usb.config=mass_storage
在Settings设置mtp后,代码执行
Usbanager.SetCurrentFunction()
->UsbService.SetCurrentFunction()
->UsbDeviceManager.setCurrentFunctions()
-> mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS)
->setEnabledFunctions(functions, makeDefault);
->SystemProperties.set("persist.sys.usb.config", functions);
2. Write /dev/block/vold/majorid:minored to /sys/class/android_usb/android0/f_mass_storage/lun/file.
这个调用还挺复杂的,这个UI做的实在不好,一般人估计找不到。这个UI完全可以放在UsbSettings.java里。只需在USB_STATE=configured时调用StorageManager.java的enableUsbMassStorage() 就行,只是要放在一个单独线程中进行。
frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java
updateState
sendMessage(MSG_UPDATE_STATE);
updateUsbState
broadcast Intent(ACTION_USB_STATE);
frameworks/base/services/core/java/com/android/server/MountService.java
//if (primary != null && primary.allowMassStorage()) {
Slog.i(TAG, "registerReceiver ACTION_USB_STATE");
mContext.registerReceiver(
mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_STATE), null, mHandler);
//}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
boolean available = (intent.getBooleanExtra(UsbManager.USB_CONNECTED, false) &&
intent.getBooleanExtra(UsbManager.USB_FUNCTION_MASS_STORAGE, false));
notifyShareAvailabilityChange(available);
}
};
notifyShareAvailabilityChange ()
bl.mListener.onUsbMassStorageConnectionChanged(avail);
frameworks/base/core/java/android/os/storage/StorageManager.java
private class MountServiceBinderListener extends IMountServiceListener.Stub {
public void onUsbMassStorageConnectionChanged(boolean available) {
final int size = mListeners.size();
for (int i = 0; i < size; i++) {
mListeners.get(i).sendShareAvailabilityChanged(available);
}
}
UmsConnectionChangedStorageEvent
super(EVENT_UMS_CONNECTION_CHANGED);
void sendShareAvailabilityChanged(boolean available) {
UmsConnectionChangedStorageEvent e = new UmsConnectionChangedStorageEvent(available);
mHandler.sendMessage(e.getMessage()); ->send StorageEvent.EVENT_UMS_CONNECTION_CHANGED
}
if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) {
mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available);
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
onUsbMassStorageConnectionChanged
onUsbMassStorageConnectionChangedAsync
updateUsbMassStorageNotification(true)
setUsbStorageNotification
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
DLG_CONFIRM_KILL_STORAGE_USERS
switchUsbMassStorage(true)
private void switchUsbMassStorage(final boolean on)
enableUsbMassStorage() StorageManager.java
setUsbMassStorageEnabled() MountService.java
UmsEnableCallBack
handleFinished()
doShareUnshareVolume()
send(H_UNMOUNT_PM_UPDATE)
mPms.updateExternalMediaStatus(false, true);
mForceUnmounts.add(ucb)
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
updateExternalMediaStatus()
sendMessage(UPDATED_MEDIA_STATUS)
PackageHelper.getMountService().finishMediaUpdate();
frameworks\base\services\core\java\com\android\server\MountService.java
finishMediaUpdate()
sendEmptyMessage(H_UNMOUNT_PM_DONE);
H_UNMOUNT_PM_DONE
sendMessage(H_UNMOUNT_MS)
H_UNMOUNT_MS
UnmountCallBack.handleFinished()
doUnmountVolume()
final Command cmd = new Command("volume", "unmount", path);
mConnector.execute(cmd);
doShareUnshareVolume()
MTP->Mass Storage,先通知其他packages要unmount SD卡,然后unmount SD卡,然后才shareVolume
doShareUnshareVolume MountService.java
mConnector.execute("volume", enable ? "share" : "unshare", path, method);
execute(int timeout, String cmd, Object... args) NativeDaemonConnector.java
CommandListener::VolumeCmd::runCommand system/vold/CommandListener.cpp
rc = vm->shareVolume(argv[2], argv[3]); system/vold/VolumeManager.cpp
fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY))
write(fd, nodepath, strlen(nodepath)) < 0)
v->handleVolumeShared();
setState(Volume::State_Shared); system/vold/DirectVolume.cpp
system/vold/VolumeManager.cpp
#define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file"
#define UICC0_MASS_STORAGE_PATH "/sys/class/android_usb/android0/f_mass_storage/uicc0/file"
snprintf(nodepath,sizeof(nodepath), "/dev/block/vold/%d:%d", major(d), minor(d));
MountService的启动
SystemServer
mountService = new MountService(context);
readStorageListLocked();
addVolumeLocked()
registerReceiver(UsbManager.ACTION_USB_STATE)
create NativeDaemonConnector to communicate with vold (listenToSocket() for handling information from vold; execute() send data to vold)
ServiceManager.addService("mount", mountService);
readStorageListLocked()
Read from storage_list.xml document:http://source.android.com/tech/storage/
google:frameworks/base/core/res/res/xml/storage_list.xml
简单介绍下vold
main() in main.cpp
vm->start() volume manager
process_config()
get fstable from fstab.qcom
addPath() system/vold/DirectVolume.cpp
mPaths->push_back(strdup(path)); push to the end of the list
addVolume() system/vold/VolumeManager.cpp
mVolumes->push_back(v);
nm->start() netlink manager
cl->startListener() command listener
handleBlockEvent() in system\vold\DirectVolume.cpp
receive NetlinkEvent::NlActionAdd from kernel
createDeviceNode /dev/block/vold/179:64
handleDiskAdded(dp, evt); (sdcard)
handlePartitionAdded(dp, evt) (usb disk)
VoldResponseCode.VolumeUserLabelChange
handleSystemReady()
doMountVolume()的调用
mConnector.execute("volume", "mount", path); send to vold-commandlistener
VolumeCmd::runCommand system\vold\CommandListener.cpp
vm->mountVolume(argv[2]); system\vold\VolumeManager.cpp
Volume->mountVol() system\vold\Volume.cpp
Fat::check system/vold/Fat.cpp
Fat::doMount system/vold/Fat.cpp
mount(fsPath, mountPoint, "vfat", flags, mountData);
bionic/libc/arch-arm/syscalls/mount.S (syscall kernel/arch/arm/kernel/calls.S)
vfat_mount kernel/fs/fat/namei_vfat.c
msdos_mount kernel/fs/fat/namei_msdos.c
mount_bdev kernel/fs/super.c
注意两个配置文件
Fstab文件和storage_list.xml