android 4.4的耳机插入检测流程
2014-05-06 10:46
267 查看
base/services/java/com/android/server/SystemServer.java
System Server是Android系统的核心,他在Dalvik虚拟机启动后立即开始初始化和运行。其它的系统服务在System Server进程的环境中运行。
在main函数中,首先检查系统时间设置和SamplingProfiler。然后加载一个叫android_servers的本地库,他提供本地方法的接口(源程序在framework/base/services/jni/目录中)。然后调用本地方法设置服务。然后执行一个死循环线程,该线程中启动了很多服务。
在ServerThread中启动了监听有线耳机接入的服务。
在base/services/java/com/android/server/WiredAccessoryManager.java 中
WiredAccessoryManager中使用了两种方式监听耳机的状态
在起构造函数中获得mUseDevInputEventForAudioJack的状态,配置为false。
在启动完成后就开启监听,注册了开机广播,开机后,会开始所有相关的UEvent,并且开始监听。在private void bootCompleted()中
在WiredAccessoryObserver中,
在WiredAccessoryObserver 的init中
通过startObserving("DEVPATH="+uei.getDevPath()); 来进行监听
监听的节点是
在onUEvent时间到来的时候更新state
updateStateLocked(devPath, name, state) -> updateLocked(String newName, int newState) -> setDevicesState(
int headsetState, int prevHeadsetState, String headsetName) -> setDeviceStateLocked() ->mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
在setDeviceStateLocked中会更新device的状态,并最终调用mAudioManager.setWiredDeviceConnectionState
AudioManager的setWiredDeviceConnectionState实际是调用AudioService的setWiredDeviceConnectionState方法。
最终会发送到上层一个广播:
System Server是Android系统的核心,他在Dalvik虚拟机启动后立即开始初始化和运行。其它的系统服务在System Server进程的环境中运行。
在main函数中,首先检查系统时间设置和SamplingProfiler。然后加载一个叫android_servers的本地库,他提供本地方法的接口(源程序在framework/base/services/jni/目录中)。然后调用本地方法设置服务。然后执行一个死循环线程,该线程中启动了很多服务。
public static void main(String[] args) { ............................................ ............................................. Environment.setUserRequired(true); System.loadLibrary("android_servers"); Slog.i(TAG, "Entered the Android system server!"); // Initialize native services. nativeInit(); // This used to be its own separate thread, but now it is // just the loop we run on the main thread. ServerThread thr = new ServerThread(); thr.initAndLoop(); } }
在ServerThread中启动了监听有线耳机接入的服务。
if (!disableMedia) { try { Slog.i(TAG, "Wired Accessory Manager"); // Listen for wired headset changes inputManager.setWiredAccessoryCallbacks( new WiredAccessoryManager(context, inputManager)); } catch (Throwable e) { reportWtf("starting WiredAccessoryManager", e); } }
在base/services/java/com/android/server/WiredAccessoryManager.java 中
WiredAccessoryManager中使用了两种方式监听耳机的状态
在起构造函数中获得mUseDevInputEventForAudioJack的状态,配置为false。
public WiredAccessoryManager(Context context, InputManagerService inputManager) { PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryManager"); mWakeLock.setReferenceCounted(false); mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); mInputManager = inputManager; mContext= context; mUseDevInputEventForAudioJack = context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack); mObserver = new WiredAccessoryObserver(); context.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context ctx, Intent intent) { bootCompleted(); } }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); }
在启动完成后就开启监听,注册了开机广播,开机后,会开始所有相关的UEvent,并且开始监听。在private void bootCompleted()中
private void bootCompleted() { if (mUseDevInputEventForAudioJack) { //inputEvent方式 int switchValues = 0; if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_HEADPHONE_INSERT) == 1) { switchValues |= SW_HEADPHONE_INSERT_BIT; } if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MICROPHONE_INSERT) == 1) { switchValues |= SW_MICROPHONE_INSERT_BIT; } notifyWiredAccessoryChanged(0, switchValues, SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT); } mObserver.init(); PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); mHdmiWakeLock=pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE , "HdmiWakeLock"); mHdmiWakeLock.setReferenceCounted(false); }在WiredAccessoryManager中实例化了一个WiredAccessoryObserver,其就是通过UEvent方式来检测耳机的插入拔出状态,
mObserver = new WiredAccessoryObserver();
class WiredAccessoryObserver extends UEventObserver { private final List<UEventInfo> mUEventInfo; public WiredAccessoryObserver() { mUEventInfo = makeObservedUEventList(); }
在WiredAccessoryObserver中,
private List<UEventInfo> makeObservedUEventList() { List<UEventInfo> retVal = new ArrayList<UEventInfo>(); UEventInfo uei; // Monitor h2w if (!mUseDevInputEventForAudioJack) { uei = new UEventInfo(NAME_H2W, BIT_HEADSET, BIT_HEADSET_NO_MIC); if (uei.checkSwitchExists()) { retVal.add(uei); } else { Slog.w(TAG, "This kernel does not have wired headset support"); } } // Monitor USB uei = new UEventInfo(NAME_USB_AUDIO, BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL); if (uei.checkSwitchExists()) { retVal.add(uei); } else { Slog.w(TAG, "This kernel does not have usb audio support"); } // Monitor HDMI // // If the kernel has support for the "hdmi_audio" switch, use that. It will be // signalled only when the HDMI driver has a video mode configured, and the downstream // sink indicates support for audio in its EDID. // // If the kernel does not have an "hdmi_audio" switch, just fall back on the older // "hdmi" switch instead. uei = new UEventInfo(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0); if (uei.checkSwitchExists()) { retVal.add(uei); } else { uei = new UEventInfo(NAME_HDMI, BIT_HDMI_AUDIO, 0); if (uei.checkSwitchExists()) { retVal.add(uei); } else { Slog.w(TAG, "This kernel does not have HDMI audio support"); } } return retVal; }
在WiredAccessoryObserver 的init中
void init() { synchronized (mLock) { if (LOG) Slog.v(TAG, "init()"); char[] buffer = new char[1024]; for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); try { int curState; FileReader file = new FileReader(uei.getSwitchStatePath()); int len = file.read(buffer, 0, 1024); file.close(); curState = Integer.valueOf((new String(buffer, 0, len)).trim()); if (curState > 0) { updateStateLocked(uei.getDevPath(), uei.getDevName(), curState); } } catch (FileNotFoundException e) { Slog.w(TAG, uei.getSwitchStatePath() + " not found while attempting to determine initial switch state"); } catch (Exception e) { Slog.e(TAG, "" , e); } } } // At any given time accessories could be inserted // one on the board, one on the dock and one on HDMI: // observe three UEVENTs for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); startObserving("DEVPATH="+uei.getDevPath()); } }
通过startObserving("DEVPATH="+uei.getDevPath()); 来进行监听
startObserving("DEVPATH="+uei.getDevPath());
监听的节点是
shell@hammerhead:/ $ ls sys/class/switch/ -l lrwxrwxrwx root root 2014-05-06 09:44 h2w -> ../../devices/virtual/switch/h2w lrwxrwxrwx root root 2014-05-06 09:44 hdmi -> ../../devices/virtual/switch/hdmi lrwxrwxrwx root root 2014-05-06 09:44 hdmi_audio -> ../../devices/virtual/switch/hdmi_audio lrwxrwxrwx root root 2014-05-06 09:44 usb_audio -> ../../devices/virtual/switch/usb_audio lrwxrwxrwx root root 2014-05-06 09:44 wfd -> ../../devices/virtual/switch/wfd
在onUEvent时间到来的时候更新state
public void onUEvent(UEventObserver.UEvent event) { if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString()); try { String devPath = event.get("DEVPATH"); String name = event.get("SWITCH_NAME"); int state = Integer.parseInt(event.get("SWITCH_STATE")); synchronized (mLock) { updateStateLocked(devPath, name, state); } } catch (NumberFormatException e) { Slog.e(TAG, "Could not parse switch state from event " + event); } }
updateStateLocked(devPath, name, state) -> updateLocked(String newName, int newState) -> setDevicesState(
int headsetState, int prevHeadsetState, String headsetName) -> setDeviceStateLocked() ->mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
在setDeviceStateLocked中会更新device的状态,并最终调用mAudioManager.setWiredDeviceConnectionState
private void setDeviceStateLocked(int headset, int headsetState, int prevHeadsetState, String headsetName) { if ((headsetState & headset) != (prevHeadsetState & headset)) { int device; int state; if ((headsetState & headset) != 0) { state = 1; } else { state = 0; } if (headset == BIT_HEADSET) { device = AudioManager.DEVICE_OUT_WIRED_HEADSET; } else if (headset == BIT_HEADSET_NO_MIC){ device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE; } else if (headset == BIT_USB_HEADSET_ANLG) { device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET; } else if (headset == BIT_USB_HEADSET_DGTL) { device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET; } else if (headset == BIT_HDMI_AUDIO) { device = AudioManager.DEVICE_OUT_AUX_DIGITAL; } else { Slog.e(TAG, "setDeviceState() invalid headset type: "+headset); return; } if (LOG) Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected")); if(headsetName.equals("hdmi")&&state==1){ Intent intent=new Intent("android.intent.action.HDMI_PLUG"); intent.putExtra("state", 1); intent.putExtra("name", "hdmi"); mContext.sendBroadcast(intent); mHdmiWakeLock.acquire(); Log.d(TAG,"--- hdmi connect "); }else if(headsetName.equals("hdmi")&&state==0){ Log.d(TAG,"--- hdmi disconnect "); Intent intent=new Intent("android.intent.action.HDMI_PLUG"); intent.putExtra("state", 0); intent.putExtra("name", "hdmi"); mContext.sendBroadcast(intent); mHdmiWakeLock.release(); } mAudioManager.setWiredDeviceConnectionState(device, state, headsetName); } }
AudioManager的setWiredDeviceConnectionState实际是调用AudioService的setWiredDeviceConnectionState方法。
2796 public void setWiredDeviceConnectionState(int device, int state, String name) { 2797 synchronized (mConnectedDevices) { 2798 int delay = checkSendBecomingNoisyIntent(device, state); 2799 queueMsgUnderWakeLock(mAudioHandler, 2800 MSG_SET_WIRED_DEVICE_CONNECTION_STATE, 2801 device, 2802 state, 2803 name, 2804 delay); 2805 } 2806 }
最终会发送到上层一个广播:
private void sendDeviceConnectionIntent(int device, int state, String name) 3924 { 3925 Intent intent = new Intent(); 3926 3927 intent.putExtra("state", state); 3928 intent.putExtra("name", name); 3929 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 3930 3931 int connType = 0; 3932 3933 if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) { 3934 connType = AudioRoutesInfo.MAIN_HEADSET; 3935 intent.setAction(Intent.ACTION_HEADSET_PLUG); 3936 intent.putExtra("microphone", 1); 3937 } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) { 3938 connType = AudioRoutesInfo.MAIN_HEADPHONES; 3939 intent.setAction(Intent.ACTION_HEADSET_PLUG); 3940 intent.putExtra("microphone", 0); 3941 } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) { 3942 connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 3943 intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); 3944 } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) { 3945 connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 3946 intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); 3947 } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) { 3948 connType = AudioRoutesInfo.MAIN_HDMI; 3949 intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG); 3950 } 3951 3952 synchronized (mCurAudioRoutes) { 3953 if (connType != 0) { 3954 int newConn = mCurAudioRoutes.mMainType; 3955 if (state != 0) { 3956 newConn |= connType; 3957 } else { 3958 newConn &= ~connType; 3959 } 3960 if (newConn != mCurAudioRoutes.mMainType) { 3961 mCurAudioRoutes.mMainType = newConn; 3962 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 3963 SENDMSG_NOOP, 0, 0, null, 0); 3964 } 3965 } 3966 } 3967 3968 final long ident = Binder.clearCallingIdentity(); 3969 try { 3970 ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 3971 } finally { 3972 Binder.restoreCallingIdentity(ident); 3973 } 3974 }
相关文章推荐
- android 4.4的耳机插入检测流程
- Android实现检测耳机插入和拔出
- android 检测耳机是否插入
- Android4.1.2 耳机插入拔出通知流程分析
- Android耳机插入检测
- android 检测耳机是否插入-改进方案
- android实现耳机插入和拔出状态检测
- android耳机插入检测
- Android实现检测耳机插入和拔出
- Android开发:检测耳机的插入状态
- Android编程:检测耳机插入拔出
- [Android开发常见问题-5] 如何检测耳机的插入状态
- Android4.1.2 耳机插入拔出通知流程分析
- android耳机插入检测
- android-检测耳机的插入和拔出动作
- android-检测耳机的插入和拔出动作
- android耳机插入检测
- android 检测耳机是否插入
- android耳机插入检测
- Android -- 检测耳机插入状态