Storage框架整理
base/services/java/com/android/server/MountService.java
base/services/java/com/android/server/pm/PackageManagerService.java
base/core/java/android/os/storage/StorageManager.java
base/packages/DefaultContainerService/src/com/android/defcontainer/
DefaultContainerService.java
packages/apps/Settings/src/com/android/settings
system/vold
package
android.os.storage
class
StorageManager
MountServiceBinderListener[StorageManager]
ObbActionListener[StorageManager]
ObbListenerDelegate[StorageManager]
ObbStateChangedStorageEvent[StorageManager]
StorageEvent[StorageManager]
UmsConnectionChangedStorageEvent[StorageManager]
StorageStateChangedStorageEvent[StorageManager]
ListenerDelegate[StorageManager]
field
TAG[StorageManager]
PROP_SD_DEFAULT_PATH[StorageManager]
PROP_SD_INTERNAL_PATH[StorageManager]
PROP_SD_EXTERNAL_PATH[StorageManager]
ICS_STORAGE_PATH_SD1[StorageManager]
ICS_STORAGE_PATH_SD2[StorageManager]
STORAGE_PATH_SD1[StorageManager]
STORAGE_PATH_SD2[StorageManager]
mMTKExternalCacheDir[StorageManager]
mMountService[StorageManager]
mTgtLooper[StorageManager]
mBinderListener [StorageManager]
mListeners[StorageManager]
mNextNonce[StorageManager]
mObbActionListener[StorageManager]
mListeners[StorageManager.ObbActionListener]
mObbEventListenerRef[StorageManager.ObbListenerDelegate]
mHandler[StorageManager.ObbListenerDelegate]
nonce[StorageManager.ObbListenerDelegate]
path[StorageManager.ObbStateChangedStorageEvent]
state[StorageManager.ObbStateChangedStorageEvent]
EVENT_UMS_CONNECTION_CHANGED[StorageManager.StorageEvent]
EVENT_STORAGE_STATE_CHANGED[StorageManager.StorageEvent]
EVENT_OBB_STATE_CHANGED[StorageManager.StorageEvent]
mMessage[StorageManager.StorageEvent]
available[StorageManager.UmsConnectionChangedStorageEvent]
path[StorageManager.StorageStateChangedStorageEvent]
oldState[StorageManager.StorageStateChangedStorageEvent]
newState[StorageManager.StorageStateChangedStorageEvent]
mStorageEventListener[StorageManager.ListenerDelegate]
mHandler[StorageManager.ListenerDelegate]
method
onUsbMassStorageConnectionChanged[StorageManager.MountServiceBinderListener]
onStorageStateChanged[StorageManager.MountServiceBinderListener]
onObbResult[StorageManager.ObbActionListener]
addListener[StorageManager.ObbActionListener]
getNextNonce[StorageManager]
ObbListenerDelegate[StorageManager.ObbListenerDelegate]
getListener[StorageManager.ObbListenerDelegate]
sendObbStateChanged[StorageManager.ObbListenerDelegate]
ObbStateChangedStorageEvent[StorageManager.ObbStateChangedStorageEvent]
StorageEvent[StorageManager.StorageEvent]
getMessage[StorageManager.StorageEvent]
UmsConnectionChangedStorageEvent[StorageManager.UmsConnectionChangedStorageEvent]
StorageStateChangedStorageEvent[StorageManager.StorageStateChangedStorageEvent]
ListenerDelegate[StorageManager.ListenerDelegate]
getListener[StorageManager.ListenerDelegate]
sendShareAvailabilityChanged[StorageManager.ListenerDelegate]
sendStorageStateChanged[StorageManager.ListenerDelegate]
from[StorageManager]
StorageManager[StorageManager]
registerListener[StorageManager]
unregisterListener[StorageManager]
enableUsbMassStorage[StorageManager]
disableUsbMassStorage[StorageManager]
isUsbMassStorageConnected[StorageManager]
isUsbMassStorageEnabled[StorageManager]
mountObb[StorageManager]
unmountObb[StorageManager]
isObbMounted[StorageManager]
getMountedObbPath[StorageManager]
getVolumeState[StorageManager]
getVolumeList[StorageManager]
getVolumePaths[StorageManager]
getPrimaryVolume[StorageManager]
getPrimaryVolume[StorageManager]
getDefaultPath[StorageManager]
setDefaultPath[StorageManager]
getMTKExternalCacheDir[StorageManager]
getExternalStoragePath[StorageManager]
getInternalStoragePath[StorageManager]
应用PhoneStatusBarPolicy.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
调用StorageManager的监听注册函数,将监听的StorageEventListener注册到StorageManager中,当有状态变化时,会调用该类的对应函数。通常在具体需要storage状态变化的场景会定义一个新类,继承于StorageEventListener。下面注册到StorageManager的listener就是继承于StorageEventListener。
// storage
mStorageManager=(StorageManager)context.getSystemService(Context.STORAGE_SERVICE);
mStorageManager.registerListener(new com.android.systemui.usb.StorageNotification(context));
com.android.systemui.usb.StorageNotification就是继承于StorageEventListener。
1) registerListener
public void registerListener(StorageEventListener listener){
if (listener == null) {
return;
}
synchronized (mListeners) {
if (mBinderListener == null ) {
try {
mBinderListener = new MountServiceBinderListener();
mMountService.registerListener(mBinderListener);
} catch (RemoteException rex) {
Log.e(TAG, "Register mBinderListener failed");
return;
}
}
mListeners.add(newListenerDelegate(listener));
}
}
2) StorageManager的registerListener有两个功能,一个是接收其他应用过来的申请,将他们的StorageEventListener,转换成ListenerDelegate对象,然后保存在mListeners 这个数组中。
privateList
mListeners.add(newListenerDelegate(listener));
另外一个功能就是向mountService注册listener,StorageManager也是个中间者,拿不到一手信息,需要从上线拿到资源,所以它需要向mountService注册listener。
mBinderListener = new MountServiceBinderListener();
mMountService.registerListener(mBinderListener);
注册进去的类型为MountServiceBinderListener,是MountServiceListener的实现。
特别注意:在mountService中,对注册进来的MountServiceBinderListener又做了一层处理,恶心的是两个类是同一个名字。
MountServiceBinderListener bl =new MountServiceBinderListener(listener);
参数listener的类型是上面蓝色的,从StorageManager传过来,红色的是mountService中的类,类似于StorageManager中的ListenerDelegate。实现如下:
private final class MountServiceBinderListener implementsIBinder.DeathRecipient {
final IMountServiceListener mListener;
MountServiceBinderListener(IMountServiceListener listener){
mListener= listener;
}
StorageManager和MountService都有一个用来记录外边注册进来的listener的数组mListeners,但是使用的类型都是自己包中定义的类,都对传进来的进行了处理。
3) 从底向上的触发
MountService的onEvent会收到底层的调用,进而触发相应的动作,例如调用updatePublicVolumeState,这里边就会调用注册进来的listener的成员函数;bl.mListener.onStorageStateChanged。这样就进入到了StorageManager,其中的listener,MountServiceBinderListener的onStorageStateChanged会被触发。进而依次触发每一个注册到StorageManager的listener,sendStorageStateChanged,发出EVENT_STORAGE_STATE_CHANGED消息。在每个listener注册到StorageManager时,通过ListenerDelegate进行过一次打包,在其构造函数中对每个listener创建了一个handler,不停的接收消息并处理。当接收到EVENT_STORAGE_STATE_CHANGED后就调用注册进来的listener的onStorageStateChanged方法。如上即为com.android.systemui.usb.StorageNotification的onStorageStateChanged函数,所以该类的onStorageStateChanged方法需要重载。
以上内容参考了这篇文章:usb状态相关处理
上面介绍的是上层如何获取系统及底层信息的中断通知的方式,除了这种被动通知状态改变的行为以外,更多的则是应用主动的获取系统的storage信息。这个功能就相对简单、直白了,可以直接调用StorageManager的成员方法。
1) ums功能的使能/禁能/状态查询
2)obb的挂载/卸载及查询
3)获取分区的所有信息:分区列表/挂载点状态/主分区路径等
4) 应用的默认存储路径的管理及内外置卡的路径获取
JB的挂载路径较ics做了更新:
private static final String ICS_STORAGE_PATH_SD1 = "/mnt/sdcard";
private static final String ICS_STORAGE_PATH_SD2 ="/mnt/sdcard2";
private static final String STORAGE_PATH_SD1 ="/storage/sdcard0";
private static final String STORAGE_PATH_SD2 ="/storage/sdcard1";
JB版本以后,为了兼容ICS,将/mnt/sdcard链接到/storage/sdcard0。
mStorageManager=(StorageManager)context.getSystemService(Context.STORAGE_SERVICE);
mStorageManager.functions;
如果外界需要知道系统的storage信息,直接调用StorageManager的方法。那么如果需要实时的知道状态的改变,就需要派一个信使驻扎在StorageManager家里,当有状态变化时,StorageManager会通知驻扎在他家的信使,listener。这就是为什么要安排驻京人员,能够及时的拿到一手信息。
紧接上面的StorageManager,MountService是为framework层和StorageManager服务的,StorageManager为应用程序服务。
-----------------------下面来自网友总结
MountService是运行在SystemService这个进程中,所以上层应用无法直接访问,StorageManager就是提供给应用层来访问存储服务的,它通过Binder机制与MountService所在进程进行通信,将使用者的请求转发进MountService中进行处理。目前StorageManager中支持的方法有enableUsbMassStorage,disableUsbMassStorage,isUsbMassStorageConnected,isUsbMassStorageConnected。在StorageManager的构造函数中,还通过调用MountService中的registerListener函数来注册listener到MountService,同时,它自己也提供了registerListener函数供其它应用来注册listener,这样,当MountService知道存储设备状态变更时,会调用StorageManager中listener的方法,而StorageManager又会继续回调上去,上层应用也就可以做相应的操作,比如图示的更新等。
MountService是一个服务类,在ServiceManager中注册为系统服务,提供对外部存储设备的管理、查询等服务,并在存储设备状态变更时发出通知。MountService起到了一个承上启下的作用,向上公开方法供上层对存储设备进行操作(enable/disable/mount…),并在存储设备状态变更时发出通知。向下接收Vold发来的事件(设备状态变更,设备插入,设备移除等),同时也会将命令发送给Vold,进行更底层的操作。
------------------
工作流程有几个:首先是构造函数的准备工作、一些接口的被调用、以及监听回调。
1) 构造函数
Mediatek/custom/mt8389_tablet_a3v2/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml
android:storageDescription="@string/storage_usb"
android:allowMassStorage="true"
android:mtpReserve="10485760"
android:primary="true"/>
android:storageDescription="@string/storage_sd_card"
android:removable="true"
android:allowMassStorage="true"
android:mtpReserve="10485760"
android:primary="false" />
android:storageDescription="@string/storage_external_usb"
android:removable="true"
android:primary="false"/>
但是vold 中关于外部存储器的挂载路径是在
mediatek/config/mt8389_tablet_a3v2/vold.fstab文件中指定的,
dev_mountsdcard /storage/sdcard0 emmc@fat/devices/platform/goldfish_mmc.0
/devices/platform/mtk-msdc.0/mmc_host
dev_mountsdcard2 /storage/sdcard1 auto/devices/platform/goldfish_mmc.1
/devices/platform/mtk-msdc.1/mmc_host
dev_mount usbotg /mnt/usbotgauto /devices/platform/mt_usb
/devices/platform/musbfsh_hdrc
所以这个xml和vold.fstab的路径必须统一。
readStorageList函数通过解析xml,丰富了系统的分区信息。mVolumes、mVolumeMap和mPrimaryVolume。
2) intent 接收处理
privatefinal BroadcastReceiver mBroadcastReceiver = newBroadcastReceiver() {
String action = intent.getAction();
通过在构造函数中注册intentfilter,接收系统发出的intent,执行相应的动作。
3) Callback from NativeDaemonConnector
MountService注册到NativeDaemonConnector的两个回调函数:onDaemonConnected和onEvent。在构造函数创建NativeDaemonConnector时,将MountService植入进了NativeDaemonConnector。
onDaemonConnected在NativeDaemonConnector线程开始运行,创建socket监听时,执行一次。onEvent是在listenToSocket每次读取socket信息,然后通过mCallbackHandler发送消息,随后在handleMessage中调用onEvent。
当vold发生动作时,通过NativeDaemonConnector完成向上的通知。
NativeDaemonConnector和vold使用的是socket连接,大概使用流程如下:
{
LocalSocketsocket = null;
socket = newLocalSocket();//创建socket
//创建目的地的socket地址
LocalSocketAddress address = newLocalSocketAddress(mSocket,
LocalSocketAddress.Namespace.RESERVED);//mSocketà"vold"
socket.connect(address);//连接目的socket
InputStreaminputStream = socket.getInputStream()//获取inputStream
inputStream.read(buffer, start, BUFFER_SIZE -start);//读取socket数据
}
在init.rc中,vold服务启动时,创建与framework通讯的socket
service vold/system/bin/vold
classcore
socket vold stream 0660 rootmount
iopriobe 2
3)功能调用
如setUsbMassStorageEnabled,有其他功能直接调用。
mountVolume----àdoMountVolume-------àmConnector.execute(cmd);
1)定义变量
privateIMountService mMountService;
2)获取实例
mMountService =IMountService.Stub.asInterface(ServiceManager.getService("mount"));
3)调用功能
mMountService.registerListener(mBinderListener);
MountService是一个核心处理功能,承上启下。他的具体功能通过他提供的各种方法来体现。如何工作上面的工作流程已经涵盖。
参考文档:
http://terryblog.blog.51cto.com/1764499/826656
android系统vold透析
这两篇文章已经讲的很好,下面只是部分功能点的说明。
----------网友
kernel层能检测到有新的设备接入,加载相应的驱动,但如何通知用户层呢?这就是sysfs的工作,内核中的sysfs机制要求当有新的驱动加载时给用户层发送相应的event.但这些event只尽告知的义务,具体怎么处理,这就是vold的事了。
uevent由内核发出,通过netlinksokect来传递给vold,在kobject被创建的时候,就会发生uevent的传递。对于未传递的uevent,会在kset下产生uevent文件,这是供用户态触发uevent使用的,通过向uevent档写入action(add,remove等),可以触发一个uevent,这些uevent可以被vold捕获,从而完成未完成的vold处理。在系统启动的时候,vold未启动的时候,这些uevent写入了uevent档,vold启动后,会扫描sys目录查找uevent,然后触发它们,来完成之前未完成的事宜。uevent文件的内容,就是uevent事件的数据。
Vold.fstab文件中的设备路径是设备在sys下的路径,并不是kernel为该设备创建的节点:
dev_mount sdcard /storage/sdcard0 emmc@fat/devices/platform/goldfish_mmc.0
/devices/platform/mtk-msdc.0/mmc_host
#######################
## Regular devicemount
##
## Format: dev_mount
## label -Label for the volume
##mount_point - Where the volume will bemounted
##part - Partition # (1 based), or 'auto' for first usablepartition.
##
######################
Kernel 创建完设备节点后又再sys下创建了相关的内容,进而发出了uevent,让vold中的socket,NetLinkManager.cpp来处理,进而根据vold.fstab的配置挂载到指定的目录。那么kernel是如何将sys下创建的目录对象和具体的设备对应起来的呢?todo:sys
1)入口:System/vold/main.c
a)创建3个vold框架使用的对象
VolumeManager *vm;
CommandListener *cl; 接收上层MountService的命令,分析后转给volumeManager,处理后返给MountService或者交给volume执行具体操作。
NetlinkManager *nm;创建与内核通讯的socket,接收底层的信息,交给volumeManager
b)解析/etc/vold.fstab
process_config
2)netlinkManager
3) commandListener
4) volumeManager
分区管理类,volume.cpp代理人。真正的分区动作都在volume.cpp来完成。
5) 其他文件
Fat.cpp/bicr.cpp/Ext4.cpp
这些都是volume等配套的具体功能文件,最后一个环节。
2013-7-31:vold和kernel配合工作的流程:首先vold在开始执行时,通过解析vold.fstab得知了该设备用户层最终需要管理的存储设备分区信息,针对需要挂载的分区信息,创建对应的DirectVolume,放入VolumeManager中进行管理。解析vold.fstab时如果是emmc是要从/proc/emmc中获取信息的,以防止vold.fstab写的信息有误。所以上面这部分工作只是准备工作,意思是当有对应的分区设备在内核空间出现时,用户空间应该如何去处理,挂载还是不挂载,挂载点是哪里。那么当内核空间的设备创建时通过uevent机制传递到netlinkManager时,会调用到netlinkHandler.cpp的onEvent,进入调用VolumeManager的handleBlockEvent,意思是处理块设备变化,由于开始时已经将vold.fstab中的分区信息创建对应的DirectVolume添加到了VolumeManager容器中,然后找出容器中的某个DirectVolume执行handleBlockEvent。