[学习记录]Android4.0耳机插入广播发送流程分析

                                                                 Android4.0耳机插入广播发送流程分析
1.    相关文件
a.    frameworks/base/services/java/com/android/server/SystemServer.java
启动线程时新建WiredAccessoryObserver对象
b.    framework/base/services/java/com/android/server/WiredAccessoryObserver.java
类WiredAccessoryObserver继承UeventObserver,处理耳机状态等
c.    framework/base/core/java/android/os/UEventObserver.java
   UEventObserver是Android Java层利用uevent获取Kernel层状态变化的机制
UEventObserver接收kernel的uevent信息的抽象类。
类UEventObserver提供了三个方法给子类来调用:
1、    onUEvent(UEvent event)
   子类必须重写这个onUEvent来处理uevent。
    2、startObserving(String match)
       启动进程,要提供一个字符串参数。
    3、stopObserving()
       停止进程。
 

2.    流程分析
启动在 systemserver.java 中
public class SystemServer {
      public static void main(String[] args) {
        ......
        init1(args);
        ......
     }
public static final void init2() {
        Log.i(TAG, "Entered the Android system server!");
        Thread thr = new ServerThread();
        thr.setName("android.server.ServerThread");
        thr.start();
     }
}
init1 将会调用到 android_server_SystemServer_init1.cpp
extern "C" int system_init();
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
{
    system_init();
}
由上可以得到,将调用到 System_init.cpp
extern "C" status_t system_init()
{
    ......
    runtime->callStatic("com/android/server/SystemServer", "init2");
    ......
}
由上可以看出,此时将调回到 SystemServer的init2启动ServerThread线程
    Thread thr = new ServerThread();
    thr.setName("android.server.ServerThread");
    thr.start();
下面来看下ServerThread中做了哪些操作
class ServerThread extends Thread {
      ......
      public void run() {
        .....
        try {
                  Slog.i(TAG, "Wired Accessory Observer");
                  // Listen for wired headset changes
                  new WiredAccessoryObserver(context);
            } catch (Throwable e) {
                 reportWtf("starting WiredAccessoryObserver", e);
            }
     }
}
这里我们看到在线程启动后run方法中新建了WiredAccessoryObserver。
class WiredAccessoryObserver extends UeventObserver {
    private static final int MAX_AUDIO_PORTS = 3; /* h2w, USB Audio & hdmi */
private static final String uEventInfo[][] = {   
{ "DEVPATH=/devices/virtual/switch/h2w","/sys/class/switch/h2w/state",
"/sys/class/switch/h2w/name"},
{ "DEVPATH=/devices/virtual/switch/usb_audio",
"/sys/class/switch/usb_audio/state",
"/sys/class/switch/usb_audio/name"},
{ "DEVPATH=/devices/virtual/switch/hdmi","/sys/class/switch/hdmi/state",
"/sys/class/switch/hdmi/name"}
};

public  WiredAccessoryObserver(Context context) {
        mContext = context;
        ………    
        context.registerReceiver(new BootCompletedReceiver(),
            new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
}

private final class BootCompletedReceiver extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
        init();  // set initial status
        for (int i = 0; i < MAX_AUDIO_PORTS; i++) {
            startObserving(uEventInfo[i][0]);
        }
}
}
在 WiredAccessoryObserver 的构造函数中注册开机完成广播,在BootCompletedReceiver接收器中循环检测数组uEventInfo,其中uEventInfo[0][0](即为DEVPATH=/devices/virtual/switch/h2w 为耳机设备路径),我们来看下函数 startObserving
该函数在其 WiredAccessoryObserver的父类UEventObserver中
public abstract class UEventObserver {
    private static UEventThread sThread;

    private static class UEventThread extends Thread {
        private ArrayList<Object> mObservers = new ArrayList<Object>();
        
        UEventThread() {
            super("UEventObserver");
        }
        
        public void run() {
            native_setup();//调用uevent.c中的API来打开socket    

            byte[] buffer = new byte[1024];
            int len;
            while (true) {
                len = next_event(buffer); // 在uevent.c中用poll调用来获取event,会阻塞
                if (len > 0) {
                    String bufferStr = new String(buffer, 0, len);
                    synchronized (mObservers) {
                        for (int i = 0; i < mObservers.size(); i += 2) {
                        // 找到匹配的match参数,说明某个observer的监听的event发生了    
                            if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {
                                    ((UEventObserver)mObservers.get(i+1))
                                        .onUEvent(new UEvent(bufferStr));
                            }
                        }
                    }
                }
            }
        }

    public final synchronized void startObserving(String match) {
        //确保sThread已经运行并且以字串参数作为匹配参数增加一个observer
        ensureThreadStarted();
        sThread.addObserver(match, this);
    }

    public void addObserver(String match, UEventObserver observer) {
         synchronized(mObservers) {
                mObservers.add(match);
                mObservers.add(observer);
         }
    }
}
会循环调用onUEvent函数,此函数在 WiredAccessoryObserver 类中
    @Override
    public void onUEvent(UEventObserver.UEvent event) {
        try {
            String name = event.get("SWITCH_NAME");
            int state = Integer.parseInt(event.get("SWITCH_STATE"));
              //此处调用 updateState
            updateState(name, state);
        } catch (NumberFormatException e) {
            Slog.e(TAG, "Could not parse switch state from event " + event);
        }
}
private synchronized final void updateState(String name, int state)
    {
        if (name.equals("usb_audio")) {
            …
        } else if (name.equals("hdmi")) {
            …
        } else {
            switchState = ((mHeadsetState & (BIT_HDMI_AUDIO|BIT_USB_HEADSET_ANLG|
                                             BIT_USB_HEADSET_DGTL)) |
                            ((state == 1) ? BIT_HEADSET :
                                          ((state == 2) ? BIT_HEADSET_NO_MIC : 0)));
        }
         //此处调用 update函数
        update(name, switchState);
    }
// update函数: 用来更新耳机状态发送消息
private synchronized final void update(String newName, int newState) {
        // Retain only relevant bits
        int headsetState = newState & SUPPORTED_HEADSETS;
        int newOrOld = headsetState | mHeadsetState;
        int delay = 0;
        int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
        int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
     
        int h2w_headset = newOrOld & (BIT_HEADSET | BIT_HEADSET_NO_MIC);
        int h2w_state   = (headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC));
        int h2w_mstate  = (mHeadsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC));
       
        boolean h2wStateChange = true;
      
        if (h2w_mstate == h2w_state || ((h2w_headset & (h2w_headset - 1)) != 0)) {
            Log.e(TAG, "unsetting h2w flag");
            h2wStateChange = false;
        }
    
        mHeadsetName = newName;
        mPrevHeadsetState = mHeadsetState;
        mHeadsetState = headsetState;

        if (headsetState == 0) {
            Intent intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
            mContext.sendBroadcast(intent);
            // It can take hundreds of ms flush the audio pipeline after
            // apps pause audio playback, but audio route changes are
            // immediate, so delay the route change by 1000ms.
            // This could be improved once the audio sub-system provides an
            // interface to clear the audio pipeline.
            delay = 1000;
        } else {
            // Insert the same delay for headset connection so that the connection event is not
            // broadcast before the disconnection event in case of fast removal/insertion
            if (mHandler.hasMessages(0)) {
                delay = 1000;
            }
        }
        mWakeLock.acquire();
        //此处会发送消息
        mHandler.sendMessageDelayed(mHandler.obtainMessage(0,
                                                           mHeadsetState,
                                                           mPrevHeadsetState,
                                                           mHeadsetName),
                                    delay);
    }
    //此处处理消息
   private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            sendIntents(msg.arg1, msg.arg2, (String)msg.obj);
            
        }
    };

    private synchronized final void sendIntents(int headsetState, int prevHeadsetState, String headsetName) {
        int allHeadsets = SUPPORTED_HEADSETS;
        //for 循环有疑问
       // int BIT_HEADSET = (1 << 0);
       //int BIT_HEADSET_NO_MIC = (1 << 1);…
       // BIT_USB_HEADSET_ANLG
       // BIT_USB_HEADSET_DGTL
       // int SUPPORTED_HEADSETS =
(BIT_HEADSET|
BIT_HEADSET_NO_MIC|
                 BIT_USB_HEADSET_ANLG|
BIT_USB_HEADSET_DGTL|
                          BIT_HDMI_AUDIO);
        for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
            if ((curHeadset & allHeadsets) != 0) {
                sendIntent(curHeadset, headsetState, prevHeadsetState, headsetName);
                allHeadsets &= ~curHeadset;
            }
        }
    }
//此处填充 Intent , 并通过 ActivityManagerNative.broadcastStickyIntent来发送
private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) {
         //判断什么类型耳机,并发送广播
        if ((headsetState & headset) != (prevHeadsetState & headset)) {

            int state = 0;
            if ((headsetState & headset) != 0) {
                state = 1;
            }

            if((headset == BIT_HEADSET) || (headset == BIT_HEADSET_NO_MIC)) {

                //  Pack up the values and broadcast them to everyone
                Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                //int state = 0;
                int microphone = 0;

                if ((headset & HEADSETS_WITH_MIC) != 0) {
                    microphone = 1;
                }

                intent.putExtra("state", state);
                intent.putExtra("name", headsetName);
                intent.putExtra("microphone", microphone);

                if (LOG) Slog.v(TAG, "Intent.ACTION_HEADSET_PLUG: state: "+state+" name: "+headsetName+" mic: "+microphone);
                
                ActivityManagerNative.broadcastStickyIntent(intent, null);
            }
        }
}

//ACTION类别
/**
     * Broadcast Action: Wired Headset plugged in or unplugged.
     *
     * <p>The intent will have the following extra values:
     * <ul>
     *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
     *   <li><em>name</em> - Headset type, human readable string </li>
     *   <li><em>microphone</em> - 1 if headset has a microphone, 0 otherwise </li>
     * </ul>
     * </ul>
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_HEADSET_PLUG =
            "android.intent.action.HEADSET_PLUG";

    /**
     * Broadcast Action: An analog(<电脑>模拟的) audio speaker/headset plugged in or unplugged.
     *
     * <p>The intent will have the following extra values:
     * <ul>
     *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
     *   <li><em>name</em> - Headset type, human readable string </li>
     * </ul>
     * </ul>
     * @hide
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_USB_ANLG_HEADSET_PLUG =
            "android.intent.action.USB_ANLG_HEADSET_PLUG";

    /**
     * Broadcast Action: A digital audio speaker/headset plugged in or unplugged.
     *
     * <p>The intent will have the following extra values:
     * <ul>
     *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
     *   <li><em>name</em> - Headset type, human readable string </li>
     * </ul>
     * </ul>
     * @hide
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_USB_DGTL_HEADSET_PLUG =
            "android.intent.action.USB_DGTL_HEADSET_PLUG";


参考资料:
http://blog.csdn.net/tanxs001/article/details/7709208
http://blog.sina.com.cn/s/blog_40d475e901012jxh.html
http://blog.csdn.net/darkengine/article/details/7442359


 后续继续整理 

你可能感兴趣的:([学习记录]Android4.0耳机插入广播发送流程分析)