关于Usb的检测,相关联的和sdcard一起研究。
在状态栏如何进行显示Sd卡插入状态的Notification和Usb在Debugging时的Notification的?
先来看Sd卡的Notification显示:
在StatusBarPolicy.java的StatusBarPolicy类的构造函数中,有这样关于Sd卡的状态监听机制:
//storage
mStorageManager=(StorageManager)context.getSystemService(Context.STORAGE_SERVICE);
mStorageManager.registerListener(
newcom.android.systemui.usb.StorageNotification(context));
进入StorageManager.java的registerListener去查看是怎样监听的:
publicvoidregisterListener(StorageEventListenerlistener){
if(listener==null){
return;
}
synchronized(mListeners){
mListeners.add(newListenerDelegate(listener));
}
}
可见所谓注册过程就是将监听类添加到监听的List表中,那么,在这个表中如何监听的?
查看ListenerDelegate:
ListenerDelegate(StorageEventListenerlistener){
mStorageEventListener=listener;
mHandler=newHandler(mTgtLooper){
@Override
publicvoidhandleMessage(Messagemsg){
StorageEvente=(StorageEvent)msg.obj;
if(msg.what==StorageEvent.EVENT_UMS_CONNECTION_CHANGED){
UmsConnectionChangedStorageEventev=(UmsConnectionChangedStorageEvent)e;
mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available);
}elseif(msg.what==StorageEvent.EVENT_STORAGE_STATE_CHANGED){
StorageStateChangedStorageEventev=(StorageStateChangedStorageEvent)e;
mStorageEventListener.onStorageStateChanged(ev.path,ev.oldState,ev.newState);
}else{
Log.e(TAG,"Unsupportedevent"+msg.what);
}
}
};
}
实际上就是开启一个无线循环的Handler等待消息的传送过来,到这一步自然就会想到是谁发送消息?
先插卡StorageManager类的构造函数:
publicStorageManager(LoopertgtLooper)throwsRemoteException{
mMountService=IMountService.Stub.asInterface(ServiceManager.getService("mount"));
if(mMountService==null){
Log.e(TAG,"Unabletoconnecttomountservice!-isitrunningyet?");
return;
}
mTgtLooper=tgtLooper;
mBinderListener=newMountServiceBinderListener();
mMountService.registerListener(mBinderListener);
}
在开启StorageManager的时候实际上就开启一个MountService,将MountServiceBinderListener注册为监听类:
它的作用是这样的:
privateclassMountServiceBinderListenerextendsIMountServiceListener.Stub{
publicvoidonUsbMassStorageConnectionChanged(booleanavailable){
finalintsize=mListeners.size();
for(inti=0;i<size;i++){
mListeners.get(i).sendShareAvailabilityChanged(available);
}
}
publicvoidonStorageStateChanged(Stringpath,StringoldState,StringnewState){
finalintsize=mListeners.size();
for(inti=0;i<size;i++){
mListeners.get(i).sendStorageStateChanged(path,oldState,newState);
}
}
}
也就是实际发送StorageEvent.EVENT_UMS_CONNECTION_CHANGED或者另外的消息:
EVENT_STORAGE_STATE_CHANGED。
那么这个监听类如何知道状态变化的?
在MountService.java中,
publicvoidregisterListener(IMountServiceListenerlistener){
synchronized(mListeners){
MountServiceBinderListenerbl=newMountServiceBinderListener(listener);
try{
listener.asBinder().linkToDeath(bl,0);
mListeners.add(bl);
}catch(RemoteExceptionrex){
Slog.e(TAG,"Failedtolinktolistenerdeath");
}
}
}
在MountService中有一个可供守护进程调用的函数:
publicbooleanonEvent(intcode,Stringraw,String[]cooked),它在有关状态发生变化时会调用相关函数,比如VolumeStateChange时,notifyShareAvailabilityChange(),而在notifyShareAvailabilityChange()中会更新:
updatePublicVolumeState(),在这里我们看到实际就是通过Environment中相关函数判断Sd卡状态,
在这里:
synchronized(mListeners){
for(inti=mListeners.size()-1;i>=0;i--){
MountServiceBinderListenerbl=mListeners.get(i);
try{
bl.mListener.onStorageStateChanged(path,oldState,state);
}catch(RemoteExceptionrex){
Slog.e(TAG,"Listenerdead");
mListeners.remove(i);
}catch(Exceptionex){
Slog.e(TAG,"Listenerfailed",ex);
}
}
}
也就是守护进程检测sd卡状态变化时调用StorageManager中的mBinderListener对象的onStorageStateChanged,此时在StorageManager中,就依次向需要知道Storage状态变化的目标发送消息,刚才我们说的StorageManager开启的无限循环的Handler收到消息就开始了相应处理。
Usb插入时有无Debugging时的Notification是怎样产生的?
在UsbService.java中,privatefinalUEventObservermUEventObserver=newUEventObserver()函数是用来监听底层Usb状态的机制。当"usb_connected"、"usb_configuration"、或者其它的Usb状态(如Adb)发生变化时会发送一个Message,然后根据message,usbService做出相应的处理。
在sourcecode中,adb变化时,有Note如下:
Note:wedonotbroadcastachangewhenafunctionisenabledordisabled.Wejustrecordthestatechangeforthenextbroadcast.
这就使得android系统不能及时更新UsbNotification状态。
在handler处理函数处:
caseMSG_FUNCTION_ENABLED:
caseMSG_FUNCTION_DISABLED:
functionEnabledLocked((String)msg.obj,msg.what==MSG_FUNCTION_ENABLED);
break;
如Note所说,仅仅是保存起来,并未进行更新。
要想即刻做出更新,应做出如下操作:
caseMSG_FUNCTION_ENABLED:
caseMSG_FUNCTION_DISABLED:
functionEnabledLocked((String)msg.obj,msg.what==MSG_FUNCTION_ENABLED);
//sendastickybroadcastcontainingcurrentUSBstate
Intentintent=newIntent(UsbManager.ACTION_USB_STATE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(UsbManager.USB_CONNECTED,mConnected!=0);
intent.putExtra(UsbManager.USB_CONFIGURATION,mConfiguration);
addEnabledFunctionsLocked(intent);
mContext.sendStickyBroadcast(intent);
break;
这就完成了及时更新策略。