Android 一直在不断发展,可支持各种存储设备类型和功能。所有 Android 版本均支持配有传统存储(包括便携式存储和内置存储)的设备。便携式存储是指物理介质(如 SD 卡或 USB 设备),用于进行临时数据传输/文件存储。物理介质可以随设备一起保留更长时间,但并非固定在设备上,可以移除。自 Android 1.0 开始,SD 卡已可用作便携式存储;Android 6.0 增加对 USB 的支持。“内置”存储可通过将部分内部存储暴露于模拟层来实现存储,并且从 Android 3.0 开始便已支持此功能。
1. 后台进程Vold启动
system\vold\main.cpp
int main ( int argc, char * * argv) {
VolumeManager * vm;
CommandListener * cl;
CryptCommandListener * ccl;
NetlinkManager * nm;
parse_args ( argc, argv) ;
sehandle = selinux_android_file_context_handle ( ) ;
if ( sehandle) { selinux_android_set_sehandle ( sehandle) ; }
fcntl ( android_get_control_socket ( "vold" ) , F_SETFD, FD_CLOEXEC) ;
fcntl ( android_get_control_socket ( "cryptd" ) , F_SETFD, FD_CLOEXEC) ;
mkdir ( "/dev/block/vold" , 0755 ) ;
if ( ! ( vm = VolumeManager:: Instance ( ) ) ) { exit ( 1 ) ; }
if ( ! ( nm = NetlinkManager:: Instance ( ) ) ) { exit ( 1 ) ; }
cl = new CommandListener ( ) ;
ccl = new CryptCommandListener ( ) ;
vm- > setBroadcaster ( ( SocketListener * ) cl) ;
nm- > setBroadcaster ( ( SocketListener * ) cl) ;
if ( vm- > start ( ) ) { exit ( 1 ) ; }
if ( process_config ( vm, & has_adoptable) ) { }
if ( nm- > start ( ) ) { exit ( 1 ) ; }
if ( cl- > startListener ( ) ) { exit ( 1 ) ; }
if ( ccl- > startListener ( ) ) { exit ( 1 ) ; }
property_set ( "vold.has_adoptable" , has_adoptable ? "1" : "0" ) ;
coldboot ( "/sys/block" ) ;
while ( 1 ) { pause ( ) ; }
exit ( 0 ) ;
}
2. CommandListener 与 VolumeManager
system\vold\CommandListener.cpp
注册一系列命令,这些Cmd均继承自VoldCommand,VoldCommand继承自FrameworkCommand
CommandListener:: CommandListener ( ) :
FrameworkListener ( "vold" , true ) {
registerCmd ( new DumpCmd ( ) ) ;
registerCmd ( new VolumeCmd ( ) ) ;
registerCmd ( new AsecCmd ( ) ) ;
registerCmd ( new ObbCmd ( ) ) ;
registerCmd ( new StorageCmd ( ) ) ;
registerCmd ( new FstrimCmd ( ) ) ;
registerCmd ( new AppFuseCmd ( ) ) ;
}
system\core\libsysutils\src\FrameworkListener.cpp
FrameworkListener:: FrameworkListener ( const char * socketName, bool withSeq) :
SocketListener ( socketName, true , withSeq) {
init ( socketName, withSeq) ;
}
system\core\libsysutils\src\SocketListener.cpp
SocketListener:: SocketListener ( const char * socketName, bool listen) {
init ( socketName, - 1 , listen, false ) ;
}
system\core\libsysutils\src\SocketListener.cpp
mClient 是一个List定义在SocketClient.h
void SocketListener:: init ( const char * socketName, int socketFd, bool listen, bool useCmdNum) {
mListen = listen;
mSocketName = socketName;
mSock = socketFd;
mUseCmdNum = useCmdNum;
pthread_mutex_init ( & mClientsLock, NULL ) ;
mClients = new SocketClientCollection ( ) ;
}
system\vold\CryptCommandListener.cpp
加密监听也是一样的
FrameworkListener ( "cryptd" , true ) {
registerCmd ( new CryptfsCmd ( ) ) ;
}
system\vold\VolumeManager.h
system\vold\NetlinkManager.h
void setBroadcaster ( SocketListener * sl) { mBroadcaster = sl; }
system\vold\VolumeManager.cpp
int VolumeManager:: start ( ) {
unmountAll ( ) ;
CHECK ( mInternalEmulated == nullptr ) ;
mInternalEmulated = std:: shared_ptr< android:: vold:: VolumeBase> (
new android:: vold:: EmulatedVolume ( "/data/media" ) ) ;
mInternalEmulated- > create ( ) ;
updateVirtualDisk ( ) ;
return 0 ;
}
system\core\libsysutils\src\SocketListener.cpp
启动加密,和命令监听
int SocketListener:: startListener ( ) {
return startListener ( 4 ) ;
}
system\core\libsysutils\src\SocketListener.cpp
int SocketListener:: startListener ( int backlog) {
if ( ! mSocketName && mSock == - 1 ) {
errno = EINVAL;
return - 1 ;
} else if ( mSocketName) {
if ( ( mSock = android_get_control_socket ( mSocketName) ) < 0 ) {
return - 1 ;
}
fcntl ( mSock, F_SETFD, FD_CLOEXEC) ;
}
if ( mListen && listen ( mSock, backlog) < 0 ) {
return - 1 ;
} else if ( ! mListen) {
mClients- > push_back ( new SocketClient ( mSock, false , mUseCmdNum) ) ;
}
if ( pipe ( mCtrlPipe) ) { return - 1 ; }
if ( pthread_create ( & mThread, NULL , SocketListener:: threadStart, this ) ) { return - 1 ; }
return 0 ;
}
system\core\libsysutils\src\SocketListener.cpp
void * SocketListener:: threadStart ( void * obj) {
SocketListener * me = reinterpret_cast < SocketListener * > ( obj) ;
me- > runListener ( ) ;
pthread_exit ( NULL ) ;
return NULL ;
}
system\core\libsysutils\src\SocketListener.cpp
开始循环监听
void SocketListener:: runListener ( ) {
SocketClientCollection pendingList;
while ( 1 ) {
SocketClientCollection:: iterator it;
fd_set read_fds;
int rc = 0 ;
int max = - 1 ;
FD_ZERO ( & read_fds) ;
if ( mListen) {
max = mSock;
FD_SET ( mSock, & read_fds) ;
}
FD_SET ( mCtrlPipe[ 0 ] , & read_fds) ;
if ( mCtrlPipe[ 0 ] > max)
max = mCtrlPipe[ 0 ] ;
pthread_mutex_lock ( & mClientsLock) ;
for ( it = mClients- > begin ( ) ; it != mClients- > end ( ) ; ++ it) {
int fd = ( * it) - > getSocket ( ) ;
FD_SET ( fd, & read_fds) ;
if ( fd > max) {
max = fd;
}
}
pthread_mutex_unlock ( & mClientsLock) ;
if ( ( rc = select ( max + 1 , & read_fds, NULL , NULL , NULL ) ) < 0 ) {
if ( errno == EINTR)
continue ;
SLOGE ( "select failed (%s) mListen=%d, max=%d" , strerror ( errno) , mListen, max) ;
sleep ( 1 ) ;
continue ;
} else if ( ! rc)
continue ;
. . . . . .
while ( ! pendingList. empty ( ) ) {
it = pendingList. begin ( ) ;
SocketClient* c = * it;
pendingList. erase ( it) ;
if ( ! onDataAvailable ( c) ) {
release ( c, false ) ;
}
c- > decRef ( ) ;
}
}
}
system\core\libsysutils\src\FrameworkListener.cpp
由子类实现的onDataAvailable函数处理
bool FrameworkListener:: onDataAvailable ( SocketClient * c) {
char buffer[ CMD_BUF_SIZE] ;
int len;
len = TEMP_FAILURE_RETRY ( read ( c- > getSocket ( ) , buffer, sizeof ( buffer) ) ) ;
if ( len < 0 ) {
return false ;
} else if ( ! len) {
return false ;
} else if ( buffer[ len- 1 ] != '\0' ) {
android_errorWriteLog ( 0x534e4554 , "29831647" ) ;
c- > sendMsg ( 500 , "Command too large for buffer" , false ) ;
mSkipToNextNullByte = true ;
return false ;
}
int offset = 0 ;
int i;
for ( i = 0 ; i < len; i++ ) {
if ( buffer[ i] == '\0' ) {
if ( mSkipToNextNullByte) {
mSkipToNextNullByte = false ;
} else {
dispatchCommand ( c, buffer + offset) ;
}
offset = i + 1 ;
}
}
mSkipToNextNullByte = false ;
return true ;
}
system\core\libsysutils\src\FrameworkListener.cpp
由FrameworkCommand的子孙类去执行命令
void FrameworkListener:: dispatchCommand ( SocketClient * cli, char * data) {
. . . . .
FrameworkCommandCollection:: iterator i;
for ( i = mCommands- > begin ( ) ; i != mCommands- > end ( ) ; ++ i) {
FrameworkCommand * c = * i;
if ( ! strcmp ( argv[ 0 ] , c- > getCommand ( ) ) ) {
if ( c- > runCommand ( cli, argc, argv) ) {
SLOGW ( "Handler '%s' error (%s)" , c- > getCommand ( ) , strerror ( errno) ) ;
}
goto out;
}
}
. . . . . .
}
system\vold\CommandListener.cpp
处理来自上层系统的命令,挂载,监听
CommandListener:: VolumeCmd:: VolumeCmd ( ) :
VoldCommand ( "volume" ) {
}
int CommandListener:: VolumeCmd:: runCommand ( SocketClient * cli,
int argc, char * * argv) {
VolumeManager * vm = VolumeManager:: Instance ( ) ;
std:: lock_guard< std:: mutex> lock ( vm- > getLock ( ) ) ;
std:: string cmd ( argv[ 1 ] ) ;
if ( cmd == "reset" ) {
return sendGenericOkFail ( cli, vm- > reset ( ) ) ;
} else if ( cmd == "shutdown" ) {
return sendGenericOkFail ( cli, vm- > shutdown ( ) ) ;
} else if ( cmd == "debug" ) {
return sendGenericOkFail ( cli, vm- > setDebug ( true ) ) ;
} else if ( cmd == "partition" && argc > 3 ) {
std:: string id ( argv[ 2 ] ) ;
auto disk = vm- > findDisk ( id) ;
if ( disk == nullptr ) {
return cli- > sendMsg ( ResponseCode:: CommandSyntaxError, "Unknown disk" , false ) ;
}
std:: string type ( argv[ 3 ] ) ;
if ( type == "public" ) {
return sendGenericOkFail ( cli, disk- > partitionPublic ( ) ) ;
} else if ( type == "private" ) {
return sendGenericOkFail ( cli, disk- > partitionPrivate ( ) ) ;
} else if ( type == "mixed" ) {
if ( argc < 4 ) {
return cli- > sendMsg ( ResponseCode:: CommandSyntaxError, nullptr , false ) ;
}
int frac = atoi ( argv[ 4 ] ) ;
return sendGenericOkFail ( cli, disk- > partitionMixed ( frac) ) ;
} else {
return cli- > sendMsg ( ResponseCode:: CommandSyntaxError, nullptr , false ) ;
}
} else if ( cmd == "mkdirs" && argc > 2 ) {
return sendGenericOkFail ( cli, vm- > mkdirs ( argv[ 2 ] ) ) ;
} else if ( cmd == "user_added" && argc > 3 ) {
return sendGenericOkFail ( cli, vm- > onUserAdded ( atoi ( argv[ 2 ] ) , atoi ( argv[ 3 ] ) ) ) ;
} else if ( cmd == "user_removed" && argc > 2 ) {
return sendGenericOkFail ( cli, vm- > onUserRemoved ( atoi ( argv[ 2 ] ) ) ) ;
} else if ( cmd == "user_started" && argc > 2 ) {
return sendGenericOkFail ( cli, vm- > onUserStarted ( atoi ( argv[ 2 ] ) ) ) ;
} else if ( cmd == "user_stopped" && argc > 2 ) {
return sendGenericOkFail ( cli, vm- > onUserStopped ( atoi ( argv[ 2 ] ) ) ) ;
} else if ( cmd == "mount" && argc > 2 ) {
std:: string id ( argv[ 2 ] ) ;
auto vol = vm- > findVolume ( id) ;
if ( vol == nullptr ) {
return cli- > sendMsg ( ResponseCode:: CommandSyntaxError, "Unknown volume" , false ) ;
}
int mountFlags = ( argc > 3 ) ? atoi ( argv[ 3 ] ) : 0 ;
userid_t mountUserId = ( argc > 4 ) ? atoi ( argv[ 4 ] ) : - 1 ;
vol- > setMountFlags ( mountFlags) ;
vol- > setMountUserId ( mountUserId) ;
int res = vol- > mount ( ) ;
if ( mountFlags & android:: vold:: VolumeBase:: MountFlags:: kPrimary) {
vm- > setPrimary ( vol) ;
}
return sendGenericOkFail ( cli, res) ;
} else if ( cmd == "unmount" && argc > 2 ) {
std:: string id ( argv[ 2 ] ) ;
auto vol = vm- > findVolume ( id) ;
if ( vol == nullptr ) {
return cli- > sendMsg ( ResponseCode:: CommandSyntaxError, "Unknown volume" , false ) ;
}
return sendGenericOkFail ( cli, vol- > unmount ( ) ) ;
} else if ( cmd == "format" && argc > 3 ) {
std:: string id ( argv[ 2 ] ) ;
std:: string fsType ( argv[ 3 ] ) ;
auto vol = vm- > findVolume ( id) ;
if ( vol == nullptr ) {
return cli- > sendMsg ( ResponseCode:: CommandSyntaxError, "Unknown volume" , false ) ;
}
return sendGenericOkFail ( cli, vol- > format ( fsType) ) ;
} else if ( cmd == "move_storage" && argc > 3 ) {
auto fromVol = vm- > findVolume ( std:: string ( argv[ 2 ] ) ) ;
auto toVol = vm- > findVolume ( std:: string ( argv[ 3 ] ) ) ;
if ( fromVol == nullptr || toVol == nullptr ) {
return cli- > sendMsg ( ResponseCode:: CommandSyntaxError, "Unknown volume" , false ) ;
}
( new android:: vold:: MoveTask ( fromVol, toVol) ) - > start ( ) ;
return sendGenericOkFail ( cli, 0 ) ;
} else if ( cmd == "benchmark" && argc > 2 ) {
std:: string id ( argv[ 2 ] ) ;
nsecs_t res = vm- > benchmarkPrivate ( id) ;
return cli- > sendMsg ( ResponseCode:: CommandOkay,
android:: base:: StringPrintf ( "%" PRId64, res) . c_str ( ) , false ) ;
} else if ( cmd == "forget_partition" && argc > 2 ) {
std:: string partGuid ( argv[ 2 ] ) ;
return sendGenericOkFail ( cli, vm- > forgetPartition ( partGuid) ) ;
} else if ( cmd == "remount_uid" && argc > 3 ) {
uid_t uid = atoi ( argv[ 2 ] ) ;
std:: string mode ( argv[ 3 ] ) ;
return sendGenericOkFail ( cli, vm- > remountUid ( uid, mode) ) ;
}
return cli- > sendMsg ( ResponseCode:: CommandSyntaxError, nullptr , false ) ;
}
system\core\libsysutils\src\SocketClient.cpp
int SocketClient:: sendMsg ( int code, const char * msg, bool addErrno) {
return sendMsg ( code, msg, addErrno, mUseCmdNum) ;
}
int SocketClient:: sendMsg ( int code, const char * msg, bool addErrno, bool useCmdNum) {
char * buf;
int ret = 0 ;
if ( addErrno) {
if ( useCmdNum) {
ret = asprintf ( & buf, "%d %d %s (%s)" , code, getCmdNum ( ) , msg, strerror ( errno) ) ;
} else {
ret = asprintf ( & buf, "%d %s (%s)" , code, msg, strerror ( errno) ) ;
}
} else {
if ( useCmdNum) {
ret = asprintf ( & buf, "%d %d %s" , code, getCmdNum ( ) , msg) ;
} else {
ret = asprintf ( & buf, "%d %s" , code, msg) ;
}
}
if ( ret != - 1 ) {
ret = sendMsg ( buf) ;
free ( buf) ;
}
return ret;
}
system\core\libsysutils\src\SocketClient.cpp
int SocketClient:: sendMsg ( const char * msg) {
if ( sendData ( msg, strlen ( msg) + 1 ) != 0 ) {
SLOGW ( "Unable to send msg '%s'" , msg) ;
return - 1 ;
}
return 0 ;
}
int SocketClient:: sendData ( const void * data, int len) {
struct iovec vec[ 1 ] ;
vec[ 0 ] . iov_base = ( void * ) data;
vec[ 0 ] . iov_len = len;
pthread_mutex_lock ( & mWriteMutex) ;
int rc = sendDataLockedv ( vec, 1 ) ;
pthread_mutex_unlock ( & mWriteMutex) ;
return rc;
}
system\core\libsysutils\src\SocketClient.cpp
向上层系统返回执行结果
int SocketClient:: sendDataLockedv ( struct iovec * iov, int iovcnt) {
if ( mSocket < 0 ) {
errno = EHOSTUNREACH;
return - 1 ;
}
if ( iovcnt <= 0 ) {
return 0 ;
}
int ret = 0 ;
int e = 0 ;
int current = 0 ;
struct sigaction new_action, old_action;
memset ( & new_action, 0 , sizeof ( new_action) ) ;
new_action. sa_handler = SIG_IGN;
sigaction ( SIGPIPE, & new_action, & old_action) ;
for ( ; ; ) {
ssize_t rc = TEMP_FAILURE_RETRY (
writev ( mSocket, iov + current, iovcnt - current) ) ;
if ( rc > 0 ) {
size_t written = rc;
while ( ( current < iovcnt) && ( written >= iov[ current] . iov_len) ) {
written - = iov[ current] . iov_len;
current++ ;
}
if ( current == iovcnt) {
break ;
}
iov[ current] . iov_base = ( char * ) iov[ current] . iov_base + written;
iov[ current] . iov_len - = written;
continue ;
}
if ( rc == 0 ) {
e = EIO;
SLOGW ( "0 length write :(" ) ;
} else {
e = errno;
SLOGW ( "write error (%s)" , strerror ( e) ) ;
}
ret = - 1 ;
break ;
}
sigaction ( SIGPIPE, & old_action, & new_action) ;
if ( e != 0 ) {
errno = e;
}
return ret;
}
3. NetLinkManager与VolumeManager
system\vold\NetlinkManager.cpp
启动监听来自内核的事件
int NetlinkManager:: start ( ) {
struct sockaddr_nl nladdr;
int sz = 64 * 1024 ;
int on = 1 ;
memset ( & nladdr, 0 , sizeof ( nladdr) ) ;
nladdr. nl_family = AF_NETLINK;
nladdr. nl_pid = getpid ( ) ;
nladdr. nl_groups = 0xffffffff ;
if ( ( mSock = socket ( PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC,
NETLINK_KOBJECT_UEVENT) ) < 0 ) { return - 1 ; }
if ( setsockopt ( mSock, SOL_SOCKET, SO_RCVBUFFORCE, & sz, sizeof ( sz) ) < 0 ) { goto out; }
if ( setsockopt ( mSock, SOL_SOCKET, SO_PASSCRED, & on, sizeof ( on) ) < 0 ) { goto out; }
if ( bind ( mSock, ( struct sockaddr * ) & nladdr, sizeof ( nladdr) ) < 0 ) { goto out; }
mHandler = new NetlinkHandler ( mSock) ;
if ( mHandler- > start ( ) ) { goto out; }
return 0 ;
}
system\vold\NetlinkHandler.cpp
int NetlinkHandler:: start ( ) {
return this - > startListener ( ) ;
}
system\core\libsysutils\src\NetlinkListener.cpp
按照上面的分析最终会走到 onDataAvailable
bool NetlinkListener:: onDataAvailable ( SocketClient * cli)
{
int socket = cli- > getSocket ( ) ;
ssize_t count;
uid_t uid = - 1 ;
bool require_group = true ;
if ( mFormat == NETLINK_FORMAT_BINARY_UNICAST) {
require_group = false ;
}
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) ;
} else if ( mFormat != NETLINK_FORMAT_BINARY) {
SLOGE ( "Error decoding NetlinkEvent" ) ;
}
delete evt;
return true ;
}
system\vold\NetlinkHandler.cpp
void NetlinkHandler:: onEvent ( NetlinkEvent * evt) {
VolumeManager * vm = VolumeManager:: Instance ( ) ;
const char * subsys = evt- > getSubsystem ( ) ;
if ( ! strcmp ( subsys, "block" ) ) {
vm- > handleBlockEvent ( evt) ;
}
}
system\vold\VolumeManager.cpp
处理来自NetLinkManager的阻塞事件
void VolumeManager:: handleBlockEvent ( NetlinkEvent * evt) {
std:: lock_guard< std:: mutex> lock ( mLock) ;
std:: string eventPath ( evt- > findParam ( "DEVPATH" ) ? evt- > findParam ( "DEVPATH" ) : "" ) ;
std:: string devType ( evt- > findParam ( "DEVTYPE" ) ? evt- > findParam ( "DEVTYPE" ) : "" ) ;
int major = atoi ( evt- > findParam ( "MAJOR" ) ) ;
int minor = atoi ( evt- > findParam ( "MINOR" ) ) ;
dev_t device = makedev ( major, minor) ;
switch ( evt- > getAction ( ) ) {
case NetlinkEvent:: Action:: kAdd: {
for ( const auto & source : mDiskSources) {
if ( source- > matches ( eventPath) ) {
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) ;
disk- > create ( ) ;
mDisks. push_back ( std:: shared_ptr< android:: vold:: Disk> ( disk) ) ;
break ;
}
}
break ;
}
case NetlinkEvent:: Action:: kChange: {
LOG ( DEBUG) << "Disk at " << major << ":" << minor << " changed" ;
for ( const auto & disk : mDisks) {
if ( disk- > getDevice ( ) == device) {
disk- > readMetadata ( ) ;
disk- > readPartitions ( ) ;
}
}
break ;
}
case NetlinkEvent:: Action:: kRemove: {
auto i = mDisks. begin ( ) ;
while ( i != mDisks. end ( ) ) {
if ( ( * i) - > getDevice ( ) == device) {
( * i) - > destroy ( ) ;
i = mDisks. erase ( i) ;
} else {
++ i;
}
}
break ;
}
default : {
LOG ( WARNING) << "Unexpected block event action " << ( int ) evt- > getAction ( ) ;
break ;
}
}
}
4. StorageMangerService
在Android8.0中MountService改名为StorageMangerService
frameworks\base\services\core\java\com\android\server\StorageManagerService.java
public StorageManagerService ( Context context) {
sSelf = this ;
mContext = context;
mCallbacks = new Callbacks ( FgThread. get ( ) . getLooper ( ) ) ;
mLockPatternUtils = new LockPatternUtils ( mContext) ;
mPms = ( PackageManagerService) ServiceManager. getService ( "package" ) ;
HandlerThread hthread = new HandlerThread ( TAG) ;
hthread. start ( ) ;
mHandler = new StorageManagerServiceHandler ( hthread. getLooper ( ) ) ;
mConnector = new NativeDaemonConnector ( this , "vold" , MAX_CONTAINERS * 2 , VOLD_TAG, 25 ,
null) ;
mConnector. setDebug ( true ) ;
mConnector. setWarnIfHeld ( mLock) ;
mConnectorThread = new Thread ( mConnector, VOLD_TAG) ;
. . . . . .
synchronized ( mLock) {
addInternalVolumeLocked ( ) ;
}
}
frameworks\base\services\core\java\com\android\server\NativeDaemonConnector.java
NativeDaemonConnector ( INativeDaemonConnectorCallbacks callbacks, String socket,
int responseQueueSize, String logTag, int maxLogSize, PowerManager. WakeLock wl) {
this ( callbacks, socket, responseQueueSize, logTag, maxLogSize, wl,
FgThread. get ( ) . getLooper ( ) ) ;
}
NativeDaemonConnector ( INativeDaemonConnectorCallbacks callbacks, String socket,
int responseQueueSize, String logTag, int maxLogSize, PowerManager. WakeLock wl,
Looper looper) {
mCallbacks = callbacks;
mSocket = socket;
mResponseQueue = new ResponseQueue ( responseQueueSize) ;
mWakeLock = wl;
if ( mWakeLock != null) {
mWakeLock. setReferenceCounted ( true ) ;
}
mLooper = looper;
mSequenceNumber = new AtomicInteger ( 0 ) ;
TAG = logTag != null ? logTag : "NativeDaemonConnector" ;
mLocalLog = new LocalLog ( maxLogSize) ;
}
frameworks\base\services\core\java\com\android\server\NativeDaemonConnector.java
@Override
public void run ( ) {
mCallbackHandler = new Handler ( mLooper, this ) ;
while ( true ) {
try {
listenToSocket ( ) ;
} catch ( Exception e) {
loge ( "Error in NativeDaemonConnector: " + e) ;
SystemClock. sleep ( 5000 ) ;
}
}
}
frameworks\base\services\core\java\com\android\server\NativeDaemonConnector.java
监听来自Vold的事件
private void listenToSocket ( ) throws IOException {
LocalSocket socket = null;
try {
socket = new LocalSocket ( ) ;
LocalSocketAddress address = determineSocketAddress ( ) ;
socket. connect ( address) ;
InputStream inputStream = socket. getInputStream ( ) ;
synchronized ( mDaemonLock) {
mOutputStream = socket. getOutputStream ( ) ;
}
mCallbacks. onDaemonConnected ( ) ;
FileDescriptor[ ] fdList = null;
byte [ ] buffer = new byte [ BUFFER_SIZE] ;
int start = 0 ;
while ( true ) {
int count = inputStream. read ( buffer, start, BUFFER_SIZE - start) ;
if ( count < 0 ) {
loge ( "got " + count + " reading with start = " + start) ;
break ;
}
fdList = socket. getAncillaryFileDescriptors ( ) ;
count += start;
start = 0 ;
for ( int i = 0 ; i < count; i++ ) {
if ( buffer[ i] == 0 ) {
final String rawEvent = new String (
buffer, start, i - start, StandardCharsets. UTF_8) ;
boolean releaseWl = false ;
try {
final NativeDaemonEvent event =
NativeDaemonEvent. parseRawEvent ( rawEvent, fdList) ;
if ( event. isClassUnsolicited ( ) ) {
if ( mCallbacks. onCheckHoldWakeLock ( event. getCode ( ) )
&& mWakeLock != null) {
mWakeLock. acquire ( ) ;
releaseWl = true ;
}
Message msg = mCallbackHandler. obtainMessage (
event. getCode ( ) , uptimeMillisInt ( ) , 0 , event. getRawEvent ( ) ) ;
if ( mCallbackHandler. sendMessage ( msg) ) {
releaseWl = false ;
}
} else {
mResponseQueue. add ( event. getCmdNumber ( ) , event) ;
}
} catch ( IllegalArgumentException e) {
log ( "Problem parsing message " + e) ;
} finally {
if ( releaseWl) {
mWakeLock. release ( ) ;
}
}
start = i + 1 ;
}
}
. . . . .
}
} catch ( IOException ex) {
loge ( "Communications error: " + ex) ;
throw ex;
} finally {
. . . . . .
}
try {
if ( socket != null) {
socket. close ( ) ;
}
} catch ( IOException ex) {
loge ( "Failed closing socket: " + ex) ;
}
}
}
frameworks\base\services\core\java\com\android\server\NativeDaemonConnector.java
处理内核事件,实际上转发给了StorageManagerService.java
@Override
public boolean handleMessage ( Message msg) {
final String event = ( String) msg. obj;
final int start = uptimeMillisInt ( ) ;
final int sent = msg. arg1;
try {
if ( ! mCallbacks. onEvent ( msg. what, event, NativeDaemonEvent. unescapeArgs ( event) ) ) {
log ( String. format ( "Unhandled event '%s'" , event) ) ;
}
} catch ( Exception e) {
loge ( "Error handling '" + event + "': " + e) ;
} finally {
. . . . . .
}
return true ;
}
frameworks\base\services\core\java\com\android\server\StorageManagerService.java
处理和转发来自Vold的事件
@Override
public boolean onEvent ( int code, String raw, String[ ] cooked) {
synchronized ( mLock) {
return onEventLocked ( code, raw, cooked) ;
}
}
private boolean onEventLocked ( int code, String raw, String[ ] cooked) {
switch ( code) {
case VoldResponseCode. DISK_CREATED: {
. . . . . .
mDisks. put ( id, new DiskInfo ( id, flags) ) ;
break ;
}
. . . . . .
default : {
Slog. d ( TAG, "Unhandled vold event " + code) ;
}
}
return true ;
}
从 Android 6.0 开始,Android 支持可合并的存储设备,这种存储设备是指可以像内部存储设备那样进行加密和格式化的物理介质(例如 SD 卡或 USB 设备)。移动存储设备可存储各类应用数据。