关于Usb的检测,相关联的和sd card一起研究。
在状态栏如何进行显示Sd卡插入状态的Notification和Usb在Debugging时的Notification的?
先来看Sd卡的Notification显示:
在StatusBarPolicy.java的StatusBarPolicy类的构造函数中,有这样关于Sd卡的状态监听机制:
// storage
mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
mStorageManager.registerListener(
new com.android.systemui.usb.StorageNotification(context));
进入StorageManager.java的registerListener去查看是怎样监听的:
public void registerListener(StorageEventListener listener) {
if (listener == null) {
return;
}
synchronized (mListeners) {
mListeners.add(new ListenerDelegate(listener));
}
}
可见所谓注册过程就是将监听类添加到监听的List表中,那么,在这个表中如何监听的?
查看ListenerDelegate:
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);
}
}
};
}
实际上就是开启一个无线循环的Handler等待消息的传送过来,到这一步自然就会想到是谁发送消息?
先插卡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);
}
在开启StorageManager的时候实际上就开启一个MountService,将MountServiceBinderListener注册为监听类:
它的作用是这样的:
private class MountServiceBinderListener extends IMountServiceListener.Stub {
public void onUsbMassStorageConnectionChanged(boolean available) {
final int size = mListeners.size();
for (int i = 0; i < size; i++) {
mListeners.get(i).sendShareAvailabilityChanged(available);
}
}
public void onStorageStateChanged(String path, String oldState, String newState) {
final int size = mListeners.size();
for (int i = 0; i < size; i++) {
mListeners.get(i).sendStorageStateChanged(path, oldState, newState);
}
}
}
也就是实际发送StorageEvent.EVENT_UMS_CONNECTION_CHANGED或者另外的消息:
EVENT_STORAGE_STATE_CHANGED。
那么这个监听类如何知道状态变化的?
在MountService.java中,
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");
}
}
}
在MountService中有一个可供守护进程调用的函数:
public boolean onEvent(int code, String raw, String[] cooked),它在有关状态发生变化时会调用相关函数,比如VolumeStateChange时,notifyShareAvailabilityChange(),而在 notifyShareAvailabilityChange()中会更新:
updatePublicVolumeState(),在这里我们看到实际就是通过Environment中相关函数判断Sd卡状态,
在这里:
synchronized (mListeners) {
for (int i = mListeners.size() -1; i >= 0; i--) {
MountServiceBinderListener bl = mListeners.get(i);
try {
bl.mListener.onStorageStateChanged(path, oldState, state);
} catch (RemoteException rex) {
Slog.e(TAG, "Listener dead");
mListeners.remove(i);
} catch (Exception ex) {
Slog.e(TAG, "Listener failed", ex);
}
}
}
也就是守护进程检测sd卡状态变化时调用StorageManager中的mBinderListener对象的onStorageStateChanged,此时在StorageManager中,就依次向需要知道Storage状态变化的目标发送消息,刚才我们说的StorageManager开启的无限循环的Handler收到消息就开始了相应处理。
Usb插入时有无Debugging时的Notification是怎样产生的?
在UsbService.java中,private final UEventObserver mUEventObserver = new UEventObserver() 函数是用来监听底层Usb状态的机制。当"usb_connected"、"usb_configuration"、或者其它的Usb状态(如Adb)发生变化时会发送一个Message,然后根据message,usbService做出相应的处理。
在source code中,adb变化时,有Note如下:
Note: we do not broadcast a change when a function is enabled or disabled. We just record the state change for the next broadcast.
这就使得android系统不能及时更新Usb Notification状态。
在handler处理函数处:
case MSG_FUNCTION_ENABLED:
case MSG_FUNCTION_DISABLED:
functionEnabledLocked((String)msg.obj, msg.what == MSG_FUNCTION_ENABLED);
break;
如Note所说,仅仅是保存起来,并未进行更新。
要想即刻做出更新,应做出如下操作:
case MSG_FUNCTION_ENABLED:
case MSG_FUNCTION_DISABLED:
functionEnabledLocked((String)msg.obj, msg.what == MSG_FUNCTION_ENABLED);
// send a sticky broadcast containing current USB state
Intent intent = new Intent(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;
这就完成了及时更新策略。