音频输出设备的选择

2023-05-16

场景:使用AudioTrack播放一段音频,streamtype是AUDIO_STREAM_MUSIC;

跟踪音频输出设备选择的流程,代码会走到这里:

1.frameworks\av\media\libaudioclient\AudioTrack.cpp
 
status_t AudioTrack::createTrack_l(){
 
    ......
    
    //假设此时播放的是音乐,那这里的streamType是Music类型,所以属性attr为NULL
    audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
    
    ......
 
    //通过属性以及stream的类型获取当前track输出的output设备;
    //传入的audio_attributes_t等参数,带回output
    status = AudioSystem::getOutputForAttr(attr, &output,
                                           mSessionId, &streamType, mClientUid,
                                           &config,
                                           mFlags, &mRoutedDeviceId, &mPortId);
 
    ......
 
}
 
 
2.frameworks\av\media\libaudioclient\AudioSystem.cpp
status_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
                                        audio_io_handle_t *output,
                                        audio_session_t session,
                                        audio_stream_type_t *stream,
                                        uid_t uid,
                                        const audio_config_t *config,
                                        audio_output_flags_t flags,
                                        audio_port_handle_t *selectedDeviceId,
                                        audio_port_handle_t *portId)
{
    //实现类是AudioPolicyInterfaceImpl
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return NO_INIT;
    //调用AudioPolicyInterfaceImpl.getOutputForAttr();
    return aps->getOutputForAttr(attr, output, session, stream, uid,
                                 config,
                                 flags, selectedDeviceId, portId);
}
 
3.frameworks\av\services\audiopolicy\service\AudioPolicyInterfaceImpl.cpp
status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
                                              audio_io_handle_t *output,
                                              audio_session_t session,
                                              audio_stream_type_t *stream,
                                              uid_t uid,
                                              const audio_config_t *config,
                                              audio_output_flags_t flags,
                                              audio_port_handle_t *selectedDeviceId,
                                              audio_port_handle_t *portId)
{
    if (mAudioPolicyManager == NULL) {
        return NO_INIT;
    }
    ALOGV("getOutput()");
    Mutex::Autolock _l(mLock);
 
    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
    if (!isTrustedCallingUid(callingUid) || uid == (uid_t)-1) {
        ALOGW_IF(uid != (uid_t)-1 && uid != callingUid,
                "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid);
        uid = callingUid;
    }
    //进入AudioPolicyManager
    return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
                                                 config,
                                                 flags, selectedDeviceId, portId);
}
 
 
4.frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp
status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
                                              audio_io_handle_t *output,
                                              audio_session_t session,
                                              audio_stream_type_t *stream,
                                              uid_t uid,
                                              const audio_config_t *config,
                                              audio_output_flags_t flags,
                                              audio_port_handle_t *selectedDeviceId,
                                              audio_port_handle_t *portId)
{
    audio_attributes_t attributes;
    //对于当前music的track,传入的attr是NULL,
    if (attr != NULL) {//判断不走
        if (!isValidAttributes(attr)) {
            ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
                  attr->usage, attr->content_type, attr->flags,
                  attr->tags);
            return BAD_VALUE;
        }
        attributes = *attr;
    } else {
        if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) {
            ALOGE("getOutputForAttr():  invalid stream type");
            return BAD_VALUE;
        }
        //①将stream保存到attributes的属性中
        /*对于当前music的场景,attributes会被如下赋值
		    attr->content_type = AUDIO_CONTENT_TYPE_MUSIC;
       	    attr->usage = AUDIO_USAGE_MEDIA;
		*/
        stream_type_to_audio_attributes(*stream, &attributes);
    }
 
    ......
 
    *stream = streamTypefromAttributesInt(&attributes);
 
    ......
 
    //②根据当前音频的属性,获取当前track的音频策略,根据attributes选中Strategy
    routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
 
    //③根据当前track的音频策略,获取当前音频的输出终端,根据Strategy选中device
    audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
 
    if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
    }
 
    ALOGV("getOutputForAttr() device 0x%x, samplingRate %d, format %x, channelMask %x, flags %x",
          device, config->sample_rate, config->format, config->channel_mask, flags);
 
    //④根据音频设备,音频输出标识,format等选择输出路径,根据选定的device获取Output
    *output = getOutputForDevice(device, session, *stream,
                                 config->sample_rate, config->format, config->channel_mask,
                                 flags, &config->offload_info);
    ......
 
    return NO_ERROR;
}
 

先看①:stream_type_to_audio_attributes(*stream, &attributes),将stream保存到attributes的属性中:

frameworks\av\media\libaudioclient\include\media\AudioPolicyHelper.h
static inline
void stream_type_to_audio_attributes(audio_stream_type_t streamType,
                                     audio_attributes_t *attr) {
    memset(attr, 0, sizeof(audio_attributes_t));
 
    switch (streamType) {
    case AUDIO_STREAM_DEFAULT:
    case AUDIO_STREAM_MUSIC:
        attr->content_type = AUDIO_CONTENT_TYPE_MUSIC;
        attr->usage = AUDIO_USAGE_MEDIA;
        break;
    case AUDIO_STREAM_VOICE_CALL:
        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
        break;
    case AUDIO_STREAM_ENFORCED_AUDIBLE:
        attr->flags  |= AUDIO_FLAG_AUDIBILITY_ENFORCED;
        // intended fall through, attributes in common with STREAM_SYSTEM
    case AUDIO_STREAM_SYSTEM:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
        break;
    case AUDIO_STREAM_RING:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
        break;
    case AUDIO_STREAM_ALARM:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_ALARM;
        break;
    case AUDIO_STREAM_NOTIFICATION:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_NOTIFICATION;
        break;
    case AUDIO_STREAM_BLUETOOTH_SCO:
        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
        attr->flags |= AUDIO_FLAG_SCO;
        break;
    case AUDIO_STREAM_DTMF:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
        break;
    case AUDIO_STREAM_TTS:
        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
        attr->usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
        break;
    default:
        ALOGE("invalid stream type %d when converting to attributes", streamType);
    }
}

content_type:具体输出类型。android当前一共提供了11种stream_type,但一旦进入到Attribute,Android就只将其整理成几种类型。这才是实际的类型。

这里的stream_type,usage定义在audio-base.h中,content_type定义在了audio.h中:
 

1.system\media\audio\include\system\audio-base.h
typedef enum {
    AUDIO_STREAM_DEFAULT = -1, // (-1)
    AUDIO_STREAM_MIN = 0,
    AUDIO_STREAM_VOICE_CALL = 0,
    AUDIO_STREAM_SYSTEM = 1,
    AUDIO_STREAM_RING = 2,
    AUDIO_STREAM_MUSIC = 3,
    AUDIO_STREAM_ALARM = 4,
    AUDIO_STREAM_NOTIFICATION = 5,
    AUDIO_STREAM_BLUETOOTH_SCO = 6,
    AUDIO_STREAM_ENFORCED_AUDIBLE = 7,
    AUDIO_STREAM_DTMF = 8,
    AUDIO_STREAM_TTS = 9,
    AUDIO_STREAM_ACCESSIBILITY = 10,
    AUDIO_STREAM_REROUTING = 11,
    AUDIO_STREAM_PATCH = 12,
    AUDIO_STREAM_PUBLIC_CNT = 11, // (ACCESSIBILITY + 1)
    AUDIO_STREAM_FOR_POLICY_CNT = 12, // PATCH
    AUDIO_STREAM_CNT = 13, // (PATCH + 1)
} audio_stream_type_t;
 
typedef enum {
    AUDIO_USAGE_UNKNOWN = 0,
    AUDIO_USAGE_MEDIA = 1,
    AUDIO_USAGE_VOICE_COMMUNICATION = 2,
    AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING = 3,
    AUDIO_USAGE_ALARM = 4,
    AUDIO_USAGE_NOTIFICATION = 5,
    AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE = 6,
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7,
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8,
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9,
    AUDIO_USAGE_NOTIFICATION_EVENT = 10,
    AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY = 11,
    AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12,
    AUDIO_USAGE_ASSISTANCE_SONIFICATION = 13,
    AUDIO_USAGE_GAME = 14,
    AUDIO_USAGE_VIRTUAL_SOURCE = 15,
    AUDIO_USAGE_ASSISTANT = 16,
    AUDIO_USAGE_CNT = 17,
    AUDIO_USAGE_MAX = 16, // (CNT - 1)
} audio_usage_t;
 
2.system\media\audio\include\system\audio.h
typedef enum {
    AUDIO_CONTENT_TYPE_UNKNOWN      = 0,
    AUDIO_CONTENT_TYPE_SPEECH       = 1,
    AUDIO_CONTENT_TYPE_MUSIC        = 2,
    AUDIO_CONTENT_TYPE_MOVIE        = 3,
    AUDIO_CONTENT_TYPE_SONIFICATION = 4,
 
    AUDIO_CONTENT_TYPE_CNT,
    AUDIO_CONTENT_TYPE_MAX          = AUDIO_CONTENT_TYPE_CNT - 1,
} audio_content_type_t;

再看②: routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);//根据当前音频的属性,获取当前track的音频策略也就是根据attributes选中Strategy:

uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) {
    // flags to strategy mapping
    if ((attr->flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
        return (uint32_t) STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
    }
    if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
        return (uint32_t) STRATEGY_ENFORCED_AUDIBLE;
    }
    // usage to strategy mapping
    //进入Engine.cpp
    //这里范围音频策略是:STRATEGY_MEDIA
    return static_cast<uint32_t>(mEngine->getStrategyForUsage(attr->usage));
}
 
 
frameworks\av\services\audiopolicy\enginedefault\src\Engine.cpp
routing_strategy Engine::getStrategyForUsage(audio_usage_t usage)
{
    // usage to strategy mapping
    switch (usage) {
    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
        return STRATEGY_ACCESSIBILITY;
 
    case AUDIO_USAGE_MEDIA:
    case AUDIO_USAGE_GAME:
    case AUDIO_USAGE_ASSISTANT:
    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
        return STRATEGY_MEDIA;
 
    case AUDIO_USAGE_VOICE_COMMUNICATION:
        return STRATEGY_PHONE;
 
    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
        return STRATEGY_DTMF;
 
    case AUDIO_USAGE_ALARM:
    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
        return STRATEGY_SONIFICATION;
 
    case AUDIO_USAGE_NOTIFICATION:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
    case AUDIO_USAGE_NOTIFICATION_EVENT:
        return STRATEGY_SONIFICATION_RESPECTFUL;
 
    case AUDIO_USAGE_UNKNOWN:
    default:
        return STRATEGY_MEDIA;
    }
}

音频策略strategy定义在RoutingStrategy.h中:

frameworks\av\services\audiopolicy\common\include\RoutingStrategy.h
enum routing_strategy {
    STRATEGY_MEDIA,
    STRATEGY_PHONE,
    STRATEGY_SONIFICATION,
    STRATEGY_SONIFICATION_RESPECTFUL,
    STRATEGY_DTMF,
    STRATEGY_ENFORCED_AUDIBLE,
    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
    STRATEGY_ACCESSIBILITY,
    STRATEGY_REROUTING,
    NUM_STRATEGIES
};

   然后看③: audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);//根据当前track的音频策略,获取当前音频的输出终端,也就是根据Strategy选中device:

audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
                                                         bool fromCache)
{
    ......
    return mEngine->getDeviceForStrategy(strategy);
}
 
frameworks\av\services\audiopolicy\enginedefault\src\Engine.cpp
audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
{
    DeviceVector availableOutputDevices = mApmObserver->getAvailableOutputDevices();
    DeviceVector availableInputDevices = mApmObserver->getAvailableInputDevices();
 
    const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
 
    return getDeviceForStrategyInt(strategy, availableOutputDevices,
                                   availableInputDevices, outputs);
}

策略,USAGE,STREAM对应关系如下:

STRATEGY_ACCESSIBILITY
    AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY  // 11
        AUDIO_STREAM_TTS  //  9

STRATEGY_MEDIA
    AUDIO_USAGE_MEDIA  //  1
        AUDIO_STREAM_DEFAULT  // -1
        AUDIO_STREAM_MUSIC    //  3
    AUDIO_USAGE_GAME
    AUDIO_USAGE_ASSISTANT
    AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
    AUDIO_USAGE_ASSISTANCE_SONIFICATION  //  11
        AUDIO_STREAM_ENFORCED_AUDIBLE   //  7
        AUDIO_STREAM_SYSTEM  //  1

STRATEGY_PHONE
    AUDIO_USAGE_VOICE_COMMUNICATION  //  2
        AUDIO_STREAM_VOICE_CALL  //  0
        AUDIO_STREAM_BLUETOOTH_SCO  //  6

STRATEGY_DTMF
    AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING  //  3
        AUDIO_STREAM_DTMF  //  8

STRATEGY_SONIFICATION
    AUDIO_USAGE_ALARM  // 4
        AUDIO_STREAM_ALARM  //  4
    AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE  //  6
        AUDIO_STREAM_RING  //  2

STRATEGY_SONIFICATION_RESPECTFUL
    AUDIO_USAGE_NOTIFICATION  //  5
        AUDIO_STREAM_NOTIFICATION  //  5
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED
    AUDIO_USAGE_NOTIFICATION_EVENT

STRATEGY_MEDIA
    AUDIO_USAGE_UNKNOWN  //  0
    default

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

音频输出设备的选择 的相关文章

  • Android SurfaceView预览变形完美解决方法

    这个问题百度上一搜一大把 xff0c 基本上都是说找到和SurfaceView的比例相近的camera预览尺寸 xff0c 但是发现预览时候还是差了点意思 xff0c 具体看下面这个回调就知道是为什么了 64 Override public
  • Camera2 教程 一概览

    从 Android 5 0 开始 xff0c Google 引入了一套全新的相机框架 Camera2 xff08 android hardware camera2 xff09 并且废弃了旧的相机框架 Camera1 xff08 androi
  • Camera2 二开关相机

    1 创建相机项目 正如前所说的 xff0c 我们会开发一个具有完整相机功能的应用程序 xff0c 所以第一步要做的就是创建一个相机项目 xff0c 这里我用 AS 创建了一个叫 Camera2Sample 的项目 xff0c 并且有一个 A
  • Camera2 三预览

    1 获取预览尺寸 CameraCharacteristics 是一个只读的相机信息提供者 xff0c 其内部携带大量的相机信息 xff0c 包括代表相机朝向的 LENS FACING xff1b 判断闪光灯是否可用的 FLASH INFO
  • Camera2 四拍照

    1 理解 Capture 工作流程 在正式介绍如何拍照之前 xff0c 我们有必要深入理解几种不同模式的 Capture 的工作流程 xff0c 只要理解它们的工作流程就很容易掌握各种拍照模式的实现原理 xff0c 在第一章 Camera2
  • 解决从PDF复制文字后乱码问题

    背景 需要从PDF复制文字出来做笔记 xff0c 可是谁知道PDF通过adobe打开后复制出来后是乱码 xff0c 如下图所示 xff1a 解决 尝试过安装字体 xff0c 可惜没卵用 方法1 CAJViewer打开 用该软件打开后复制 x
  • Android Studio不能启动模拟器原因探秘 The emulator process for AVD xxx has terminated

    文章背景 在Android Studio中创建模拟器后 xff0c 启动模拟器时弹出提示 The emulator process for AVD Pixel 2 API 31 has terminated xff0c 但是并没有显示具体错
  • AndroidStudio-快捷键-格式化代码

    Windows Ctrl 43 Alt 43 L Ctrl 43 Shift 43 F 无效 亲测 和qq热键冲突 我的解决方式是把qq除捕获屏幕外的热键全部设置为无 Mac OPTION 43 CMD 43 L
  • 安装APK时报错:Failure [INSTALL_FAILED_TEST_ONLY: installPackageLI]

    使用AS自动运行时会在app build outputs apk debug文件夹下自动生成测试APK xff1a app debug apk xff0c 用命令adb install app debug apk时报错 xff1a Fail
  • 计算机网络-划分子网 四大类必会题型

    必记知识点 A类 xff1a 0 126 xff0c 默认子网掩码 xff1a 255 0 0 0 B类 xff1a 128 191 xff0c 默认子网掩码 xff1a 255 255 0 0 C类 xff1a 192 223 xff0c
  • C语言-解释复杂声明

    基本术语 xff1a 声明符 xff1a int a 就是一个声明符 标识符 定义的变量名字 xff0c 如 xff1a int a xff0c 那么a就是一个标识符 1 两个原则 xff1a 始终从内往外读声明符 xff0c 括号优先级高
  • Android EditText 不自动获取焦点

    在Activity上面显示一个EditText xff0c 进入该页面时想阻止这个EditText自动获取焦点而自动调起键盘 思路如下 xff1a 可以采取让父级控件来获取焦点就可以了 例如说在这个EditText外面包一个LinearLa
  • Wireshark中无法显示网卡列表的解决方法

    1 问题描述 打开Wireshark时 xff0c 都会有一个网卡列表 xff0c 在该列表中显示了电脑的所有网卡 但是 xff0c 有时打开Wireshark时 xff0c 该网卡列表不显示 xff0c 如图1所示 图1 不显示网卡列表
  • Android事件分发与事件处理源码分析

    一 前言 Android中事件分发与事件处理是一个老生常谈的问题了 xff0c 自己在网上也看过很多文章 xff0c 但是大部分人都只是抛出一些结论或是一些流程图或者干脆就是一些运行demo的截图等 xff0c 对于这些结论和流程图是怎么来
  • 解决小米pad USB安装apk时AS报错:INSTALL_FAILED_USER_RESTRICTED

    设置 更多设置 开发者选项 gt 取消启用MIUI优化 用USB接口 xff0c 选择传输文件 xff08 MTP xff09
  • git 通过 comment 关键字查找 commit

    git log grep 61 word 比如 xff1a git log grep 61 同步
  • git合并多个 Commit

    在使用 Git 作为版本控制的时候 xff0c 我们可能会由于各种各样的原因提交了许多临时的 commit xff0c 而这些 commit 拼接起来才是完整的任务 那么我们为了避免太多的 commit 而造成版本控制的混乱 xff0c 通
  • git查看某次提交的文件列表

    Git操作常用 xff1a 一 查看某次提交的文件列表 首先使用git log查看历史提交记录 xff1a 复制你想要查看记录的某个提交代号9ddc9dca00b 使用命令git show 9ddc9dca00b stat查看详细文件列表
  • Android SoundPool插入耳机后依然有外放声音

    使用soundPool播放声音 xff0c 当手机已经接通耳机时 xff0c 还会有外放声音 xff0c 是因为在初始化soundpool是用的流类型 xff08 streamType xff09 导致的 xff0c 有些流类型系统是一定会

随机推荐

  • 一文搞懂Android JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧

    Lifecycle LiveData和ViewModel作为AAC架构的核心 xff0c 常常被用在Android业务架构中 在京东商城Android应用中 xff0c 为了事件传递等个性化需求 xff0c 比如ViewModel间通信 V
  • Linux下安装npm

    1 root 登录linux 2 没有目录就自己创建一个 cd usr local node 3 下载安装包 wget https npm taobao org mirrors node v4 4 7 node v4 4 7 linux x
  • AudioService之音频输出通道切换

    前言 xff1a 音频输出的方式有很多种 xff0c 外放即扬声器 xff08 Speaker xff09 听筒 xff08 Telephone Receiver xff09 有线耳机 xff08 WiredHeadset xff09 蓝牙
  • Android音频——音量调节

    一 音量相关概念 1 相关术语解释 track volume 单个App设置音量时设置的是这个 xff0c 它只影响本App的音量 stream volume xff1a 设置某一stream的音量 xff0c Android系统中支持10
  • 电话状态权限及IMEI获取流程源码分析

    IMEI是设备唯一性的一个重要指标 xff0c 这篇文章对IMEI获取做一些分析 xff0c 以达到以下两个目的 xff1a 1 梳理Android源码中获取IMEI流程 2 理解获取IMEI时 xff0c 源码中权限调用流程 备注 xff
  • Android Handler深入学习(源码分析)

    目录 xff1a 1 背景 在分析源码之前 xff0c 先来了解一下Message MessageQueue Looper这几个对象 1 1 Message 消息 定义 xff1a 是线程间通讯的数据单元 xff0c 包含着描述信息及任意数
  • git 合并两个不同仓库

    在日常开发过程中 xff0c 可能会遇到需要将两个不同的仓库合并成到一个仓库的场景 这里介绍一下怎么将两个不同的仓库合并到一个仓库中 合并两个不同仓库 思路 xff1a 添加两个远程仓库 xff0c 将两个代码作为两个分支 xff0c 然后
  • Android-Handler源码解析-Message

    成员变量 标识Message public int what 存储简单数据 xff0c 如果存储复杂的数据使用setData 方法 public int arg1 public int arg2 发送给接收者的任意对象 public Obj
  • Git中submodule的使用

    背景 面对比较复杂的项目 xff0c 我们有可能会将代码根据功能拆解成不同的子模块 主项目对子模块有依赖关系 xff0c 却又并不关心子模块的内部开发流程细节 这种情况下 xff0c 通常不会把所有源码都放在同一个 Git 仓库中 有一种比
  • Android-Handler源码解析-Looper

    成员变量 Log的TAG private static final String TAG 61 34 Looper 34 线程本地变量 xff0c 保证了每个线程仅有唯一的Looper对象 64 UnsupportedAppUsage st
  • 5步删除 git submodule

    1 删除submodule缓存 需要先暂存 gitmodules 文件 否则会报错 fatal please stage your changes to gitmodules or stash them to proceed 1 2 git
  • java.lang.NoSuchMethodError: java.lang.reflect.Field.trySetAccessible()Z

    把jdk 设置成11 就可以了
  • ES6 模块

    概述 在 ES6 前 xff0c 实现模块化使用的是 RequireJS 或者 seaJS xff08 分别是基于 AMD 规范的模块化库 xff0c 和基于 CMD 规范的模块化库 xff09 ES6 引入了模块化 xff0c 其设计思想
  • jdk 8 、9 10 11 12 13 14和 jdk 1.8 什么关系?

    jdk 8 就是 jdk 1 8 jdk9 就是 jdk 1 9
  • android studio设置jdk版本项目设置和全局设置

    android studio设置jdk版本项目设置和全局设置 方法1 xff1a 修改项目的gradle构建jdk xff08 建议在使用别人的单个项目时使用 xff09 打开项目设置 打开jdk设置 选择jdk11 注意要apply保存然
  • Gradle:执行命令时指定 JDK 版本

    应用场景 在命令行执行 Gradle 时使用的 Gradle 版本为系统环境变量中指定的 Gradle 版本 xff0c 使用的 JDK 为系统环境变量 JAVA HOME 指定的 JDK 来自 Gradle 官网的说明 xff1a JAV
  • Java基础-方法区以及static的内存分配图

    什么是方法区 xff1a 方法区是系统分配的一个内存逻辑区域 xff0c 是JVM在装载类文件时 xff0c 用于存储类型信息的 类的描述信息 方法区存放的信息包括 xff1a 类的基本信息 xff1a 1 每个类的全限定名 2 每个类的直
  • AudioManager 蓝牙sco连接相关接口

    蓝牙耳机连接之后 xff0c 发现音频发声的还是终端 xff0c 并没有转换到蓝牙耳机发声 网上搜索相关资料 xff0c 发现是蓝牙耳机需要建立链路来播放音频 简单介绍下蓝牙耳机的两种链路 xff1a A2DP xff08 异步链路 xff
  • Android 音频源码分析——AudioTrack设备选择

    基于Andorid9 0源码 以AudioTrack为例 xff0c 梳理下输出设备选择流程 音频设备选择的影响因素 xff1a AudioAttributes 声音流类型 setForceUse 设置 setPreferredDevice
  • 音频输出设备的选择

    场景 xff1a 使用AudioTrack播放一段音频 xff0c streamtype是AUDIO STREAM MUSIC xff1b 跟踪音频输出设备选择的流程 xff0c 代码会走到这里 xff1a 1 frameworks av