Storage框架整理

一 storage功能相关模块

  • MountService.java

base/services/java/com/android/server/MountService.java

  • PackageManagerService.java

base/services/java/com/android/server/pm/PackageManagerService.java

  • StorageManager.java

base/core/java/android/os/storage/StorageManager.java

  • DefaultContainerService.java

base/packages/DefaultContainerService/src/com/android/defcontainer/

DefaultContainerService.java

  • Settings—storage/application

packages/apps/Settings/src/com/android/settings

  • Vold框架

system/vold

  • Kernel

二 StorageManager

2.1 方法/类/变量

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]

2.2 工作流程

应用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<ListenerDelegate> mListeners = newArrayList<ListenerDelegate>();

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状态相关处理

2.3 功能调用

上面介绍的是上层如何获取系统及底层信息的中断通知的方式,除了这种被动通知状态改变的行为以外,更多的则是应用主动的获取系统的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。

2.4 使用方法

mStorageManager=(StorageManager)context.getSystemService(Context.STORAGE_SERVICE);

mStorageManager.functions;

2.5 StorageManager总结

如果外界需要知道系统的storage信息,直接调用StorageManager的方法。那么如果需要实时的知道状态的改变,就需要派一个信使驻扎在StorageManager家里,当有状态变化时,StorageManager会通知驻扎在他家的信使,listener。这就是为什么要安排驻京人员,能够及时的拿到一手信息。

三 MountService

3.1 MountService与StorageManager的交互

紧接上面的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,进行更底层的操作。

------------------

3.2 工作流程

工作流程有几个:首先是构造函数的准备工作、一些接口的被调用、以及监听回调。

1)构造函数

Mediatek/custom/mt8389_tablet_a3v2/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml

<StorageListxmlns:android="http://schemas.android.com/apk/res/android">

<!-- removable is not set in nosdcard product-->

<storage android:mountPoint="/storage/sdcard0"

android:storageDescription="@string/storage_usb"

android:allowMassStorage="true"

android:mtpReserve="10485760"

android:primary="true"/>

<storage android:mountPoint="/storage/sdcard1"

android:storageDescription="@string/storage_sd_card"

android:removable="true"

android:allowMassStorage="true"

android:mtpReserve="10485760"

android:primary="false" />

<storageandroid:mountPoint="/mnt/usbotg"

android:storageDescription="@string/storage_external_usb"

android:removable="true"

android:primary="false"/>

</StorageList>

但是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);

3.3 使用方法

1)定义变量

privateIMountService mMountService;

2)获取实例

mMountService =IMountService.Stub.asInterface(ServiceManager.getService("mount"));

3)调用功能

mMountService.registerListener(mBinderListener);

3.4 MountService总结

MountService是一个核心处理功能,承上启下。他的具体功能通过他提供的各种方法来体现。如何工作上面的工作流程已经涵盖。

四 volumedemo

参考文档:

http://terryblog.blog.51cto.com/1764499/826656

android系统vold透析

这两篇文章已经讲的很好,下面只是部分功能点的说明。

4.1 vold/kernel简介

----------网友

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><mount_point><part><sysfs_path1...>

## label-Label for the volume

##mount_point - Where the volume will bemounted

##part- Partition # (1 based), or 'auto' for first usablepartition.

##<sysfs_path> - List of sysfs paths tosource devices

######################

Kernel 创建完设备节点后又再sys下创建了相关的内容,进而发出了uevent,让vold中的socket,NetLinkManager.cpp来处理,进而根据vold.fstab的配置挂载到指定的目录。那么kernel是如何将sys下创建的目录对象和具体的设备对应起来的呢?todo:sys

4.2 vold 代码流程

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。

更多相关文章

  1. 箭头函数的基础使用
  2. Python技巧匿名函数、回调函数和高阶函数
  3. Android(安卓)NDK打印log到logcat的方法
  4. androidの自定义加载对话框ProgressDialog
  5. Android图片剪裁-调用系统实现,完美适配魅族等机型
  6. android 动画
  7. android settings命令
  8. Android(安卓)根据Video绝对路径获取其缩略图
  9. Android隐藏标题栏,全屏显示

随机推荐

  1. Android(安卓)报错:Caused by: android.os
  2. Android使用Retrofit进行网络请求
  3. Android(安卓)给 app默认权限(不弹窗申请
  4. Android(安卓)触摸提示音
  5. android 复制、剪切、粘贴
  6. 细数Android(安卓)Studio中使用junit4测
  7. Android设置通知栏/状态栏透明改变通知栏
  8. Android(安卓)的 supportdesign
  9. Android(安卓)流式布局FlowLayout(搜索历
  10. Android的Handler机制详解3_Looper.loope