以下是调节音量的流程:

Step_1.首先在调节机台Volume_Up_Key & Volume_Down_Key操作时,系统会调用到AudioManager.java中handleKeyUp & handleKeyDown函数,以 handleKeyDown函数为例:

1 public void handleKeyDown(KeyEvent event, int stream) {

2 int keyCode = event.getKeyCode();

3 switch (keyCode) {

4 case KeyEvent.KEYCODE_VOLUME_UP: /*KeyEvent 在KeyEvent.java中定义*/

5 case KeyEvent.KEYCODE_VOLUME_DOWN:

6

7 int flags = FLAG_SHOW_UI | FLAG_VIBRATE;

8

9 if (mUseMasterVolume) {

10 adjustMasterVolume(

11 keyCode == KeyEvent.KEYCODE_VOLUME_UP

12 ? ADJUST_RAISE

13 : ADJUST_LOWER,

14 flags);

15 } else {

16 adjustSuggestedStreamVolume(

17 keyCode == KeyEvent.KEYCODE_VOLUME_UP

18 ? ADJUST_RAISE

19 : ADJUST_LOWER,

20 stream,

21 flags);

22 }

23 break;

24        ... ...

25 }

26 }

其中是否进入adjustMasterVolume函数是通过mUseMasterVolume的值判断的,而mUseMasterVolume的值是在AudioManager的构造函数中定义,其值的大小如下:mUseMasterVolume = mContext.getResources().getBoolean(com.android.internal.R.bool.config_useMasterVolume),所以首先从系统的配置文件config.xml中查找config_useMasterVolume值的大小

false

所以handleKeyDown中 switch语句中会选择进入adjustSuggestedStreamVolume函数。

1 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {

2 IAudioService service = getService();

3 try {

4 if (mUseMasterVolume) {

5 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());

6 } else {

7 service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags,

8 mContext.getOpPackageName());

9 }

10   ... ...

11      }

12 }

Step_2.在adjustSuggestedStreamVolume函数中首先会通过binder机制得到AudioService,并将音量控制过程转入到AudioService.java中。

1 public void adjustStreamVolume(int streamType, int direction, int flags,

2 String callingPackage) {

3 ... ...

4 /*音量调大时,若要超过SafeMediaVolume时,系统会弹出对话框给予确认*/

5 if ((direction == AudioManager.ADJUST_RAISE) &&

6 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {

7 Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);

8 mVolumePanel.postDisplaySafeVolumeWarning(flags);

9 } else if (streamState.adjustIndex(direction * step, device)) {

10 sendMsg(mAudioHandler,

11 MSG_SET_DEVICE_VOLUME, /*需要处理的Message值*/

12 SENDMSG_QUEUE,

13 device,

14 0,

15 streamState,

16 0);

17 }

18 }

19 int index = mStreamStates[streamType].getIndex(device);

20 sendVolumeUpdate(streamType, oldIndex, index, flags); /*通知上层更新Volume*/

21 }

在adjustStreamVolume 中会通过sendMsg的方式来将调节音量的事件加入到消息列队SENDMSG_QUENE中,当轮寻到该Message时,系统会调用handleMessage函数来处理该Message,此时该处对应的Message为MSG_SET_DEVICE_VOLUME。

1 public void handleMessage(Message msg) {

2

3 switch (msg.what) {

4

5 case MSG_SET_DEVICE_VOLUME:

6 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);

7 break;

8

9 case MSG_SET_ALL_VOLUMES:

10 setAllVolumes((VolumeStreamState) msg.obj);

11 break;

12

13   ... ...

14 }

15 }

可以发现当msg.what =  MSG_SET_DEVICE_VOLUME时,会进到setDeviceVolume函数中,继续往下分析:

1 private void setDeviceVolume(VolumeStreamState streamState, int device) {

2

3 // Apply volume

4 streamState.applyDeviceVolume(device);

5

6 // Apply change to all streams using this one as alias

7      ... ...

8

9 // Post a persist volume msg

10      ... ...

11 }

applyDeviceVolume就是将音量Volume设置到对应的设备Device上,继续往下分析:

1 public void applyDeviceVolume(int device) {

2 int index;

3 if (isMuted()) {

4 index = 0;

5 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&

6 mAvrcpAbsVolSupported) {

7 index = (mIndexMax + 5)/10;

8 } else {

9 index = (getIndex(device) + 5)/10;

10 }

11 AudioSystem.setStreamVolumeIndex(mStreamType, index, device);

12 }

此处VolumeIndex就是对应UI界面调节音量时,音量所处在的位置下标。在AudioService.java中定义了每种音频流对应的Max-Index,在AudioManager.java中定义了每种音频流在第一次刷机后默认的Index。

Step_3.此时得到音量的下标Index后,会调用AudioSystem.java中的setStreamVolumeIndex函数中来得到此时音量的放大倍数。通过JNI层调用到AudioSystem.cpp文件中的 setStreamVolumeIndex中。

1 status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,

2 int index,

3 audio_devices_t device)

4 {

5 const sp& aps = AudioSystem::get_audio_policy_service();

6 if (aps == 0) return PERMISSION_DENIED;

7 return aps->setStreamVolumeIndex(stream, index, device);

8 }

setStreamVolumeIndex函数中比较简单,通过StrongPointer来与AudioPolicyService建立联系,将AudioSystem中的setStreamVolumeIndex操作移到aps中完成。下面进入到AudioPolicyService.cpp文件中的setStreamVolumeIndex继续分析:

1 status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,

2 int index,

3 audio_devices_t device)

4 {

5 ... ...

6 if (mpAudioPolicy->set_stream_volume_index_for_device) {

7 return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy,

8 stream,

9 index,

10 device);

11 } else {

12 return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);

13 }

14 }

Step_4.AudioPolicyService.cpp作为bn端,其对应的bp端为AudioPolicyManagerBase.cpp。在当前函数的if语句中判断AudioPolicyManagerBase.cpp文件中是否存在setStreamVolumeIndexForDevice函数,条件成立则会选择setStreamVolumeIndexForDevice作为函数入口端;否则选择setStreamVolumeIndex作为函数入口。现在进入AudioPolicyManagerBase.cpp中文件中完成最后的分析:

1 status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream,

2 int index,

3 audio_devices_t device)

4 {

5 ... ...

6 // compute and apply stream volume on all outputs according to connected device

7 status_t status = NO_ERROR;

8 for (size_t i = 0; i < mOutputs.size(); i++) {

9 audio_devices_t curDevice =

10 getDeviceForVolume(mOutputs.valueAt(i)->device());

11 if ((device == AUDIO_DEVICE_OUT_DEFAULT) || (device == curDevice)) {

12 status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);

13 if (volStatus != NO_ERROR) {

14 status = volStatus;

15 }

16 }

17 }

18 return status;

19 }

继续调用checkAndSetVolume函数:

1 status_t AudioPolicyManagerBase::checkAndSetVolume(int stream,

2 int index,

3 audio_io_handle_t output,

4 audio_devices_t device,

5 int delayMs,

6 bool force)

7 {

8

9 // do not change actual stream volume if the stream is muted

10 ... ...

11 // do not change in call volume if bluetooth is connected and vice versa

12 ... ...

13 audio_devices_t checkedDevice = (device == AUDIO_DEVICE_NONE) ? mOutputs.valueFor(output)->device() : device;

14 float volume = computeVolume(stream, index, checkedDevice);

15

16 ... ...

17   mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);/*将得到的volume应用到对应的output中*/

18 }

在checkAndSetVolume中可以知道volume是通过computeVolume得到的。继续向下分析:

float AudioPolicyManagerBase::computeVolume(int stream,

int index,

audio_devices_t device)

{

... ...

volume = volIndexToAmpl(device, streamDesc, index);

... ...

return volume;

}

终于到了最后volIndexToAmpl,从函数名就可以知道该函数的作用是通过volIndex得到音量放大倍数。

float AudioPolicyManagerBase::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,

int indexInUi)

{

device_category deviceCategory = getDeviceCategory(device);

const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];

// the volume index in the UI is relative to the min and max volume indices for this stream type

int nbSteps = 1 + curve[VOLMAX].mIndex -

curve[VOLMIN].mIndex;

int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /

(streamDesc.mIndexMax - streamDesc.mIndexMin);

// find what part of the curve this index volume belongs to, or if it's out of bounds

int segment = 0;

if (volIdx < curve[VOLMIN].mIndex) { // out of bounds

return 0.0f;

} else if (volIdx < curve[VOLKNEE1].mIndex) {

segment = 0;

} else if (volIdx < curve[VOLKNEE2].mIndex) {

segment = 1;

} else if (volIdx <= curve[VOLMAX].mIndex) {

segment = 2;

} else { // out of bounds

return 1.0f;

}

// linear interpolation in the attenuation table in dB

float decibels = curve[segment].mDBAttenuation +

((float)(volIdx - curve[segment].mIndex)) *

( (curve[segment+1].mDBAttenuation -

curve[segment].mDBAttenuation) /

((float)(curve[segment+1].mIndex -

curve[segment].mIndex)) );

float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )

return amplification;

}

其中curve代表在用设备(如SPEAKER、HEADSET & EARPIECE)播放音频流(如SYSTEM、MUSIC、ALARM、RING & TTS等)时的音量曲线,最后decibles & amplification就是我们需要求的值,其中decibles代表某一音节所对应的dB值,而amplification则是由dB值转化得到的音量放大倍数。这样整个音量调节过程到此就算完成了,具体的计算分析会放在后面继续分析。

java调节音量_调节音量的流程相关推荐

  1. python蜂鸣器占空比调节音量_蜂鸣器音量的控制方法和控制系统的制作方法

    蜂鸣器音量的控制方法和控制系统的制作方法 [技术领域] [0001]本发明属于控制领域,尤其涉及一种家电蜂鸣器音量的控制方法和控制系统. [背景技术] [0002]目前多数家电产品的蜂呜器都是单一的通 ...

  2. java第一周_从计算机基础到流程控制语句(if_else)

    一.计算机基础 裸机 没有安装任何软件的计算机(无操作系统.无应用软件) 计算机的应用 1.科学计算 科学计算也称数值计算.计算机最开始是为解决科学研究和工程设计中遇到的大量数学问题的数值计算而研制的 ...

  3. 提升手机麦克风音量_手机音量太小?赶快打开手机这个音量设置,声音瞬间扩大一倍!...

    原标题:手机音量太小?赶快打开手机这个音量设置,声音瞬间扩大一倍! 我们在使用手机的时候,会因为在不同场合,适当的调整手机听筒音量,是自己能够听到电话内容而不会影响他人,但是最近,很多朋友表示,自己手 ...

  4. java 项目测试_项目测试工作流程

    第一轮测试,第二轮测试,第三轮测试,日常测试,预发测试,线上测试 由于为新起项目,日常测试部分可以忽略,不用上日常测试环境,项目测试环境即是日常测试环境,该部分在第一次做项目时,容易忽视. 各个阶段测 ...

  5. Android音量调节(一)音量键的处理流程

    文章目录 1.Android音量键调节音量流程 2.Android流定义 3.按键的处理流程 3.1 adjustSuggestedStreamVolume 3.2 adjustStreamVolum ...

  6. 客户手动调节音量的范围,修改默认音量各类型音量,按音量键或手动调进度条触发流程,调节音量大小级数每次加减的级数,同时操作指定多个音量类型,更改开机音量,通过底层节点来调节音量大小,音量控制的对话框UI

    frameworks/base/services/core/java/com/android/server/audio/AudioService.java 客户手动调节音量的范围:就是按音量键出来的进 ...

  7. mac hdmi 不能调整音量_用快捷键调节 Mac 外接显示器亮度:MonitorControl

    相信很多 Mac 用户的日常 Setup,都是一台 MacBook + 一台外接屏.这样不仅可以提高效率,也能换来更好的大屏体验.但这样以来就会牺牲掉 Mac 上两个方便的功能:不能用键盘直接调节外接 ...

  8. android 音量 广播,Android平台音量调节(一)音量键调节音量

    Android平台音量调节 本文基于Android 8.0讲述Android平台原生音量控制功能. 流的定义 Android中,音量都是分开控制,各种流定义各种流的音量.在Android8.0中,定义 ...

  9. android音量键调节听筒音量的大小

    android音量键调节听筒音量的大小 最近发现微信的语音功能可以在听筒和喇叭间互相切换并且可以使用音量按键进行调节,之前在项目开发中只用到音频的多媒体类型播放音频文件但没用到听筒,所以就写了个dem ...

  10. Android6.0 源码修改之Settings音量调节界面增加通话音量调节

    Android6.0 源码修改之Settings音量调节界面增加通话音量调节 前言 今天客户提了个需求,因为我们的设备在正常情况下无法调节通话音量,只有在打电话过程中,按物理音量加减键才能出现调节通话 ...

最新文章

  1. c语言中的字节和元素,C语言指向数组元素的指针
  2. mysql 中文乱码
  3. C/C++中的函数中的void和void* 理解
  4. Paper:2020年3月30日何恺明团队最新算法RegNet—来自Facebook AI研究院《Designing Network Design Spaces》的翻译与解读
  5. 关于Jquery中ajax方法data参数用法的总结
  6. 限制排列与棋盘多项式
  7. 跟我一起学.NetCore之配置初体验
  8. java PageUtil + stream 手动计算List 分页
  9. java学习日记 集合框架
  10. 2020-08-17 java实战项目汇总
  11. 接口文档模板(Markdown)
  12. iozone - 性能压力测试工具
  13. 预设Date时间格式化参数
  14. linux 移动硬盘 mac,Mac下使用NTFS格式的移动硬盘
  15. c#应用:简单的图片查看器
  16. 奇异值分解(SVD)
  17. 通过物理地址查计算机,别人知道我查电脑的物理地址,怎么处理
  18. Python:过程型考核
  19. java.lang.IllegalArgumentException: Malformed \uxxxx encoding
  20. 【素描基础】大师素描及素描抽象明…

热门文章

  1. 系统架构师必须掌握的英语单词
  2. SVN下载 1.11.0版本 win7 32位 安装文件及中文语言包
  3. 计算机图像处理入门基础知识——色域,色度图,色彩空间和色彩管理
  4. AI技术的苹果iPhone XS Max双卡双待7纳米6.5寸512GB顶配12799元(公号回复“苹果AI”下载PDF资料)
  5. 整蛊小学妹,督促学习的html代码
  6. 上网本之必备网络工具推荐
  7. c# splitContainer控件
  8. PES,TS,PS,RTP等流的打包格式解析之PES流
  9. 如何把书上的字弄到电脑
  10. 前阿里GOC负责人葛梅:运维转型运营,IT服务管理体系搭建实践