android 后台应用申请音频焦点失败

现象

app在前台可以申请音频焦点,但是在后台申请音频焦点失败。

原因

HardeningEnforcer.blockFocusMethod方法拒绝了后台app的申请,这个方法的第一个if会判断app是否符合拿到音频焦点的条件。第二if判断如果targetSdk是否小于35,如果小于35也不会拒绝。

java 复制代码
//frameworks/base/services/core/java/com/android/server/audio/HardeningEnforcer.java
/**
 * Checks whether the call in the current thread should be allowed or blocked
 * @return false if the method call is allowed, true if it should be a no-op
 */
@SuppressWarnings("AndroidFrameworkCompatChange")
protected boolean blockFocusMethod(int callingUid, int focusMethod, @NonNull String clientId,
                                   int focusReqType, @NonNull String packageName, String attributionTag, int targetSdk) {

    if (noteOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, callingUid, packageName, attributionTag)) {
        blocked = false;
    } else if (targetSdk < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
        // Build.VERSION_CODES.VANILLA_ICE_CREAM=35
        // 如果targetSdk<35,允许申请音频焦点
        blocked = false;
        unblockedBySdk = true;
    }
    metricsLogFocusReq(blocked, focusReqType, callingUid, unblockedBySdk);
    if (!blocked) {
        // 不允许申请音频焦点
        return false;
    }
    // 允许申请音频焦点
    return true;
}

解决方法

方法一

直接降级targetSdk,改到35以下

ini 复制代码
android {
    defaultConfig {
        targetSdk = 34
    }
}

方法二

创建前台Service来申请音频焦点,developer.android.com/develop/bac...

方法三

添加MODIFY_AUDIO_ROUTING或MODIFY_AUDIO_SETTINGS_PRIVILEGED权限。必须要有系统签名的应用才能获取这个权限。

xml 复制代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING"/>
  <!-- <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED"/> -->

</manifest>

AudioService在申请音频焦点时,会先判断是否有这个权限。如果MODIFY_AUDIO_ROUTING或MODIFY_AUDIO_SETTINGS_PRIVILEGED,就不会调用HardeningEnforcer.blockFocusMethod,自然也不会拒绝音频焦点了。

java 复制代码
//frameworks/base/services/core/java/com/android/server/audio/AudioService.java
public int requestAudioFocus(AudioAttributes aa, int focusReqType, IBinder cb,
                             IAudioFocusDispatcher fd, String clientId, String callingPackageName,
                             String attributionTag, int flags, IAudioPolicyCallback pcb, int sdk) {

    // 检查申请音频焦点的app是否有权限绕过HardeningEnforcer
    // does caller have system privileges to bypass HardeningEnforcer
    boolean permissionOverridesCheck = false;
    if ((mContext.checkCallingOrSelfPermission(MODIFY_AUDIO_SETTINGS_PRIVILEGED)
         == PackageManager.PERMISSION_GRANTED)
        || (mContext.checkCallingOrSelfPermission(MODIFY_AUDIO_ROUTING)
            == PackageManager.PERMISSION_GRANTED)) {
        permissionOverridesCheck = true;
    } else if (uid < UserHandle.AID_APP_START) {
        permissionOverridesCheck = true;
    }

    try {
        if (permissionOverridesCheck) {
            mHardeningEnforcer.metricsLogFocusReq(/*blocked*/ false, focusReqType, uid,
                                                  /*unblockedBySdk*/ false);
        }
        if (!permissionOverridesCheck && mHardeningEnforcer.blockFocusMethod(uid,
                                                                             HardeningEnforcer.METHOD_AUDIO_MANAGER_REQUEST_AUDIO_FOCUS,
                                                                             clientId, focusReqType, callingPackageName, attributionTag, sdk)) {
            // 没有MODIFY_AUDIO_ROUTING权限,并且blockFocusMethod返回false,
            // 才会申请焦点失败
            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
        }
    } finally {
        Binder.restoreCallingIdentity(token);
    }
}
相关推荐
xiangpanf12 小时前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx15 小时前
安卓线程相关
android
消失的旧时光-194315 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon16 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon16 小时前
VSYNC 信号完整流程2
android
dalancon16 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户693717500138417 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android18 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才18 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶19 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle