Android学习笔记之AudioManger与HAL之间的联系

Android学习笔记之AudioManger与HAL之间的联系,第1张

前言

最近在做一个音效功能,通过一个app去修改音频设备的一些参数。这时候就需要用到audio_hw.cpp里的adev_set_parameters()来控制。为了更好的实现功能,详细追踪了这个接口的调用和实现流程。

1.AudioManager.setParameters()

暴露给上层app的是这个接口,使用方法如下

mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mAudioManager.setParameters("test");

这个函数的原型是在​android/frameworks/base/media/java/android/media/AudioManager.java

      /**
       * Sets a variable number of parameter values to audio hardware.
       *
       * @param keyValuePairs list of parameters key value pairs in the form:
       *    key1=value1;key2=value2;...
       *
       */
      public void setParameters(String keys) {
          AudioSystem.setParameters(keyValuePairs);
      }
2. AudioSystem.setParameters()

这里调用了android/frameworks/base/media/java/android/media/AudioSystem.java的native接口

      /*
       * Sets a group generic audio configuration parameters. The use of these parameters
       * are platform dependent, see libaudio
       *
       * param keyValuePairs  list of parameters key value pairs in the form:
       *    key1=value1;key2=value2;...
       */
      public static native int setParameters(String keyValuePairs);

搜索android_media_AudioSystem*,可查到是在android/frameworks/base/core/jni/android_media_AudioSystem.cpp

  static jint
  android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
  {
      const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
      String8 c_keyValuePairs8;
      if (keyValuePairs) {
          c_keyValuePairs8 = String8(
              reinterpret_cast(c_keyValuePairs),
              env->GetStringLength(keyValuePairs));
          env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
      }
      int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
      return (jint) status;
  }
3. AudioSystem::setParameters()

继续追踪,在android/frameworks/av/media/libaudioclient/AudioSystem.cpp

  status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
  {
      const sp& af = AudioSystem::get_audio_flinger();
      if (af == 0) return PERMISSION_DENIED;
      return af->setParameters(ioHandle, keyValuePairs);
  }
4. AudioFlinger->setParameters()

这里通过get_audio_flinger(),调用的是这里android/frameworks/av/services/audioflinger/AudioFlinger.cpp

1220  status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
1221  {
1222      ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d calling uid %d",
1223              ioHandle, keyValuePairs.string(),
1224              IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
1225  
1226      // check calling permissions
1227      if (!settingsAllowed()) {
1228          return PERMISSION_DENIED;
1229      }
1230  
1231      String8 filteredKeyValuePairs = keyValuePairs;
1232      filterReservedParameters(filteredKeyValuePairs, IPCThreadState::self()->getCallingUid());
1233  
1234      ALOGV("%s: filtered keyvalue %s", __func__, filteredKeyValuePairs.string());
1235  
1236      // AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
1237      if (ioHandle == AUDIO_IO_HANDLE_NONE) {
1238          Mutex::Autolock _l(mLock);
1239          // result will remain NO_INIT if no audio device is present
1240          status_t final_result = NO_INIT;
1241          {
1242              AutoMutex lock(mHardwareLock);
1243              mHardwareStatus = AUDIO_HW_SET_PARAMETER;
1244              for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
1245                  sp dev = mAudioHwDevs.valueAt(i)->hwDevice();
1246                  status_t result = dev->setParameters(filteredKeyValuePairs);
1247                  // return success if at least one audio device accepts the parameters as not all
1248                  // HALs are requested to support all parameters. If no audio device supports the
1249                  // requested parameters, the last error is reported.
1250                  if (final_result != NO_ERROR) {
1251                      final_result = result;
1252                  }
1253              }
1254              mHardwareStatus = AUDIO_HW_IDLE;
1255          }
1256          // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
1257          AudioParameter param = AudioParameter(filteredKeyValuePairs);
1258          String8 value;
1259          if (param.get(String8(AudioParameter::keyBtNrec), value) == NO_ERROR) {
1260              bool btNrecIsOff = (value == AudioParameter::valueOff);
1261              if (mBtNrecIsOff.exchange(btNrecIsOff) != btNrecIsOff) {
1262                  for (size_t i = 0; i < mRecordThreads.size(); i++) {
1263                      mRecordThreads.valueAt(i)->checkBtNrec();
1264                  }
1265              }
1266          }
1267          String8 screenState;
1268          if (param.get(String8(AudioParameter::keyScreenState), screenState) == NO_ERROR) {
1269              bool isOff = (screenState == AudioParameter::valueOff);
1270              if (isOff != (AudioFlinger::mScreenState & 1)) {
1271                  AudioFlinger::mScreenState = ((AudioFlinger::mScreenState & ~1) + 2) | isOff;
1272              }
1273          }
1274          return final_result;
1275      }
1276  
1277      // hold a strong ref on thread in case closeOutput() or closeInput() is called
1278      // and the thread is exited once the lock is released
1279      sp thread;
1280      {
1281          Mutex::Autolock _l(mLock);
1282          thread = checkPlaybackThread_l(ioHandle);
1283          if (thread == 0) {
1284              thread = checkRecordThread_l(ioHandle);
1285              if (thread == 0) {
1286                  thread = checkMmapThread_l(ioHandle);
1287              }
1288          } else if (thread == primaryPlaybackThread_l()) {
1289              // indicate output device change to all input threads for pre processing
1290              AudioParameter param = AudioParameter(filteredKeyValuePairs);
1291              int value;
1292              if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
1293                      (value != 0)) {
1294                  broacastParametersToRecordThreads_l(filteredKeyValuePairs);
1295              }
1296          }
1297      }
1298      if (thread != 0) {
1299          return thread->setParameters(filteredKeyValuePairs);
1300      }
1301      return BAD_VALUE;
1302  }

在这里,我们会发现用到了智能指针sp dev并进行调用dev->setParameters.

先保留,后面会用上。

5. AudioFlinger

继续对AudioFlinger进行分析,先看它的构造函数,里面有个

mDevicesFactoryHal = DevicesFactoryHalInterface::create();

搜索下mDevicesFactoryHal,发现在loadHwModule_l()里有进行openDevice

1795  // loadHwModule_l() must be called with AudioFlinger::mLock held
1796  audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
1797  {
1798      for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
1799          if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
1800              ALOGW("loadHwModule() module %s already loaded", name);
1801              return mAudioHwDevs.keyAt(i);
1802          }
1803      }
1804  
1805      sp dev;
1806  
1807      int rc = mDevicesFactoryHal->openDevice(name, &dev);
1808      if (rc) {
1809          ALOGE("loadHwModule() error %d loading module %s", rc, name);
1810          return AUDIO_MODULE_HANDLE_NONE;
1811      }
1812  
1813      mHardwareStatus = AUDIO_HW_INIT;
1814      rc = dev->initCheck();
1815      mHardwareStatus = AUDIO_HW_IDLE;
1816      if (rc) {
1817          ALOGE("loadHwModule() init check error %d for module %s", rc, name);
1818          return AUDIO_MODULE_HANDLE_NONE;
1819      }
1820  
1821      // Check and cache this HAL's level of support for master mute and master
1822      // volume.  If this is the first HAL opened, and it supports the get
1823      // methods, use the initial values provided by the HAL as the current
1824      // master mute and volume settings.
1825  
1826      AudioHwDevice::Flags flags = static_cast(0);
1827      {  // scope for auto-lock pattern
1828          AutoMutex lock(mHardwareLock);
1829  
1830          if (0 == mAudioHwDevs.size()) {
1831              mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
1832              float mv;
1833              if (OK == dev->getMasterVolume(&mv)) {
1834                  mMasterVolume = mv;
1835              }
1836  
1837              mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
1838              bool mm;
1839              if (OK == dev->getMasterMute(&mm)) {
1840                  mMasterMute = mm;
1841              }
1842          }
1843  
1844          mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
1845          if (OK == dev->setMasterVolume(mMasterVolume)) {
1846              flags = static_cast(flags |
1847                      AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
1848          }
1849  
1850          mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
1851          if (OK == dev->setMasterMute(mMasterMute)) {
1852              flags = static_cast(flags |
1853                      AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
1854          }
1855  
1856          mHardwareStatus = AUDIO_HW_IDLE;
1857      }
1858  
1859      audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
1860      mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
1861  
1862      ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
1863  
1864      return handle;
1865  
1866  }

可想而知,audio device是通过它进行关联的

6. DevicesFactoryHalInterface

继续追踪,android/frameworks/av/media/libaudiohal/DevicesFactoryHalInterface.cpp

sp DevicesFactoryHalInterface::create() {
    if (hardware::audio::V4_0::IDevicesFactory::getService() != nullptr) {
        return new V4_0::DevicesFactoryHalHybrid();
    }
    if (hardware::audio::V2_0::IDevicesFactory::getService() != nullptr) {
        return new DevicesFactoryHalHybrid();
    }
    return nullptr;
}

这里会根据不同的HW版本返回不同的实例,android 9.0这里使用的是4.0版本。

7. DevicesFactoryHalHybrid

往下看,android/frameworks/av/media/libaudiohal/4.0/DevicesFactoryHalHybrid.cpp

  DevicesFactoryHalHybrid::DevicesFactoryHalHybrid()
          : mLocalFactory(new DevicesFactoryHalLocal()),
            mHidlFactory(new DevicesFactoryHalHidl()) {
  }
  
  DevicesFactoryHalHybrid::~DevicesFactoryHalHybrid() {
  }
  
  status_t DevicesFactoryHalHybrid::openDevice(const char *name, sp *device) {
      if (mHidlFactory != 0 && strcmp(AUDIO_HARDWARE_MODULE_ID_A2DP, name) != 0 &&
          strcmp(AUDIO_HARDWARE_MODULE_ID_HEARING_AID, name) != 0) {
          return mHidlFactory->openDevice(name, device);
      }
      return mLocalFactory->openDevice(name, device);
  }

这里构造函数有两个对象,openDevice()的时候会根据名字进行二选一。AUDIO_HARDWARE_MODULE_ID_A2DP查询发现是在AudioFlinger里

  static const char * const audio_interfaces[] = {
      AUDIO_HARDWARE_MODULE_ID_PRIMARY,
      AUDIO_HARDWARE_MODULE_ID_A2DP,
      AUDIO_HARDWARE_MODULE_ID_USB,
  };

看名字推测,A2DP是跟蓝牙相关,USB是U盘,那么PRIMARY就是其他普通情况下使用。

也就是说普通情况下是走的mHidlFactory流程

8. DevicesFactoryHalHidl

继续往下看,android/frameworks/av/media/libaudiohal/4.0/DevicesFactoryHalHidl.cpp

55  status_t DevicesFactoryHalHidl::openDevice(const char *name, sp *device) {
56      if (mDevicesFactory == 0) return NO_INIT;
57      Result retval = Result::NOT_INITIALIZED;
58      Return ret = mDevicesFactory->openDevice(
59              name,
60              [&](Result r, const sp& result) {
61                  retval = r;
62                  if (retval == Result::OK) {
63                      *device = new DeviceHalHidl(result);
64                  }
65              });
66      if (ret.isOk()) {
67          if (retval == Result::OK) return OK;
68          else if (retval == Result::INVALID_ARGUMENTS) return BAD_VALUE;
69          else return NO_INIT;
70      }
71      return FAILED_TRANSACTION;
72  }

这里用到了mDevicesFactory,在这个文件里往上搜,发现在构造函数里

mDevicesFactory = IDevicesFactory::getService();

这是个binder接口

9. DevicesFactory.impl.h

继续追,在android/hardware/interfaces/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h发现,这是个public接口

 Return DevicesFactory::openDevice(const hidl_string& moduleName, openDevice_cb _hidl_cb) {
     if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
         return openDevice(moduleName.c_str(), _hidl_cb);
     }
     return openDevice(moduleName.c_str(), _hidl_cb);
 }

在本文第7点中我们推测,普通情况下是使用PRIMARY,那么按流程走的是模板类,下面是它的private实现

 Return DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) {
     return openDevice(moduleName, _hidl_cb);
 }
 
 template 
 Return DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) {
     audio_hw_device_t* halDevice;
     Result retval(Result::INVALID_ARGUMENTS);
     sp result;
     int halStatus = loadAudioInterface(moduleName, &halDevice);
     if (halStatus == OK) {
         result = new DeviceShim(halDevice);
         retval = Result::OK;
     } else if (halStatus == -EINVAL) {
         retval = Result::NOT_INITIALIZED;
     }
     _hidl_cb(retval, result);
     return Void();
 }

主要是调用loadAudioInterface,然后返回PrimaryDevice的对象

80  int DevicesFactory::loadAudioInterface(const char* if_name, audio_hw_device_t** dev) {
81      const hw_module_t* mod;
82      int rc;
83  
84      rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
85      if (rc) {
86          ALOGE("%s couldn't load audio hw module %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID,
87                if_name, strerror(-rc));
88          goto out;
89      }
90      rc = audio_hw_device_open(mod, dev);
91      if (rc) {
92          ALOGE("%s couldn't open audio hw device in %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID,
93                if_name, strerror(-rc));
94          goto out;
95      }
96      if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) {
97          ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
98          rc = -EINVAL;
99          audio_hw_device_close(*dev);
100          goto out;
101      }
102      return OK;
103  
104  out:
105      *dev = NULL;
106      return rc;
107  }

这里就从Hal层获取到了dev,这是个PrimaryDevice的对象

10. PrimaryDevice.impl.h

继续往下分析,android/hardware/interfaces/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h

dev获取到了,那么我们回到第4点dev->setParameters,那么它应该是

  Return PrimaryDevice::setParameters(const hidl_vec& context,
                                              const hidl_vec& parameters) {
      return mDevice->setParameters(context, parameters);
  }

这里的mDevice是什么,我们往上看构造函数

PrimaryDevice::PrimaryDevice(audio_hw_device_t* device) : mDevice(new Device(device)) {}

到这里,还不能停

11. Device.impl.h

继续查,android/hardware/interfaces/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h,这里构造函数没什么特别的

Device::Device(audio_hw_device_t* device) : mDevice(device) {}

我们看它的setParameters

  Return Device::setParameters(const hidl_vec& context,
                                       const hidl_vec& parameters) {
      return setParametersImpl(context, parameters);
  }
12. ParametersUtil.impl.h

继续追踪,android/hardware/interfaces/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h

139  Result ParametersUtil::setParametersImpl(const hidl_vec& context,
140                                           const hidl_vec& parameters) {
141      AudioParameter params;
142      for (auto& pair : context) {
143          params.add(String8(pair.key.c_str()), String8(pair.value.c_str()));
144      }
145      for (size_t i = 0; i < parameters.size(); ++i) {
146          params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str()));
147      }
148      return setParams(params);
149  }
156  Result ParametersUtil::setParams(const AudioParameter& param) {
157      int halStatus = halSetParameters(param.toString().string());
158      return util::analyzeStatus(halStatus);
159  }
13. Device.impl.h

又回到了这里

59  int Device::halSetParameters(const char* keysAndValues) {
60      return mDevice->set_parameters(mDevice, keysAndValues);
61  }

可以看出,最终调用的是audio_hw_device_t里的set_parameters

14. audio_hw_device

在android/hardware/libhardware/include/hardware/audio.h查到这个结构体

typedef struct audio_hw_device audio_hw_device_t;

那么这个结构里成员是在哪里赋值的呢

15. audio_hw

在android/vendor/mediatek/proprietary_tv/open/hardware/audio/audio_hw_7_0/audio_hw.cpp这里,adev_open()的时候发现

adev->device.set_parameters = adev_set_parameters;
adev->device.get_parameters = adev_get_parameters;

那么,HAL最终实现的地方就找到了

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/719811.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存