Android12 不依赖运行时权限使用蓝牙Sco

背景

在Android 12+上,Android添加了一个新的运行时权限BLUETOOTH_CONNECT,官方解释是

Required to be able to connect to paired Bluetooth devices. 看起来要配对蓝牙就一定需要这个权限了。可是这个权限是Dangerous,这样就得弹窗申请了,有没有可能不用这个权限,依旧可以配对蓝牙。

通过分析业界的产品,发现有的产品可以做到,这样就需要看看是如何实现的了。

分析

首先dumpsys 看看能否找到线索,分析音频蓝牙相关的调用就需要看 dumpsys audio, dumpsys media.metrics, 在机器上操作了下,发现的确使用了通话音量,并且也有连接sco的记录,这就证明了这个产品的确做到了。

比如dumpsys audio下有以下信息记录:

10-18 11:35:14:511 setCommunicationRouteForClient for pid: 20191 device: AudioDeviceAttributes: role:output type:bt_sco addr: from API: startBluetoothSco()) from u/pid:10324/20191
10-18 11:35:14:512 startBluetoothSco()) from u/pid:10324/20191
10-18 11:35:14:529 onUpdateCommunicationRoute, preferredCommunicationDevice: null eventSource: startBluetoothSco()) from u/pid:10324/20191
10-18 11:35:14:542 removePreferredDevicesForStrategySync, strategy: 15
10-18 11:35:15:309 onUpdateCommunicationRoute, preferredCommunicationDevice: AudioDeviceAttributes: role:output type:bt_sco addr:9C:FC:28:59:5E:C1 eventSource: setBluetoothScoOn(true) from u/pid:1002/13471
10-18 11:35:15:312 onUpdateCommunicationRoute, preferredCommunicationDevice: AudioDeviceAttributes: role:output type:bt_sco addr:9C:FC:28:59:5E:C1 eventSource: BtHelper.receiveBtEvent
10-18 11:35:15:313 setPreferredDevicesForStrategySync, strategy: 15 devices: [AudioDeviceAttributes: role:output type:bt_sco addr:9C:FC:28:59:5E:C1]

可是dumpsys 里看不出来调用什么接口感知到蓝牙设备了,接下来就得通过hook了,对于这种问题,应该用objection就够了。和音频相关的类主要是Audio.Media.AudioManager, 那直接hook这个类的所有方法就好了。

指令如下:

 android hooking watch class android.media.AudioManager

这时候操作下应用,就看到了一个可疑的调用registerAudioDeviceCallback

接下来继续hook这个方法

android hooking watch class_method android.media.AudioManager.registerAudioDeviceCallback --dump-args --dump-ba
cktrace --dump-return

这下子就看到了具体调用了

[usb] # (agent) [681721] Called android.media.AudioManager.registerAudioDeviceCallback(android.media.AudioDeviceCallback, android.os.Handler)
(agent) [681721] Backtrace:
        android.media.AudioManager.registerAudioDeviceCallback(Native Method)

这样就基本锁定了方向,接下来研究下这个方法,

     * Registers an {@link AudioDeviceCallback} object to receive notifications of changes
     * to the set of connected audio devices.
     * @param callback The {@link AudioDeviceCallback} object to receive connect/disconnect
     * notifications.
     * @param handler Specifies the {@link Handler} object for the thread on which to execute
     * the callback. If <code>null</code>, the {@link Handler} associated with the main
     * {@link Looper} will be used.
     */
    public void registerAudioDeviceCallback(AudioDeviceCallback callback,
            @Nullable Handler handler) {
        synchronized (mDeviceCallbacks) {
            if (callback != null && !mDeviceCallbacks.containsKey(callback)) {
                if (mDeviceCallbacks.size() == 0) {
                    if (mPortListener == null) {
                        mPortListener = new OnAmPortUpdateListener();
                    }
                    registerAudioPortUpdateListener(mPortListener);
                }
                NativeEventHandlerDelegate delegate =
                        new NativeEventHandlerDelegate(callback, handler);
                mDeviceCallbacks.put(callback, delegate);
                broadcastDeviceListChange_sync(delegate.getHandler());
            }
        }
    }

看起来这个方法会以回调形式提供所有的路由设备变化,而蓝牙对应的Flag就是TYPE_BLUETOOTH_A2DP, TYPE_BLUETOOTH_SCO,用demo 验证了下,的确不需要运行时权限也可以感知到。

到了这儿还没有结束,对于Android12, 通过广播感知sco的连接状态也需要运行时权限,看了下对比产品,没有感知sco的连接结果,而我们的产品有这块的检测,为了保持逻辑一致,也需要想办法感知到到sco的连接结果。这下就不能对比了,不过看了下开启sco的api,有如下的介绍:

 /**
     * Start bluetooth SCO audio connection.
     * <p>Requires Permission:
     *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
     * <p>This method can be used by applications wanting to send and received audio
     * to/from a bluetooth SCO headset while the phone is not in call.
     * <p>As the SCO connection establishment can take several seconds,
     * applications should not rely on the connection to be available when the method
     * returns but instead register to receive the intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED}
     * and wait for the state to be {@link #SCO_AUDIO_STATE_CONNECTED}.
     * <p>As the ACTION_SCO_AUDIO_STATE_UPDATED intent is sticky, the application can check the SCO
     * audio state before calling startBluetoothSco() by reading the intent returned by the receiver
     * registration. If the state is already CONNECTED, no state change will be received via the
     * intent after calling startBluetoothSco(). It is however useful to call startBluetoothSco()
     * so that the connection stays active in case the current initiator stops the connection.
     * <p>Unless the connection is already active as described above, the state will always
     * transition from DISCONNECTED to CONNECTING and then either to CONNECTED if the connection
     * succeeds or back to DISCONNECTED if the connection fails (e.g no headset is connected).
     * <p>When finished with the SCO connection or if the establishment fails, the application must
     * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection.
     * <p>Even if a SCO connection is established, the following restrictions apply on audio
     * output streams so that they can be routed to SCO headset:

也就是通过注册ACTION_SCO_AUDIO_STATE_UPDATED 广播,由于这个广播是粘性的,那么就可以同步感知到sco连接结果了。再在demo上验证了下,的确没问题。

安全隐私话题越来越被重视,对于产品,涉及到使用运行时权限一定需要谨慎一些。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容