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++