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以下

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

方法二

创建前台Service来申请音频焦点,https://developer.android.com/develop/background-work/services/fgs?hl=zh-cn

方法三

添加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);
    }
}
相关推荐
阿巴斯甜1 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95271 天前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android