安卓漏洞揭秘-android投屏scrcpy支持声音部分调研-千里马framework投屏开发

Android 通话录音功能 通话录音功能因为涉及隐私问题,Android 6.0上就移除官方的通话录音接口,只能通过其他方式去获取调用。 录音时需要设置音频类型,系统中定义以下几种 (MediaRecorder.AudioSource) CAMCORDER 录音来源于同方向的相机麦克风相同,若相机无内置相机或无法识别,则使用预设的麦克风 DEFAULT 默认音频源 MIC 录音来源为主麦克风 REMOTE_SUBMIX 用于远程呈现的音频流的子混音的音频源,需要Manifest.permission.CAPTURE_AU 阅读详情

hi,粉丝朋友们!

今天刚好使用了一下新版本的scrcpy,发现了竟然新版本scrcpy支持了音频,这个不得不说让我十分的感兴趣,这里我刚好给出一下相关的调研结果。

1、scrcpy获取音频方式

大家都知道要获取系统的声音一般需要通过类是如下接口获取系统声音,类是我们说的内录:
builder.setAudioSource(MediaRecorder.AudioSource.REMOTE_SUBMIX);
但是这个REMOTE_SUBMIX是需要权限的,因为这个毕竟属于一个高危险的行为,你想一个任意第三方app即可以随意来内录你的手机系统声音
所以scrcpy可以获取声音了,其实还是和安卓系统权限漏洞有关系拉(可能也不是漏洞,只是被scrcpy刚好发现了可以这样做)
2、scrcpy音频获取原理分析
经过scrcpy代码分析发现其实实现原理方式就是这种
builder.setAudioSource(MediaRecorder.AudioSource.REMOTE_SUBMIX);录制方式:

 private static AudioRecord createAudioRecord() {
        AudioRecord.Builder builder = new AudioRecord.Builder();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            // On older APIs, Workarounds.fillAppInfo() must be called beforehand
            builder.setContext(FakeContext.get());
        }
        builder.setAudioSource(MediaRecorder.AudioSource.REMOTE_SUBMIX);
        builder.setAudioFormat(createAudioFormat());
        int minBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, FORMAT);
        // This buffer size does not impact latency
        builder.setBufferSizeInBytes(8 * minBufferSize);
        return builder.build();
    }

但是这个调用其实很简单,就是关键在与权限,为啥这个scrcpy可以获取到这个REMOTE_SUBMIX

    <!-- Allows an application to capture audio output.
         Use the {@code CAPTURE_MEDIA_OUTPUT} permission if only the {@code USAGE_UNKNOWN}),
         {@code USAGE_MEDIA}) or {@code USAGE_GAME}) usages are intended to be captured.
         <p>Not for use by third-party applications.</p> -->
    <permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"
        android:protectionLevel="signature|privileged|role" />

明显看出这里需要platform签名和privileged等
但是scrcpy都不具有这些
那么是怎么实现可以正常调用呢?
这里我经过去相关权限

 @Override
        @PermissionCheckerManager.PermissionResult
        public int checkPermission(@NonNull String permission,
                @NonNull AttributionSourceState attributionSourceState, @Nullable String message,
                boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource,
                int attributedOp) {
            Objects.requireNonNull(permission);
            Objects.requireNonNull(attributionSourceState);
            final AttributionSource attributionSource = new AttributionSource(
                    attributionSourceState);
            android.util.Log.i("lsm","checkPermission permission " + permission + " attributionSource = " + attributionSource);
            final int result = checkPermission(mContext, mPermissionManagerServiceInternal,
                    permission, attributionSource, message, forDataDelivery, startDataDelivery,
                    fromDatasource, attributedOp);
            // Finish any started op if some step in the attribution chain failed.
            if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED
                    && result != PermissionChecker.PERMISSION_SOFT_DENIED) {
                if (attributedOp == AppOpsManager.OP_NONE) {
                    finishDataDelivery(AppOpsManager.permissionToOpCode(permission),
                            attributionSource.asState(), fromDatasource);
                } else {
                    finishDataDelivery(attributedOp, attributionSource.asState(), fromDatasource);
                }
            }
            return result;
        }

加入打印后如下:

03-07 18:09:07.367  2240  2597 I lsm     : checkPermission permission android.permission.CAPTURE_AUDIO_OUTPUT attributionSource = AttributionSource { uid = 2000, packageName = com.android.shell, attributionTag = null, token = android.os.BinderProxy@584a956, next = null }

发现居然这里检测的uid 2000这个大家都可以理解,因为scrcpy本身user就是shell,但是这里的packageName = com.android.shell,是从哪里来的?
这里就需要看看,哪怕是这个包名又怎么可以获取CAPTURE_AUDIO_OUTPUT呢?

1、这里先解决第一个为啥packageName = com.android.shell

在s上其实就是靠这个

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            // On older APIs, Workarounds.fillAppInfo() must be called beforehand
            builder.setContext(FakeContext.get());
        }

FakeContext代码如下:

public final class FakeContext extends ContextWrapper {

    public static final String PACKAGE_NAME = "com.android.shell";
    public static final int ROOT_UID = 0; // Like android.os.Process.ROOT_UID, but before API 29

    private static final FakeContext INSTANCE = new FakeContext();

    public static FakeContext get() {
        return INSTANCE;
    }

    private FakeContext() {
        super(null);
    }

    @Override
    public String getPackageName() {
        return PACKAGE_NAME;
    }

    @Override
    public String getOpPackageName() {
        return PACKAGE_NAME;
    }

    @TargetApi(Build.VERSION_CODES.S)
    @Override
    public AttributionSource getAttributionSource() {
        AttributionSource.Builder builder = new AttributionSource.Builder(Process.SHELL_UID);
        builder.setPackageName(PACKAGE_NAME);
        return builder.build();
    }
}

所以综合大概就知道原来是调用时候传递了一个Context进去

当然同时也会有疑问,那么如果不传递是否可以?android 12就没有传递,为啥也可以,其实这里我经过验证哪怕屏蔽
builder.setContext(FakeContext.get());其实也是可以正常有一个packageName = com.android.shell
这样来看好像这个Context设置就不是最关键的,那肯定还有其他地方进行设置,经过寻找发现这这里也进行设置,如果Context为null时候:

private AudioRecord(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
            int sessionId, @Nullable Context context,
            int maxSharedAudioHistoryMs) throws IllegalArgumentException {
        //省略

        AttributionSource attributionSource = (context != null)
                ? context.getAttributionSource() : AttributionSource.myAttributionSource();
        //省略
    }

  public static @NonNull AttributionSource myAttributionSource() {
//省略
        try {
            if (uid == Process.SHELL_UID) {
                android.util.Log.i("lsm","uid Process.SHELL_UID packageName = "+ AppGlobals.getPackageManager().getPackagesForUid(uid)[0]);
            }
            //这里最为关键,或根据uid从AppGlobals.getPackageManager().getPackagesForUid查询的第一个作为packageName
            return new AttributionSource.Builder(uid)
                .setPackageName(AppGlobals.getPackageManager().getPackagesForUid(uid)[0])
                .build();
        } catch (Exception ignored) {
        }

        throw new IllegalStateException("Failed to resolve AttributionSource");
    }

加入对应打印如下:

03-07 18:09:07.356  4700  4730 I lsm     : uid Process.SHELL_UID packageName = com.android.shell

2、为啥com.android.shell就可以获取权限?

com.android.shell其实是Shell.apk这个Shell.apk当然属于platform签名,那么也就可以说明已经可以得到系统授权了,当然那也要manifest中有对应的权限声明才可以阿,哈哈,其实这样真相如下:

在这里插入图片描述

那么scrcpy整体可以支持音频就解密了
在这里插入图片描述

Windows下用scrcpy实现手机投屏:如何单独投声音或画面(附完整脚本) 本文详细介绍了在Windows平台下使用scrcpy实现手机投屏的高级技巧,特别是如何单独投声音或画面。通过完整的脚本示例和参数配置,帮助用户灵活控制音视频传输,适用于音乐播放、游戏录制等多种场景。 阅读详情

相关推荐

解决scrcpy投屏无声问题的完整指南

Android设备投屏技术通过ADB协议实现设备屏幕的实时镜像,其中音频转发是关键技术难点之一。scrcpy作为主流开源投屏工具,其音频模块依赖系统级音频捕获和编解码器转码,需要特定Android版本和编译参数支持。在音视频同步、低延迟传输等工程实践中,开发者常遇到权限配置、编解码兼容等问题。本文针对Android 11+设备的音频转发需求,详细解析scrcpy的编译参数调整、运行时调试技巧,并提供sndcpy等替代方案,帮助解决开发测试中的无声故障。

weixin_29189373的博客 396

Android audio设置投屏和喇叭双输出

在 Android13 平台上,使用 USB 投屏工具scrcpy,投屏到电脑端时,声音被截到 电脑端播放,Android设备 端静音,在Android11及之前都是 在Android设备端正常播放。

sdkdlwk的博客 4万+

结构设计3D拆件与骨架模型构建实战:基于Creo 8.0的5个高效建模技巧

本文详细解析了基于Creo 8.0的结构设计3D拆件与骨架模型构建实战技巧,涵盖5个高效建模方法,包括参数化驱动、曲面分割、多实体协同设计等。通过骨架模型的智能应用,设计效率可提升30%以上,特别适合复杂产品的结构设计。文章还提供了TWS耳机充电仓等实战案例,帮助工程师快速掌握工业设计中的核心建模技术。

weixin_30000735的博客 572

com.android.shell精简,Ticwear adb 无损系统精简

前言Ticwear(主要搭载于Ticwatch)是国内手表操作系统目前体验最好的,也是功能最完善的。但近期其大幅增加新功能,导致应用启动器图标数量众多,寻找app困难。同时很多系统应用可能并不经常使用甚至根本不用,在tic官方由于各种原因短时间内不会自主精简的情况下只能出此下策。希望可以帮到有需要的朋友。警告:按照此教程精简产生的任何后果(包括但不限于系统无法更新)自行承担由于tic系统更新,可能...

weixin_31212247的博客 1953

【实战学习(五)】开源项目学习之uWSGI的部署以及配合nginx

文章目录1)uWSGI是什么?1.1 WSGI1.1.1 Application端1.1.2 Server端1.1.3 WSGI中间件1.2 uwgi1.3 uWSGI、WSGI、uwsgi之间的关系*为什么有了uWSGI为什么还需要nginx?2)连接uwsgi和Django*避坑之Windows10安装uWSGI非常极其艰难,最好勿浪费时间,直接转战Linux吧:2.1 uWGI部署2.1.1 在虚拟环境下安装uwsgi:2.1.2 测试uWSGI的运行2.1.3 使用uWSGI运行Django项目2.

黑黑白白君的博客 1507

2025华东杯A/B/C题解题思路+可运行代码参考

这些因素包括但不限于:助滑坡的坡度、运动员的质量、滑雪板的接触面与雪地的摩擦力、空气阻力系数、运动员的体型和衣物形态等。助滑坡是运动员滑行至起跳台前的最后一段坡道,这一段坡道的坡度、长度和运动员的姿势会直接影响到起跳时的初始速度。运动员的滑行速度不仅受助滑坡的坡度影响,还受到摩擦力、空气阻力和重力等多方面因素的影响。通过合理的姿势调整,运动员能够有效减少空气阻力,增加身体的重力加速度,进而提升滑行速度。助滑坡的角度通常介于10°到12°之间,而运动员的滑行速度将受到重力、摩擦力和空气阻力的共同作用。

qq_52590045的博客 1797

[CM311-1A]- Android 文件/目录 管理

adb 查看/连接 设备命令 adb 下载上传文件命令 pull 下载文件 push 上传文件 Android 目录操作命令 cd 切换目录命令 ls 查看目录命令 mkdir 创建目录命令 cp 复制目录命令 mv 剪切或重命名目录 rm 删除目录命令 Android 文件操作命令 创建文件命令 查看文件内容命令 cp 复制文件命令 mv 剪切或重命名文件 删除文件命令 编辑文件命令 使用 ed 编辑文件!!! Android/Linux 的 7 种文件类型 ls/file/stat 查看文件类型命令..

燃吹 U 客帮 1727

逆向Shopee签名机制:从参数分析到稳定采集方案

本文深入解析了Shopee签名机制的逆向过程,从参数分析到稳定采集方案的实现。通过抓包定位关键参数`sap-ri`和`x-sap-sec`,还原了签名生成算法,并提供了Python实现代码。文章还分享了反反爬策略、性能优化技巧及长期维护建议,帮助开发者构建稳定的Shopee数据采集方案。

weixin_27722377的博客 672

windwos脚本 | 基于scrcpy,只投声音、只投画面

【代码】windwos脚本 | 基于scrcpy,只投声音、只投画面。

专注于C/C++/Linux领域创作 1011

企业IT运维实录:批量部署银河麒麟V10-SP1,Ghost镜像与UKey激活实战

本文详细介绍了企业级银河麒麟V10-SP1操作系统的批量部署全流程,包括标准化镜像制作、自动化封装技术、网络化部署方案及UKey集群激活方案。通过实战案例和技术要点解析,帮助企业IT运维团队大幅提升部署效率,确保系统安全与稳定性。

weixin_30729609的博客 388

GEE数据融合——Landsat (collection 2,level 2 )4、5、7、8、9长时间序列影像数据融合和视频导出分析

长时间序列影像数据融合是指将Landsat影像数据集合2级2(Level 2)中的4、5、7、8和9这五个卫星的数据进行融合。具体来说,这包括将同一地点的多个卫星影像数据进行处理和整合,以产生一个单一的、具有更高质量的影像产品。在长时间序列影像数据融合中,首先需要对不同卫星的影像数据进行校正,以消除不同卫星之间的光谱差异、辐射度问题和几何纠正误差等。然后,通过使用融合算法,将多个卫星的影像数据进行组合,以生成一张全新的、高质量的合成影像。

此星光明博客 1734

scrcpy安装升级 安卓开发 投屏安卓设备到电脑端

scrcpy 配置

shuangrenlong的博客 1625

Python爬虫博客:爬取碳排放交易数据——使用最新技术的完整实现

通过上述方法,我们可以构建一个高效的爬虫,爬取碳排放交易市场的数据并进行分析。这个项目不仅展示了如何处理静态和动态网页,还提供了如何存储数据、分析数据和可视化结果的技巧。随着爬虫技术的不断进步,我们可以进一步提升爬取效率和数据分析能力。如果你希望更深入了解如何进行数据挖掘和机器学习分析,可以尝试将碳排放数据与其他经济数据结合,利用机器学习模型进行趋势预测或决策支持。

2201_76125261的博客 351

Permission failure: android.permission.CAPTURE_AUDIO_OUTPUT 解决办法

在 android M 以上,MediaRecorder 录音时音源设置为 VOICE_CALL,开始录音时会抛出权限异常 12-04 10:34:41.808 545 2254 D AudioRecord: set(): 0xe90ba000, inputSource 4, sampleRate 44100, format 0x1, channelMask 0x10, frameCount...

cczhengv 8421

StarRocks 面试题及参考答案详解(万字详解)

Broker Load的过程通常涉及到数据的解析、转换和加载,它支持多种数据格式,并且可以处理复杂的数据导入任务。一方面,压缩可以减少磁盘I/O操作,因为压缩后的数据占用的空间更小,需要读取的数据块数量也就更少。在StarRocks中,表数据可以被划分成多个分区,每个分区包含表的一部分数据。在传统的行存储模型中,数据是按行组织的,这意味着在执行分析查询时,系统需要读取并处理整行数据,即使很多时候只需要查询其中的少数几列。物化视图的更新可以是完全重算,也可以是增量更新,取决于物化视图的定义和数据变更的模式。

大模型大数据攻城狮的专栏 2082

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android开发中常用的shell脚本和bat脚本命令

1. 当需要跳转到某个路径下执行操作就可以使用cd命令,下面表示将当前的路径跳转到C:\ZhouXi下 C:\shellShow>cd C:\ZhouXi ---------//cd就是change directory的缩写 C:\ZhouXi> 2. 当需要调试手机,但是不确定手机是否连接上的时候可以使用adb devices查看当前连接的设备 C:\ZhouXi>adb devices List of devices attached FRU6R204260

洲汐的博客 1838

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

android shell 定位 命令,【Adb shell】---玩转 Android系统 查询 应用包名 命令

1:列出所有应用的包名pm list packagesrk3288:/ $ pm list packagespackage:com.android.cts.priv.ctsshimpackage:com.android.providers.telephonypackage:com.android.providers.calendarpackage:com.android.providers.med...

weixin_29994587的博客 3370

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

如何使Android录音实现内录功能

原址 背景 之前在做直播的时候需要使用到内录功能,比如经常看到游戏主播在直播玩游戏,游戏的声音不是通过MIC录制的,而是内录完成的。故在此记录一下。 相信大家都很熟悉Android如果录音的了: int frequency = 44100; int audioEncoding = AudioFormat.ENCODING_PCM

Android系统攻城狮 1万+

QtScrcpy+Bandicam实现在windows上录制Android的屏幕+声音

QtScrcpy的Girhub地址:Releases · barry-ran/QtScrcpy (github.com)QtScrcpy链接:https://pan.baidu.com/s/1QlCHQ4qcEs9qJetJi3ZW_w?pwd=1015提取码:1015Bandicam链接:https://pan.baidu.com/s/1zr9khglpZRMDEXFhkWADlA?pwd=1015提取码:1015两个都是不需要安装的,解压后打开exe文件就行了。

weixin_51757406的博客 2291

android11不能root,Android11 Root启动无法访问 com.android.shell 目录

google/coral/coral:11/RPB1.200504.018/6520161:user/release-keysWARNING: run as root is experimental!!!checking for server..fail[command] pm path me.piebridge.breventpackage:/data/app/~~4ONAvCk0b-C7WO2...

weixin_42515089的博客 1093

Android 10 Audio系统:REMOTE_SUBMIX 实现原理

Android10 Audio系统:REMOTE_SUBMIX 实现原理前言什么是REMOTE_SUBMIX怎么使用REMOTE_SUBMIX如何实现的创建REMOTE_SUBMIX类型的 input输入设备创建output设备如何通过output设备采集到数据小结 前言 由于业务需求,需要对Android设备的音频输出进行采集,同时还需要保持Android本身设备的输出。Android原生是无法实现的,因为使用了REMOTE_SUBMIX 之后,Android本身喇叭输出会停止,所以需要对音频系统进行一定

biandan1231的专栏 1万+

【免费下载】 探索 Android Shell:一款强大的Android命令行工具

**Android Shell** 是一个由 JRummyApps 开发的开源项目,它为 Android 设备提供了一个功能丰富的命令行接口(CLI),让你可以在没有 root 权限的情况下执行许多系统级别的操作。这个项目旨在让开发者、爱好者和高级用户能够更深入地掌控他们的设备,实现自动化任务,甚至进行性能优化。 ## 技术分析 Android Shell 基于 Android 的 `dalv...

gitblog_00092的博客 5031

Cursor试用限制如何突破?go-cursor-help开源工具的深度技术解析

# Cursor试用限制如何突破?go-cursor-help开源工具的深度技术解析 面对Cursor AI编程助手试用限制的技术挑战,go-cursor-help项目提供了一套完整的设备标识重置解决方案。这款开源工具通过设备ID修改、配置文件清理和进程管理三大核心技术,实现了Cursor试用状态的智能重置,为开发者提供了持续使用AI辅助编程功能的技术路径。 ## 技术架构深度解析:设备标识重

gitblog_01238的博客 1048

scrcpy音频传输技术:从Android 11到最新版本

scrcpy音频传输技术:从Android 11到最新版本 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/gh_m...

gitblog_01091的博客 1402

android手机执行shell脚本

注意: 1.手机必须root 2.shell脚本需要有执行权限 流程: 1.编写shell脚本 #!/system/bin/sh i=1 while [ $i -le 100 ] do let i++ sleep 2 input swipe 100 950 200 300 150 done 解释:每隔2秒滑屏一次,一共滑动100次(这个脚本比较简单,明白流程后可自行优化) 2.把shell脚本传到/data/目录(/system目录也可以) ...

quarles123的专栏 1万+
上一篇: aosp11/12/13 壁纸高斯模糊,毛玻璃SurfaceFlinger层面原理-第二节千里马framework实战
下一篇: 安卓车机手机系统开发--多窗口模式之PIP详细讲解
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值