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

简介: 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 2048, notificationFrames 1024, sessionId 0, transferType 0, flags 0, opPackageName cn.wangy.contacts uid 10059, pid 1917
12-04 10:34:41.814   409  2559 W ServiceManager: Permission failure: android.permission.CAPTURE_AUDIO_OUTPUT from uid=10059 pid=1917
12-04 10:34:41.815   409  2559 D PermissionCache: checking android.permission.CAPTURE_AUDIO_OUTPUT for uid=10059 => denied (548 us)
12-04 10:34:41.815   409  2559 E         : Request requires android.permission.CAPTURE_AUDIO_OUTPUT
12-04 10:34:41.815   409  2559 E AudioFlinger: createRecord() checkRecordThread_l failed
12-04 10:34:41.815   545  2254 E IAudioFlinger: createRecord returned error -22
12-04 10:34:41.815   545  2254 E AudioRecord: AudioFlinger could not create record track, status: -22
12-04 10:34:41.816   545  2254 E StagefrightRecorder: audio source is not initialized
12-04 10:34:41.816   545  2254 D MPEG4Writer: reset+ 1081
12-04 10:34:41.816  1917  1917 E MediaRecorder: start failed: -2147483648
12-04 10:34:41.816  1917  1917 W System.err: java.lang.RuntimeException: start failed.
12-04 10:34:41.825  1917  1917 W System.err:  at android.media.MediaRecorder.start(Native Method)

方法一,给 app 增加 sharedUserId=“android.uid.system”,并使用系统签名


方法二,屏蔽系统源码,跳过权限检查


通过全局搜索,发现权限判断竟然在 c 中,通过 pid 和 vid 来检查


frameworks\av\services\audiopolicy\service\AudioPolicyInterfaceImpl.cpp

frameworks\av\services\audioflinger\ServiceUtilities.cpp

android 8.1

注释 AudioPolicyInterfaceImpl.cpp 中 switch 语句块 status = PERMISSION_DENIED;

或者修改 ServiceUtilities.cpp 中 captureAudioOutputAllowed() 返回 true

if (status == NO_ERROR) {
            // enforce permission (if any) required for each type of input
            switch (inputType) {
            case AudioPolicyInterface::API_INPUT_LEGACY:
                break;
            case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
                // FIXME: use the same permission as for remote submix for now.
            case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
                if (!captureAudioOutputAllowed(pid, uid)) {
                    ALOGE("getInputForAttr() permission allowed: capture allowed");
                    //cczheng annotation for don't check android.Manifest.permission.CAPTURE_AUDIO_OUTPUT
                    /*ALOGE("getInputForAttr() permission denied: capture not allowed");
                    status = PERMISSION_DENIED;*/
                }
                break;
            case AudioPolicyInterface::API_INPUT_MIX_EXT_POLICY_REROUTE:
                if (!modifyAudioRoutingAllowed()) {
                    ALOGE("getInputForAttr() permission denied: modify audio routing not allowed");
                    status = PERMISSION_DENIED;
                }
                break;
            case AudioPolicyInterface::API_INPUT_INVALID:
            default:
                LOG_ALWAYS_FATAL("getInputForAttr() encountered an invalid input type %d",
                        (int)inputType);
            }
        }


android 9.0

9.0 中 AudioPolicyInterfaceImpl.cpp 在 switch 语句块前新增加了包名判断,上面的报错权限就是从这里打印的,注释如下

// check calling permissions
    //cczheng annotation for don't check android.Manifest.permission.CAPTURE_AUDIO_OUTPUT
    /*if (!recordingAllowed(opPackageName, pid, uid)) {
        ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
                __func__, uid, pid);
        return PERMISSION_DENIED;
    }
    if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
        attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
        attr->source == AUDIO_SOURCE_VOICE_CALL) &&
        !captureAudioOutputAllowed(pid, uid)) {
        return PERMISSION_DENIED;
    }*/
    if ((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed(pid, uid)) {
        return BAD_VALUE;
    }
    sp<AudioPolicyEffects>audioPolicyEffects;
    {
        status_t status;
        AudioPolicyInterface::input_type_t inputType;
        Mutex::Autolock _l(mLock);
        {
            AutoCallerClear acc;
            // the audio_in_acoustics_t parameter is ignored by get_input()
            status = mAudioPolicyManager->getInputForAttr(attr, input, session, uid,
                                                         config,
                                                         flags, selectedDeviceId,
                                                         &inputType, portId);
        }
        audioPolicyEffects = mAudioPolicyEffects;
        if (status == NO_ERROR) {
            // enforce permission (if any) required for each type of input
            switch (inputType) {
            case AudioPolicyInterface::API_INPUT_LEGACY:
                break;
            case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
                // FIXME: use the same permission as for remote submix for now.
            case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
                if (!captureAudioOutputAllowed(pid, uid)) {
                    ALOGE("getInputForAttr() permission allowed: capture allowed");
                    //cczheng annotation for don't check android.Manifest.permission.CAPTURE_AUDIO_OUTPUT
                    /*ALOGE("getInputForAttr() permission denied: capture not allowed");
                    status = PERMISSION_DENIED;*/
                }
                break;
            case AudioPolicyInterface::API_INPUT_MIX_EXT_POLICY_REROUTE:
                if (!modifyAudioRoutingAllowed()) {
                    ALOGE("getInputForAttr() permission denied: modify audio routing not allowed");
                    status = PERMISSION_DENIED;
                }
                break;
            case AudioPolicyInterface::API_INPUT_INVALID:
            default:
                LOG_ALWAYS_FATAL("getInputForAttr() encountered an invalid input type %d",
                        (int)inputType);
            }
        }


目录
相关文章
|
8月前
|
定位技术 API 开发工具
Android 按照步骤接入百度地图API,定位显示不了解决办法
Android 按照步骤接入百度地图API,定位显示不了解决办法
233 0
|
2月前
|
编译器 开发工具 Android开发
|
8月前
|
Android开发
android.view.WindowLeaked的解决办法
我们知道Android的每一个Activity都有个WindowManager窗体管理器,同样,构建在某个Activity之上的对话框、PopupWindow也有相应的WindowManager窗体管理器。
62 0
|
8月前
|
Android开发
Android 使用DataBinding时 将布局页面转换为数据绑定布局(Convert to data binding layout) 不出现提示解决办法
Android 使用DataBinding时 将布局页面转换为数据绑定布局(Convert to data binding layout) 不出现提示解决办法
94 0
|
8月前
|
Android开发
Android中使用Tortoise SVN遇到代码被锁定的解决办法
Android中使用Tortoise SVN遇到代码被锁定的解决办法
74 0
|
10月前
|
安全 Android开发
Android 动态权限 permission 操作类简单封装
Android 动态权限 permission 操作类简单封装
|
11月前
|
监控 开发工具 Android开发
AMD机器:Android Studio启动模拟器提示“HAXM is not installed”的解决办法
AMD机器:Android Studio启动模拟器提示“HAXM is not installed”的解决办法
1550 0
|
编解码 机器人 Android开发
Android10.0 OTA 错误解决办法(@/cache/recovery/block.map‘ failed)
Android10.0 OTA 错误解决办法(@/cache/recovery/block.map‘ failed)
456 0
|
Java Android开发 开发者
Android9.0 无锁屏下连续锁屏-解屏2次,画面点击无响应 bug 解决办法
Android9.0 无锁屏下连续锁屏-解屏2次,画面点击无响应 bug 解决办法
101 0
|
Android开发
Android Studio 编译输出中文乱码的解决办法
Android Studio 编译输出中文乱码的解决办法
95 0