Android 2.3 SD卡挂载流程浅析(6)

(3).继续探索getStorageManager()

继续跟踪getStorageManager()方法我们会看到:

    private StorageManager getStorageManager() {           synchronized (mSync) {               if (mStorageManager == null) {                   try {                       mStorageManager = new StorageManager(mMainThread.getHandler().getLooper());                   } catch (RemoteException rex) {                       Log.e(TAG, "Failed to create StorageManager", rex);                       mStorageManager = null;                   }               }           }           return mStorageManager;       }

通过该方法可以看到,返回的是一个StorageManager对象。但我们需要关注的是StorageManager(mMainThread.getHandler().getLooper())在这个方法中传递的参数是ActivityThread的handler中的looper。继续跟踪此方法就可以来到StorageManager的带参构造函数:

    public StorageManager(Looper tgtLooper) throws RemoteException {           mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));           if (mMountService == null) {               Log.e(TAG, "Unable to connect to mount service! - is it running yet?");               return;           }           mTgtLooper = tgtLooper;           mBinderListener = new MountServiceBinderListener();           mMountService.registerListener(mBinderListener);       }

在该方法中,首先初始化了IMountService的对象,因为目前自己对Binder这一块还不是很熟悉,因此只能凭借自己的理解来分析。我们先去看看ServiceManager.getService("mount")方法:

    public static IBinder getService(String name) {           try {               IBinder service = sCache.get(name);               if (service != null) {                   return service;               } else {                   return getIServiceManager().getService(name);               }           } catch (RemoteException e) {               Log.e(TAG, "error in getService", e);           }           return null;       } 

“该方法将返回一个服务的引用,这个服务的名称就是我们传递进去的参数名称。如果这个服务不存在的话将返回null。”源码注释里面是这么说的,但我们就从代码中可以知道,实际上返回的是一个IBinder的对象。

接着调用回到StorageManager的构造函数中的??IMountService.Stub.asInterface()方法:

        public static IMountService asInterface(IBinder obj) {               if (obj == null) {                   return null;               }               IInterface iin = obj.queryLocalInterface(DESCRIPTOR);               if (iin != null && iin instanceof IMountService) {                   return (IMountService) iin;               }               return new IMountService.Stub.Proxy(obj);           }

“该方法将一个IBinder对象转换成一个IMountService接口,如果必要的话将通过代理来实现”,这里所��的代理指的是Proxy()方法。

这里又需要跳转到obj.queryLocaIInterface()方法中(PS:大家不要觉得枯燥,作为一个新手很多东西我也是第一次接触因此可能会走很多弯路,但过程还是很精彩的):

public IInterface queryLocalInterface(String descriptor);

很明显,这是一个在IBinder中的接口,因为Binder类实现了IBinder接口,因此我们直接去Binder类中查找该方法:

    public IInterface queryLocalInterface(String descriptor) {           if (mDescriptor.equals(descriptor)) {               return mOwner;           }           return null;       }

以上方法的作用是,根据传入的描述符返回一个IInterface的mOwner对象,该mOwner对象在Binder类中有方法带参数传递如下:

    public void attachInterface(IInterface owner, String descriptor) {           mOwner = owner;           mDescriptor = descriptor;       }

分析到这一步,我相信大家都头都晕了吧(不管你晕不晕,我反正是晕了,休息休息...)。

***********************分割线*********************

休息好了,我们继续分析吧。

因为IInterface实际上也是一个接口,因此不可能实例化对象来传递,所以这里我们也不用想,只要找到其子类那么传递的对象就是其子类实例化的对象。但是要怎么找呢?我们这里的descriptor是“IMountService”因此我们可以在IMountService.java中寻找线索:

public interface IMountService extends IInterface {       /** Local-side IPC implementation stub class. */       public static abstract class Stub extends Binder implements IMountService {           private static class Proxy implements IMountService {               private IBinder mRemote;                  Proxy(IBinder remote) {                   mRemote = remote;               }   ...省略              /** Construct the stub at attach it to the interface. */           public Stub() {               attachInterface(this, DESCRIPTOR);           }   ...省略

这里可以看到IMountService继承了IInterface并且其内部类Stub还继承了Binder并实现了IMountService。(这里会涉及到了Android中的AIDL即Android Interface Defenition Language的知识,关于AIDL我会在博客中另起文章介绍并结合源码分析。

虽然通过以上代码的分析,但似乎已经是死胡同了,那么接下来该肿么办呢?

(4).切莫误入歧途

我们回到StorageManager的带参构造函数中(别忘了我们从这里开始分支的):

    public StorageManager(Looper tgtLooper) throws RemoteException {           mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));           if (mMountService == null) {               Log.e(TAG, "Unable to connect to mount service! - is it running yet?");               return;           }           mTgtLooper = tgtLooper;           mBinderListener = new MountServiceBinderListener();           mMountService.registerListener(mBinderListener);       }

因为刚分析到第一句mMountService的实例化,通过以上的分析,我们将实例化对象锁定到了IMountService中的内部类Stub身上。因为分析不动了,那么我们先看看下一句关键代码吧:

mMountService.registerListener(mBinderListener);  

这里调用的是IMountService中的方法,因为该类是一个接口,因此不可能去执行其中的registerListener()方法。前面我们在StorageManager中提到了,在IMountService的对象mMountService实例化的过程中,最终IMountService.Stub有关系,mMountService实际上是传递的IMountService.Stub对象的引用。因此这里调用registerListener()方法的时候会去IMountService.Stub中查找有没有registerListener()方法,在Stub中有如下代码:

            public void registerListener(IMountServiceListener listener) throws RemoteException {                   Parcel _data = Parcel.obtain();                   Parcel _reply = Parcel.obtain();                   try {                       _data.writeInterfaceToken(DESCRIPTOR);                       _data.writeStrongBinder((listener != null ? listener.asBinder() : null));                       mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0);                       _reply.readException();                   } finally {                       _reply.recycle();                       _data.recycle();                   }               }

估计很多朋友看到这里又晕了,“这是又是什么东西啊...“

大家请勿惊慌,因为在Android中涉及到很多设计思路,这里就是其中之一——Android中的IPC机制。这里我会展开去说这个东西的原理以及如何实现的,因为我们的目标并不是它,所以我们只需要了解其大概意思就行了。

在IMountService.Stub中的registerListener()方法中,实现了对数据的封装并发送。那么哪里会接收呢?

(5).神秘的接收者

那么到底是谁来接收呢?答案是:MountService.java

这里的接收需要有一点AIDL的知识,这一点我回在后面的博文中加入实例以及和源码的分析。

MountService继承了IMountService.Stub并覆写了其中的registerListener()方法,真正调用的也就是MountService中的registerListener()方法:

    public void registerListener(IMountServiceListener listener) {           synchronized (mListeners) {               MountServiceBinderListener bl = new MountServiceBinderListener(listener);               try {                   listener.asBinder().linkToDeath(bl, 0);                   mListeners.add(bl);               } catch (RemoteException rex) {                   Slog.e(TAG, "Failed to link to listener death");               }           }       }

首先是一个同步块,然后是MountServiceBinderListener对象的声明以及实例化,但这里的MountServiceBinderListener和StorageManager中的可不是同一个哦。现在我们已经从StorageManager跳转到了MountService,我们回过头再看看我们在StorageManager中的调用吧:

    public StorageManager(Looper tgtLooper) throws RemoteException {           mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));           if (mMountService == null) {               Log.e(TAG, "Unable to connect to mount service! - is it running yet?");               return;           }           mTgtLooper = tgtLooper;           mBinderListener = new MountServiceBinderListener();           mMountService.registerListener(mBinderListener);       }

细心的朋友已经发现了吧!对,没错,我们传递的参数分明是MountServiceBinderListener的对象,而在MountService中的registerListener接收的参数却是IMountServiceListener类型的。这是怎么回事呢?我们可以在StorageManager中跟踪MountServiceBinderListener类,会发现:

private class MountServiceBinderListener extends IMountServiceListener.Stub

原来MountServiceBinderListener继承了IMountServiceListener.Stub,而Stub有实现了IMountServiceListener,因此根据多态性,参数为IMountServiceListener可以接收为MountServiceBinderListener的对象。

接下来我们回到MountService中的registerListener方法中,继续分析:

<font xmlns="http://www.w3.org/1999/xhtml" size="4"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml">MountServiceBinderListener bl = new MountServiceBinderListener(listener);   </font></font></font></font></font></font></font></font>  

这里是MountService中的MountServiceBinderListener,直接跟踪过去会发现:

<font xmlns="http://www.w3.org/1999/xhtml" size="4"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml">    private final class MountServiceBinderListener implements IBinder.DeathRecipient {           final IMountServiceListener mListener;              MountServiceBinderListener(IMountServiceListener listener) {               mListener = listener;              }   ...省略       }</font></font></font></font></font></font></font>  

在这个MountServiceBinderListener的构造函数中,相当于对IMountServiceListener对象进行了实例化,而实例化的对象就是StorageManager中传递过来的MountServiceBinderListener对象。

接着分析后面的代码:

<font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"> listener.asBinder().linkToDeath(bl, 0);   mListeners.add(bl);</font></font></font></font></font></font></font>  

这两句代码的意思就是注册一个IBinder进程死亡标志,该方法用来接收进程退出的消息,然后执行然后执行mListeners.add(bl);将bl对象加入Arraylist中。

(6).胜利的曙光

经过前面那么长,注意啊,是那么长的分析,我们回到到原点:

<font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml">        if (mStorageManager == null) {               mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);               mStorageManager.registerListener(mStorageListener);           }</font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font>  

我们刚刚分析完第一句,T_T,只是第一句啊。。。。。。

牢骚话不多说了,我们继续分析,接下来跳转到mStorageManager.registerListener()方法中:

<font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml">    public void registerListener(StorageEventListener listener) {           if (listener == null) {               return;           }              synchronized (mListeners) {               mListeners.add(new ListenerDelegate(listener));           }       }</font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font>  

继续跳转到ListenerDelegate()方法中:

<font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml"><font xmlns="http://www.w3.org/1999/xhtml">        ListenerDelegate(StorageEventListener listener) {               mStorageEventListener = listener;               mHandler = new Handler(mTgtLooper) {                   @Override                   public void handleMessage(Message msg) {                       StorageEvent e = (StorageEvent) msg.obj;                          if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) {                           UmsConnectionChangedStorageEvent ev = (UmsConnectionChangedStorageEvent) e;                           mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available);                       } else if (msg.what == StorageEvent.EVENT_STORAGE_STATE_CHANGED) {                           StorageStateChangedStorageEvent ev = (StorageStateChangedStorageEvent) e;                           mStorageEventListener.onStorageStateChanged(ev.path, ev.oldState, ev.newState);                       } else {                           Log.e(TAG, "Unsupported event " + msg.what);                       }                   }               };           }</font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font>  

根据以上代码可以知道,这里是将StorageEventListener的对象传入ListenerDelegate的构造函数,并返回一个ListenerDelegate的对象,将该返回的对象加入ArrayList<ListenerDelegate>中。我们可以看到在ListenerDelegate类的构造函数中有一个handleMessage,用于接收handler传递的消息。这一步分析到这里也就完成了,相当于监听的初始化已经完成。

后文将继续分析,敬请关注...

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wysszw.html