(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传递的消息。这一步分析到这里也就完成了,相当于监听的初始化已经完成。
后文将继续分析,敬请关注...