android 4.4的耳机插入检测流程
来源:互联网 发布:淘宝客如何设置优惠券 编辑:程序博客网 时间:2024/04/30 15:58
base/services/java/com/android/server/SystemServer.java
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);
- }
- 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 }
0 0
- android 4.4的耳机插入检测流程
- android 4.4的耳机插入检测流程
- android耳机检测之最复杂的耳机检测流程
- android耳机插入检测
- android耳机插入检测
- android 耳机插入检测
- android耳机插入检测
- android耳机插入检测
- Android耳机插入检测
- Android开发:检测耳机的插入状态
- android 检测耳机是否插入
- android 检测耳机是否插入
- android 检测耳机是否插入
- android 检测耳机是否插入
- android 检测耳机是否插入
- android 检测耳机是否插入
- android 检测耳机是否插入
- android 检测耳机是否插入
- storm local版本本地测试异常汇总
- openfire 集群原理说明
- EasyUI form ajax submit后,在IE下提示下载内容的解决办法
- Linux 下编译Android-VLC开源播放器详解
- else语句
- android 4.4的耳机插入检测流程
- 设计模式六大原则(1):单一职责原则
- 【UGUI】Interaction Components
- mac下sips的用法
- android Sensor一些手机感应效果
- Win7 Jekyll安装(使用64位)
- ubuntu 安装svn及svn使用指南
- Java监视系统剪贴板
- 思科CCNA第二学期第三章答案