zoukankan      html  css  js  c++  java
  • 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 来检查

    frameworksavservicesaudiopolicyserviceAudioPolicyInterfaceImpl.cpp
    frameworksavservicesaudioflingerServiceUtilities.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);
                }
            }
    
    
  • 相关阅读:
    根据访问ip的地区跳转到指定地址
    js生成vCard,以及格式参数详细说明
    min_to_split_multiprocessing多进程,用于平时快速补充数据
    min_to_split.py按日存储到按个股存储
    readzip_minute_data 多进程处理数据
    打包成7zfile,to7zfile
    baostock_multiprocessing 多进程取数据
    终止阻塞线程(有共享锁的线程无效)
    readzip_add_maxL3多线程
    readzip_add_maxL2
  • 原文地址:https://www.cnblogs.com/cczheng-666/p/12607001.html
Copyright © 2011-2022 走看看