Android音量调节修改

news/2024/7/16 9:34:22 标签: android, vscode, ide

前言

今日公司,安卓设备的音量显示不正常,让我来修复这个bug,现在已修复,做个博客,记录一下,以后碰到类似一下子就好解决。

Android音量调节相关

路径

frameworks\base\services\core\java\com\android\server\audio\AudioService.java

这个文件包含了关于android音量调节的代码逻辑。

问题

音量调节那里,调小会直接变成0,而且过程我发现他会有跳动的感觉。

思路

找到apk,调用这个文件的接口,添加打印了解对应逻辑。

找到问题点

  • 音量数值对不上
  • 音量多次调用onSetStreamVolume函数(每个音乐流都调用一次)

解决问题

  • 数值对不上(修改apk与底层数值对应关系)

  • 多次调用(把对应干扰流都屏蔽掉)

setStreamVolume接口

/**
     * 设置音频流的音量。
     *
     * @param streamType 要设置音量的音频流类型,例如 AudioManager.STREAM_MUSIC。
     * @param index 要设置的音量索引,通常是一个在音频流范围内的整数值。
     * @param flags 设置标志,包括有关音量设置的额外信息,例如 AudioManager.FLAG_FIXED_VOLUME。
     * @param callingPackage 调用该方法的应用程序的包名。
     * @param caller 调用者的标识。
     * @param uid 调用者的用户标识。
     * @param hasModifyAudioSettings 是否有修改音频设置的权限。
     */
    private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
                                 String caller, int uid, boolean hasModifyAudioSettings) {
        if (DEBUG_VOL) {
            Log.d(TAG, "setStreamVolume(stream=" + streamType + ", index=" + index
                    + ", calling=" + callingPackage + ")");
        }
        if(streamType != 3){
            return ;
        }

        // 如果使用了固定音量,直接返回
        if (mUseFixedVolume) {
            return;
        }
        
        Log.d(TAG, "************************");

        // 确保音频流类型有效
        ensureValidStreamType(streamType);

        // 获取音频流类型别名和对应的音量流状态
        int streamTypeAlias = mStreamVolumeAlias[streamType];
        VolumeStreamState streamState = mStreamStates[streamTypeAlias];

        // 获取与音频流类型别名对应的设备
        final int device = getDeviceForStream(streamType);
        int oldIndex;

        // 如果不是 A2DP 设备,并且标志包含了 AudioManager.FLAG_BLUETOOTH_ABS_VOLUME,
        // 则跳过 A2DP 绝对音量控制请求
        if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
            return;
        }

        // 如果是系统调用(例如硬件按键),检查当前用户以正确处理用户限制
        if (uid == android.os.Process.SYSTEM_UID) {
            uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
        }

        // 验证调用包和 app op 权限
        if (!checkNoteAppOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)) {
            return;
        }

        // 在 Android N 及以上版本,如果音量调整将切换 Zen 模式,
        // 则检查是否已授予调用包通知策略的访问权限
        if (isAndroidNPlus(callingPackage)
                && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
                && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
            throw new SecurityException("Not allowed to change Do Not Disturb state");
        }

        // 如果音量调整在当前 Do Not Disturb 模式下不允许,则直接返回
        if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
            return;
        }

        synchronized (mSafeMediaVolumeStateLock) {
            // 重置任何挂起的音量命令
            mPendingVolumeCommand = null;

            // 获取旧的音量索引
            oldIndex = streamState.getIndex(device);

            // 对索引进行重新缩放
            Log.d(TAG, "缩放前 index=+"+index);
            index = index * 10;//rescaleIndex(index * 10, streamType, streamTypeAlias);
            Log.d(TAG, "缩放后 index=+"+index);

            // 如果音频流类型别名是 STREAM_MUSIC
            // 且设备是 A2DP 设备并且标志不包含 AudioManager.FLAG_BLUETOOTH_ABS_VOLUME,
            // 则发送 Avrcp 绝对音量索引的消息
            if (streamTypeAlias == AudioSystem.STREAM_MUSIC
                    && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                    && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                if (DEBUG_VOL) {
                    Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index
                            + "stream=" + streamType);
                }
                mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
            }

            // 如果设备是 HEARING_AID 设备且音频流是 HEARING_AID 类型,
            // 则发送设置 HEARING_AID 音量索引的消息
            if (device == AudioSystem.DEVICE_OUT_HEARING_AID
                    && streamType == getHearingAidStreamType()) {
                Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
                        + " stream=" + streamType);
                mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
            }

            // 如果音频流类型别名是 STREAM_MUSIC,发送设置系统音频音量的消息
            if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
                setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
            }

            // 清除 AudioManager.FLAG_FIXED_VOLUME 标志
            flags &= ~AudioManager.FLAG_FIXED_VOLUME;

            // 如果音频流类型别名是 STREAM_MUSIC 且是固定音量设备,则设置 AudioManager.FLAG_FIXED_VOLUME 标志
            if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) {
                flags |= AudioManager.FLAG_FIXED_VOLUME;

                // 对于固定音量设备,音量要么为 0,要么为允许的最大值
                if (index != 0) {
                    if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
                            mSafeMediaVolumeDevices.contains(device)) {
                        index = safeMediaVolumeIndex(device);
                    } else {
                        index = streamState.getMaxIndex();
                    }
                }
                Log.d(TAG,"STREAM_MUSIC   index = " + index);
            }

            // 如果音量超出安全范围,显示安全音量警告,并设置挂起的音量命令
            if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
                mVolumeController.postDisplaySafeVolumeWarning(flags);
                mPendingVolumeCommand = new StreamVolumeCommand(
                        streamType, index, flags, device);
            } else {
                // 否则,调用 onSetStreamVolume 设置音量
                onSetStreamVolume(streamType, index, flags, device, caller, hasModifyAudioSettings);
                // 获取最终的音量索引
                index = mStreamStates[streamType].getIndex(device);
                Log.d(TAG, "获取最终的音量索引"+ "index=" + index + ")");
            }
        }

问题 1关键点
在这里插入图片描述
问题 2关键点
在这里插入图片描述

结束

轻描淡写的俩个问题,看上去简单,如果你什么也不知道情况下调试,你就知道了。

刚解决完,马上发一篇博客,帮助更多的人,因为有问题找不到答案真的很无助,做点力所能及的事情吧。


http://www.niftyadmin.cn/n/5350243.html

相关文章

C++ 之LeetCode刷题记录(二十)

😄😊😆😃😄😊😆😃 开始cpp刷题之旅。 依旧是追求耗时0s的一天。 110. 平衡二叉树 给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二…

C 练习实例49-宏#define命令练习3

#ifdef if define 如果define定义了神马&#xff0c;便执行该语句。如果没定义这个&#xff0c;则执行#else语句。注意结尾要加#endif语句 代码&#xff1a; #include <stdio.h> #define Max #define MAXIMUM(x,y) (x,y)?x:y #define MINIMUM(x,y) (x,y)?y:x …

(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第8章 项目整合管理(八)

博主2023年11月通过了信息系统项目管理的考试&#xff0c;考试过程中发现考试的内容全部是教材中的内容&#xff0c;非常符合我学习的思路&#xff0c;因此博主想通过该平台把自己学习过程中的经验和教材博主认为重要的知识点分享给大家&#xff0c;希望更多的人能够通过考试&a…

react 什么是h函数

React 中的 H 函数&#xff0c;通常是指 Hooks&#xff08;钩子&#xff09;函数。Hooks 是 React 16.8 版本引入的新特性&#xff0c;允许你在不写 class 的情况下使用 state 以及其他的 React 特性。Hooks 提供了一种更简洁、更直观的方式来使用 React 的功能&#xff0c;使得…

npm install 一直卡在 sill idealTree 解决方案

npm install 一直卡在 sill idealTree 解决方案 npm install安装vue项目的依赖时&#xff0c;执行 npm install 一直卡在 idealTree:xxx: sill idealTree buildDeps 。 解决方案&#xff1a; 设置淘宝源 npm config set registry https://registry.npm.taobao.org查看是否设置…

GEE错误——Image.displacement: Unable to compute bounds for geometry: <Geometry>.

错误 offset: Layer error: Image.displacement: Unable to compute bounds for geometry: <Geometry>. After Registration: Layer error: Image.displacement: Unable to compute bounds for geometry: <Geometry>. angle: Layer error: Image.displacement: U…

Django实战

一、开发登录表单 def login_form(request):html <html><body><form method"post">用户名:<input name "username" type"text"></input></br>密码&#xff1a;<input name "password" type…

自动求导与可微分编程

1.张量的自动求导 1.1 自动求导机制 张量的自动求导机制是现代深度学习框架&#xff08;如PyTorch和TensorFlow&#xff09;的核心功能之一&#xff0c;它允许开发者在无需手动计算梯度的情况下&#xff0c;自动获得神经网络中所有参数相对于损失函数的梯度。以下是这一机制的…