浏览 3108 次
锁定老帖子 主题:MeidaProvider 流程学习笔记
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2013-08-29
参考代码: ./packages/providers/MediaProvider/src/com/android/providers/media/ MediaProvider.java MediaScannerReceiver.java MediaScannerService.java MediaUpgradeReceiver.java MtpReceiver.java MtpService.java ./frameworks/base/media/java/android/media/ MediaScanner.java ./frameworks/base/media/java/android/mtp/ MtpDatabase.java MtpServer.java MtpStorage.java MtpStorageInfo.java ./frameworks/base/media/jni/ android_media_MediaScanner.cpp android_mtp_MtpDatabase.cpp android_mtp_MtpServer.cpp ./frameworks/av/media/mtp/ MtpServer.h MtpServer.cpp MediaProvider主要用于创建媒体库的数据库表。对它的流程理解主要分为MTP流程、MediaScanner流程以及MediaProvider本身流程。 关于MeidaScanner和MediaProvider网上有较多的解释,这里主要说一下MTP的流程。 MTP流程 MediaProvider通过MtpReceiver(MtpReceiver.java::onReceive,31~42)建立了对于Usb接口的关联,一旦接收到usbState状态变化,则调用handleUsbState函数(MtpReceiver::handleUsbState,44~65),一旦发现UsbState是MTP(Media Transfer Protocal)或者是PTP(Picture Transfer Protocal)时就会启动MtpService服务(MtpService.java)。在MTPService中又建立了对于StorageEvent的监听,一旦Storage有Event发生,MtpServer(MtpServer.java)和MtpDatabase(MtpDataBase.java)函数就会被响应,具体看函数代码(MtpService.java::addStorageLocked 254~266) private void addStorageLocked(StorageVolume volume) { ... if (mDatabase != null) { //MtpDatabase添加存储数据信息 1 mDatabase.addStorage(storage); } if (mServer != null) { //mServer添加存储数据信息 2 mServer.addStorage(storage); } } 1 中只是建立了一个关于数据路径到数据的Map映射,关键还是看2 在2中唤起了一个native 函数android_mtp_MtpServer_add_storage,并由该函数调用MtpServer.cpp中的addStorage方法(android_mtp_MtpServer.cpp::120~150) static void android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) { ... server->addStorage(storage); ... } 通过该方法由sendStoreAdded(storage->getStorageID()); //MtpServer.cpp::addStorage ,121行 发出一个MTP_EVENT_STORE_ADDED事件(MtpServer.cpp:: sendStoreAdded ,255~258行) void MtpServer::sendStoreAdded(MtpStorageID id) { ALOGV("sendStoreAdded %08X\n", id); sendEvent(MTP_EVENT_STORE_ADDED, id); } 由MtpServer的run接收到该Event后通过handleRequest函数分发执行该事 件响应(MtpServer.java:: run 153~228) 。 void MtpServer::run() { ... if (handleRequest()) {...} ... } 触发doSendObjectInfo(MtpResponseCode MtpServer::doSendObjectInfo 818~923),在该函数中MtpDatabase.beginSendObject函数被调用。 MtpResponseCode MtpServer::doSendObjectInfo() { ... MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, format, parent, storageID, mSendObjectFileSize, modifiedTime); ... } 从而在 doSendObjectInfo中MediaProvider插入该数据信息(MtpDatabase.java::doSendObjectInfo 206~304行) private int beginSendObject(String path, int format, int parent, int storageId, long size, long modified) { ... Uri uri = mMediaProvider.insert(mPackageName, mObjectsUri, values); ... } 同样,在MtpService.java中还有一个removeStorage 事件(MtpService.java::removeStorage 268~282) private void removeStorageLocked(StorageVolume volume) { ... if (mDatabase != null) { mDatabase.removeStorage(storage); } if (mServer != null) { mServer.removeStorage(storage); } } 由该函数唤起了native的android_mtp_MtpServer_remove_storage方法(android_mtp_MtpServer.cpp, 152~166) static void android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId) { ... server->removeStorage(storage); ... } ,过渡到MtpServer.cpp中的removeStorage函数(124~134) void MtpServer::removeStorage(MtpStorage* storage) { Mutex::Autolock autoLock(mMutex); ... sendStoreRemoved(storage->getStorageID()); ... } ,并通过sendStoreRemoved函数触发MTP_EVENT_STORE_REMOVED事件,并由run函数接收到该事件后handleRequest到doSendObject函数中,并在该函 数最后调用mDatabase->endSendObjec去通知MediaScanner,canMtpFile。 MtpServer.cpp 915~986 MtpResponseCode MtpServer::doSendObject() { ... done: // reset so we don't attempt to send the data back mData.reset(); mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, result == MTP_RESPONSE_OK); ... } MtpDatabase.java 306~340 private void endSendObject(String path, int handle, int format, boolean succeeded) { ... mMediaScanner.scanMtpFile(path, mVolumeName, handle, format); ... } 可参考:http://blog.csdn.net/innost/article/details/8876392 MediaScanner流程 这块的内容太多了,我就不具体介绍,需要的请参考 http://wenku.baidu.com/view/9151d3d349649b6648d747d2.html 和 深入理解Android 卷1 第10章 这里紧接着上面的函数,当MtpDatabase:: endSendObject执行了mMediaScanner.scanMtpFile函数后,便会由scanMtpFile函数通过MediaFile的类型判断,通知是否去执行MediaProvider的update操作。 MediaScanner.java 1477~1530行 public void scanMtpFile(String path, String volumeName, int objectHandle, int format) { … if (!MediaFile.isAudioFileType(fileType) && !MediaFile.isVideoFileType(fileType) && !MediaFile.isImageFileType(fileType) && !MediaFile.isPlayListFileType(fileType)) { ... mMediaProvider.update(Files.getMtpObjectsUri(volumeName), values, "_id=?", whereArgs); ... } 注:深入理解Android 卷1 第10章 图10-2MediaScanner扫描流程图将该过程归 纳的很详细,建议看一下。 与这个动作保持平行的是开机启动时,会由系统调用MediaScanner执行一次scanFile操作(MeidaScanner.java::scanFile 531~536行),并通过doScanFile函数中的endFile方法去判定是应该执行MediaProvider的update还是insert操作。 MediaProvider 流程 关于MediaProvider,虽然代码较多,但是主要还是对于媒体数据库的操作以及通知MediaScanner扫描文件信息。 具体可参考http://blog.csdn.net/evilcode/article/details/6321803 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |