当前位置: 代码迷 >> 综合 >> SystemUI之USB1(kernel-Framework UEvent)
  详细解决方案

SystemUI之USB1(kernel-Framework UEvent)

热度:87   发布时间:2024-01-10 22:24:51.0

kernel那边有USB事件后,往上层传到framework,封装消息后通知systemUI。


第一节 
Kernal 与 Framework层交互 UEventObserver;插入与拔出USB设备,事件监听以及上报.UEventObserver

涉及到的类文件: 
- android_os_UEventObserver.cpp 
./frameworks/base/core/jni/android_os_UEventObserver.cpp 
- UEventObserver.Java 
./frameworks/base/core/java/Android/os/UEventObserver.java

插拔U盘,usb事件上报 
在UsbDeviceManager.java的构造方法中,添加了USB_STATE_MATCH和ACCESSORY_START_MATCH监听。因此,下面我们就按照源码跟踪framework与kernal交互的这段边界部分。    

    ...// Watch for USB configuration changesmUEventObserver.startObserving(USB_STATE_MATCH);    mUEventObserver.startObserving();...
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

下面我们转到UEventObserver中,UEventObserver 是一个Interface,定义了一个回调方法,onUEvent,通过它将kernal 上报事件传递至app/framework层、

/*mUEventObserver的声明:* Listens for uevent messages from the kernel to monitor the USB state*/private final UEventObserver mUEventObserver = new UEventObserver() {@Overridepublic void onUEvent(UEventObserver.UEvent event) { //这里从UEventTheadString state = event.get("USB_STATE");String accessory = event.get("ACCESSORY");if (state != null) {mHandler.updateState(state); //更新USB当前的状态,CONNECTED ,DISCONNECTED,CONFIGURED} else if ...}};
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

先看UEventObserver中的startObservering方法

    public final void startObserving(String match) {...//The UEventThread is Singleton pattern.final UEventThread t = getThread();t.addObserver(match, this); //this参数,当onUEvent回调时,则回调到注册的这个Observer中。}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

接下来,startObserving方法转到了UEventThread中。UEventThread是个线程是UEventObserver的内部类,run方法中是个死循环,不断地监听UEvent,当有事件从Kernal上报时,则通过Handler一步步上传。UEventThread 在UEventObserver中以单例模式存在。

//Create the thread and start itprivate static UEventThread getThread() {synchronized (UEventObserver.class) { //keep it sysncronizedif (sThread == null) {sThread = new UEventThread(); //第一次创建并startsThread.start();}return sThread;}}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

UEventThread:

 private static final class UEventThread extends Thread {
    /** Many to many mapping of string match to observer.*  Multimap would be better, but not available in android, so use*  an ArrayList where even elements are the String match and odd*  elements the corresponding(相关的) UEventObserver observer */private final ArrayList<Object> mKeysAndObservers = new ArrayList<Object>();private final ArrayList<UEventObserver> mTempObserversToSignal =new ArrayList<UEventObserver>();public UEventThread() {super("UEventObserver");}@Overridepublic void run() {nativeSetup();while (true) {
   //   a loop to get Event everytimeString message = nativeWaitForNextEvent();//wait for the next Eventif (message != null) {sendEvent(message);}}}
//向上层发送Eventprivate void sendEvent(String message) {synchronized (mKeysAndObservers) {final int N = mKeysAndObservers.size();for (int i = 0; i < N; i += 2) {final String key = (String)mKeysAndObservers.get(i); // the match String index is i//遍历list中所有的match Stringif (message.contains(key)) {final UEventObserver observer =(UEventObserver)mKeysAndObservers.get(i + 1); // then , the Observer object in ArrayList index is (i+1)mTempObserversToSignal.add(observer);}}}if (!mTempObserversToSignal.isEmpty()) {final UEvent event = new UEvent(message);//mTempObserversToSignal存储是的与该message相配套的Observer,所以这里遍历后,将message全部发出去。final int N = mTempObserversToSignal.size();for (int i = 0; i < N; i++) {final UEventObserver observer = mTempObserversToSignal.get(i);observer.onUEvent(event); //找到与回调回去了}//发出去完了,等待下一波mTempObserversToSignal.clear();}}// “matchA”,ObserverA ;"matchB",ObserverB ...// 这里的match String 和 Observer Object是成双成对的,如果我取到了match String index 为 i,则Observer object 的index 为 (i+1)// 这里 match是不会一致的,否则就重复了,但是Observer 是会有可能同一个public void addObserver(String match, UEventObserver observer) {synchronized (mKeysAndObservers) {//mKeyAndroidObservers key to valuemKeysAndObservers.add(match); mKeysAndObservers.add(observer);nativeAddMatch(match);}}...
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

在UEventThread中,有两个ArrayList,一个是mKeysAndObservers,虽然是个List但是它扮演的是Map的角色,里面的match (String) , Observer(Object) 一一对应,这里就有疑问了?为何不直接使用map呢?map不正好是key-value对应的吗? 我的认为是,list里面match (String) 与Obsever的对应是存在重复的情况。但是map中是不允许key重复的。这应该是没有使用Map的原因吧。?????

另外一个是mTempObserversToSignal ,作为临时变量。framework/base/core/jni/android_os_UEventObserver.cpp 

那UEvent从哪里来呢?从nativeWaitForNextEvent这里来。后面的部分暂时不继续往下跟了。

static jstring nativeWaitForNextEvent(JNIEnv *env, jclass clazz) {char buffer[1024];for (;;) {int length = uevent_next_event(buffer, sizeof(buffer) - 1);if (length <= 0) {return NULL;}buffer[length] = '\0';ALOGV("Received uevent message: %s", buffer);if (isMatch(buffer, length)) {// Assume the message is ASCII.jchar message[length];for (int i = 0; i < length; i++) {message[i] = buffer[i];}return env->NewString(message, length);}}}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  1. UsbInterface,UsbConfigration,UsbDevice 的创建
  2. USB相关Notification的显示流程,源码解析

从上面的分析我们看到,当有新的UEvent从kernal 过来后,UEventObserver回调在UsbDeviceManager中,此时我们通过Handler消息机制,更新Notification的显示。具体过程如下:

 private final UEventObserver mUEventObserver = new UEventObserver() {@Overridepublic void onUEvent(UEventObserver.UEvent event) { //这里从UEventTheadif (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());String state = event.get("USB_STATE");String accessory = event.get("ACCESSORY");if (state != null) {mHandler.updateState(state);} else if {...}}};
mHandler中的updateState:public void updateState(String state) {int connected, configured;if ("DISCONNECTED".equals(state)) {  //断开连接connected = 0;configured = 0;} else if ("CONNECTED".equals(state)) {  //连接上connected = 1;configured = 0;} else if ("CONFIGURED".equals(state)) {connected = 1;configured = 1;} else {Slog.e(TAG, "unknown state " + state);return;}removeMessages(MSG_UPDATE_STATE); //avoid MSG repeatedMessage msg = Message.obtain(this, MSG_UPDATE_STATE);msg.arg1 = connected;msg.arg2 = configured;// debounce disconnects to avoid problems bringing up USB tetheringsendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

此处对MSG_UPDATE_STATE 的处理是关键。

        @Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_UPDATE_STATE:mConnected = (msg.arg1 == 1); mConfigured = (msg.arg2 == 1);updateUsbNotification(); // 更新USB NotificationupdateAdbNotification();if (containsFunction(mCurrentFunctions,UsbManager.USB_FUNCTION_ACCESSORY)) {updateCurrentAccessory();} else if (!mConnected) {// restore defaults when USB is disconnectedsetEnabledFunctions(getDefaultFunctions(), false);}if (mSystemReady) {updateUsbState();updateAudioSourceFunction();}break;...
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

接下来我们只看updateUsbNotification方法。这个方法很简单,就是更新Notification,就是我们平时插上USB连接线的时候,顶部通知栏会显示的通知。

如果你要添加声音或者振动,或者更改图标等,算是找对地方了。

  private void updateUsbNotification() {if (mNotificationManager == null || !mUseUsbNotification) return;int id = 0;Resources r = mContext.getResources();if (mConnected) {if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) {id = com.android.internal.R.string.usb_mtp_notification_title; //作为USB设备链接} else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) {id = com.android.internal.R.string.usb_ptp_notification_title;//作为相机链接} else if (containsFunction(mCurrentFunctions,UsbManager.USB_FUNCTION_MASS_STORAGE)) {id = com.android.internal.R.string.usb_cd_installer_notification_title; //作为安装应用程序} else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ACCESSORY)) {id = com.android.internal.R.string.usb_accessory_notification_title; // 已链接到USB配件} else {// There is a different notification for USB tethering so we don't need one here//if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) {
    // Slog.e(TAG, "No known USB function in updateUsbNotification");//}}}if (id != mUsbNotificationId) {// clear notification if title needs changingif (mUsbNotificationId != 0) { //当前正在显示的notification idmNotificationManager.cancelAsUser(null,mUsbNotificationId,UserHandle.ALL);mUsbNotificationId = 0;}if (id != 0) {CharSequence message = r.getText(com.android.internal.R.string.usb_notification_message); //触摸可以显示其他USB选项CharSequence title = r.getText(id);Notification notification = new Notification();notification.icon = com.android.internal.R.drawable.stat_sys_data_usb;notification.when = 0; notification.flags = Notification.FLAG_ONGOING_EVENT;notification.tickerText = title;//如果我们需要添加声音,是否振动或者更改显示的图标,可以修改这里。notification.defaults = 0; // please be quietnotification.sound = null;notification.vibrate = null;//设置优先级notification.priority = Notification.PRIORITY_MIN;//点击通知栏后的操作Intent intent = Intent.makeRestartActivityTask(new ComponentName("com.android.settings","com.android.settings.UsbSettings"));PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,intent, 0, null, UserHandle.CURRENT);notification.color = mContext.getResources().getColor(com.android.internal.R.color.system_notification_accent_color);notification.setLatestEventInfo(mContext, title, message, pi);notification.visibility = Notification.VISIBILITY_PUBLIC;mNotificationManager.notifyAsUser(null, id, notification,UserHandle.ALL);mUsbNotificationId = id;}}}......
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

Kernal —> Framework UEvent这部分,并插拔USB时,Notification的更新就先讲到这里了





  相关解决方案