Android 耳机插拔处理流程

最近遇到一个bug: 当播放音乐时,插拔耳机,此时闹钟响起,闹钟响铃没有声音。

刚开始以为是闹钟问题,浪费了不少时间,后来发现,插拔耳机后,音乐播放也会出现没有声音。

使用命令,

adb shell getevent 发现,插拔耳机时,底层事件有正常上报。

adb shell  parameter status >  status.log  查看,log中,当耳机拔出后,还是HeadSet状态,此时扬声器模式是disabled的,所以没有声音,再次插入耳机就有声音了。log属于特定打印,不同机子不一样。

SelectedInputDevice = <none>

SelectedOutputDevice = Headset

因此,特地代码跟踪了一下耳机处理流程。 参考了几篇大牛们的博客。

代码版本主要以Android 4.4和Android 5.0的为主。

主要有两种处理方式、

  1. UEvent
  2. InputEvent

Android 系统默认是使用UEvent的方式。两种模式的切换可以使用配置项来完成。

在:android4.4/frameworks/base/core/res/res/values/config.xml 中有

config.xml:1151:    <bool name="config_useDevInputEventForAudioJack">false</bool>  配置项。当为false 则使用UEVent方式,为true则使用InputEvent方式,现在大多使用后者,具体得看厂商的定制代码。

比如我这里的device目录下,配置为true,使用的InputEvent方式。

xxx_rtfsc@xxx-HP-EliteDesk-880-G1-TWR:~/rtfsc/xxxxx_5.0/device$ grep -rn config_useDevInputEventForAudioJack
xxxx/common/overlays_aosp/frameworks/base/core/res/res/values/config.xml:40:    <bool name="config_useDevInputEventForAudioJack">true</bool>



一 InputEvent

这种方式主要InputManagerService.java(framework/base/services/java/com/android/server/input/InputManagerService.java)中处理。

在InputManagerService的构造函数中,获取config_useDevInputEventForAudioJack的值,判断当前是否是使用InputEvent模式。

        //判断当前是否使用InputEvent实现插拔检测。
        //true:InputEvent;fasle:UEvent模式
        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);

当底层事件上报后,会转到InputManagerService的 notifySwitch方法中处理,然后回调到 WiredAccessoryManager中,。


    // Native callback.
    private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
        if (DEBUG) {
            Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
                    + ", mask=" + Integer.toHexString(switchMask));
        }

        if ((switchMask & SW_LID_BIT) != 0) {
            final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
            mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
        }

        if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
            //此时回调到WiredAccessoryManager.java中
            mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
                    switchMask);
        }
    }

提问: notifyWiredAccessoryChanged传递的参数分别是?

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Android中,可以通过监听耳机插拔广播来检测耳机的插入和拔出事件。广播接收器可以通过实现BroadcastReceiver类来处理这些广播事件。通过注册一个广播接收器,并设置接收的广播事件为Intent.ACTION_HEADSET_PLUG,可以监听耳机插拔状态。在onReceive方法中,可以通过intent.getIntExtra("state", 0)来获取耳机的状态,其中1代表耳机插入,2代表耳机拔出。通过在onReceive方法中处理具体的逻辑,可以根据耳机插拔状态进行相应的操作,比如显示Toast提示信息。当需要监听耳机插拔事件时,可以在代码中创建一个BroadcastReceiver对象,并将其注册到系统中,如通过调用registerReceiver方法注册广播接收器。这样,当耳机插入或拔出时,广播接收器就会接收到相关的广播事件,从而可以进行相应的处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [android 不打开APP的情况下监听耳机插拔情况](https://blog.csdn.net/weixin_28872035/article/details/117540394)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Android 平时用到比较多的广播之飞行模式和耳机插拔](https://blog.csdn.net/qq_27062249/article/details/54962483)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值