New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 704439 link

Starred by 2 users

Issue metadata

Status: Fixed
Owner:
Last visit > 30 days ago
Closed: Sep 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Chrome
Pri: 3
Type: Bug



Sign in to add a comment

factory: Use HiFi ucm to replace audio.conf

Project Member Reported by hungte@chromium.org, Mar 23 2017

Issue description

Currently the factory audio tests rely on a YAML or JSON "audio.conf" to initialize audio interfaces (dmic, spk, headphone, ...). This is because the audio bring up process is:

 - Factory needs audio for initial build
 - Audio vendor provides audio.conf
 - Later on, release images need config for cras in later builds like EVT/DVT/PVT.
 - Audio vendor provides HiFi ucm files.

audio.conf and HiFi ucm are very similar, so it's probably a duplicated effort for vendor to provide audio.conf.
It's also confusing to explain how the audio.conf should look like to new vendors.
And it also makes factory toolkit need to have explicit correct audio.conf files before it can test audio on a device.

As a result, we think it may be better to directly support UCM file in factory audio component and deprecate audio.conf, so we can always request for UCM to use.
And when a toolkit runs on a device without audio.conf, it can try to look for system hifi ucm to init audio interfaces.

P.S: We may also need additional logic to "guess" card name just like Chrome does, for example trying "Internal Speaker" first than other names.
 

Comment 1 by hungte@chromium.org, Mar 23 2017

Temporarily assign to yhong as a Noogler starter project.

Comment 2 by hungte@chromium.org, Mar 23 2017

p.s: you can use alsaucm to apply the ucm config, but we should not add extra dependency to cras. Just the config files so it's easier for cherry-picking into factory branches.

Comment 3 by hungte@chromium.org, May 18 2017

Cc: yllin@chromium.org petershih@chromium.org yhong@chromium.org
Owner: petershih@chromium.org
Reassign to petershih since yhong may be busy at HWID.

Comment 4 by hungte@chromium.org, Jul 14 2017

Cc: -petershih@chromium.org -yhong@chromium.org -yllin@chromium.org chromeos-factory-eng@google.com
According to the above comments, I'd like to set the goal to:
* Factory toolkit uses alsa ucm config directly, so vendor no longer needs to provide audio.conf.


If it is allowed to use the 'alsaucm' binary, the steps might be something like:
1. Use 'alsaucm' to enable the device
# alsaucm -n -b - <<EOM                                                                                                                                                                          
> open kblrt5514rt5663max
> set _verb HiFi
> set _enadev Speaker
> EOM

2. Play the wav file:
# aplay -t wav foo.wav

3. Disable the speaker (should we do this? any other cleanup command?)
# alsaucm -n -b - <<EOM                                                                                                                                                                          
> open kblrt5514rt5663max
> set _verb HiFi
> set _disdev Speaker
> EOM


Is this process sounds okay?

And, some more questions:

Question 1:
There might be multiple sound card names under /usr/share/alsa/ucm, which should be used?
Further, multiple verbs (e.g., 'Record', 'Hifi', 'Voice', 'Voice_Call' in SDP4430.conf) and multiple devices (e.g., 'Speaker', 'Headphone', 'Internal mic', 'Mic', 'HDMI1', etc.) might be defined , which should be used?

I think this differs on different boards, and depend on which device we're controlling (e.g., speaker, left headphone, right headphone, left mic, right mic, etc.).
(If the answer is yes, we still need a config file to specify the 'card-name', 'verb' and 'device_name', which is similar to the current audio.conf)

Question 2:
Can we depend on the binary 'alsaucm' (like stated above) for bring up?

Question 3:
Is it possible that a vendor can only provide audio.conf, but cannot provide ucm configs? If no, should we deprecate audio.conf?

Comment 6 by hungte@chromium.org, Aug 16 2017

Q1 => ask audio team how do they select for chrome?
Correct me if I'm wrong, but I think today in audio.conf we simply create a list of verb & devies, while the real thing to test or use verb is given from test list arguments. So it should make no difference when you move to ucm?

Q2 => I'm ok with using alsaucm if it's available on chromebook test images.
But can it take files not in /usr/share/alsa/ucm?
We may need to override files for manufacturing process.

Q3 => I think all vendors will need to provide ucm in the end for release images, so we may be able to deprecate in future.
So maybe two more questions:

Question 4:
Will the binary 'alsaucm' be ready when bring up a board?

Question 5:
Can the binary 'alsaucm' reads configures outside of /usr/share/alsa/ucm.


Q5 => I guess the answer is no. In this case, maybe we can use bind mount, just as what we do for /etc/chrome_dev.conf?
Some conclusions of an offline discussions with hychao@.

Facts about UCM files:
1. UCM is a format defined by ALSA. All audio devices used in Chrome OS are ALSA devices.
2. Chrome OS adds some customized fields in UCM format (e.g., the 'default-gain' field mentioned in the meeting)
3. The binary 'alsaucm' can be used to control the devices regarding to UCM files. But according to audio team's experience, this binary might not be stable/reliable enough.
   (Further, it does not parse the customized fields mentioned in the previous point)

Facts about cras:
1. It's a service maintained by the audio team, so it's well supported.
2. It's included in the test image, and is stable/reliable enough to use in factory bring up process (even when the audio driver is still under development).
3. It provides dbus interface to list audio devices.

Suggestions from audio team:
* Use 'cras' service to control audio devices. So factory team don't bother to parse UCM files, and list/map/control all audio devices.
Detail steps might be something like:
1. Use dbus interface to list all audio devices.
2. Use 'cras_test_client --select_output' to choose the output device
3. Use 'cras_test_client --playback_file' to play a raw audio file.


From factory's point of view, several tasks need to be done:
1. Mute a specific device (e.g., left speaker, right speaker, head phone, mic, ext mic, etc.)
2. Enable/Disable a specific device
3. Set speaker volume (possibly to a 'raw' value)
4. Playback a raw/wav file
5. (maybe more...)
Different methods to get it done:

1. Parse UCM files manually
  * Can refer to alsa-lib source code
  * 'cras' use alsa-lib, so they didn't do the parse themselves
Pros:
  * Only depends on aplay, amixer, arecord
Cons:
  * Need to write parse code manually.
  * Need to rewrite if UCM file format is changed (not likely to happen).
  * Need to know the device name (e.g., 'kblrt5514rt5663max'), so we can locate the UCM conf (e.g., /usr/share/alsa/ucm/kblrt5514rt5663max/HiFi.conf'). Maybe 'aplay -L' helps
    * See 'get_sysdefault_playback_device' in https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/client/cros/audio/alsa_utils.py
    * Or a darg parameter for the pytest
  * How to map the 'SectionDevice' in a UCM config file?
    * SectionDevice."Speaker".0
    * SectionDevice."Headphone".0
    * etc.

2. Use alsa-lib to parse/apply UCM files
  * cras uses this way by calling snd_use_case_* interfaces
    See https://chromium.googlesource.com/chromiumos/third_party/adhd/+/master/cras/src/server/cras_alsa_ucm.c

Pros:
  * No need to write parser manually
Cons:
  * Alsa-lib is all in C, which depends on other C libraries.
  * Factory toolkit don't want to build C code (cross-platform issue, dependency, complicate the build process, etc...)

3. Use 'alsaucm' binary to parse/apply UCM files
Pros:
  * 'alsaucm' exports several commands of alsa-lib interfaces. We can use it to parse/apply UCM configs.
Cons:
  * Depend on 'alsaucm' binary.
  * We don't control the real command via 'amixer -c' anymore; alsaucm will do that.
  * Hard to debug if something goes wrong (because we don't know alsaucm invokes which 'amixer -c' commands).

4. Depends on cras service
  * dbus-send --system --type=method_call --print-reply --dest=org.chromium.cras /org/chromium/cras org.chromium.cras.Control.GetNodes
  * Output like:
   array [
      dict entry(
         string "IsInput"
         variant             boolean false
      )
      dict entry(
         string "Id"
         variant             uint64 21474836480
      )
      dict entry(
         string "DeviceName"
         variant             string "kblrt5514rt5663max: :0,0"
      )
      dict entry(
         string "StableDeviceId"
         variant             uint64 1923447123
      )
      dict entry(
         string "StableDeviceIdNew"
         variant             uint64 1923447123
      )
      dict entry(
         string "Type"
         variant             string "INTERNAL_SPEAKER"
      )
      dict entry(
         string "Name"
         variant             string "Speaker"
      )
      dict entry(
         string "MicPositions"
         variant             string ""
      )
      dict entry(
         string "Active"
         variant             boolean false
      )
      dict entry(
         string "PluggedTime"
         variant             uint64 1502876121538032
      )
      dict entry(
         string "NodeVolume"
         variant             uint64 4
      )
      dict entry(
         string "NodeCaptureGain"
         variant             int64 0
      )
      dict entry(
         string "HotwordModels"
         variant             string ""
      )
   ]
Pros:
  * Easy to use.
Cons:
  * Depends on cras. If there's an issue in cras, it blocks the factory test.
  * The 'Id' is used in other command like 'adjust-volume' or 'mute'. This is not the device id 'amixer -c' uses.
  * Need to rewrite the audio testing suite to use cras to select device, play sound, and record sound.
  * More issues if we depend on cras. E.g., how to detect headphone jack is plugged in? how to adjust the 'raw' volume value?


In conclusion, Method 1 should be the best solution for factory team.
* audio.conf and UCM HiFi.conf are actually identical.
* phonenixshen@ has some experience to convert a HiFi.conf to the audio.conf.
* We gain fully control over the audio devices.
For option 2, we can safely assume libasound.so and all dependencies exists on dut (commands like amixer/aplay depend on it), and use ctypes to wrap libasound.so. So no need to compile c code.
Not sure if this will be easier than option 1.

Cons: need extra efforts to make this work on station mode.


More thoughts on parsing/applying UCM configs manually or not...

Option 1: Parse/Apply UCM configs manually
Pros:
  * Easily load other UCM configs outside /usr/share/alsa/ucm
  * Easily trace all amixer commands
Cons:
  * Need to parse/apply UCM configs
    * Reference: http://www.alsa-project.org/alsa-doc/alsa-lib/group__ucm.html
    * More details at alsa-lib/src/ucm/parser.c
    * Need some maintenance effort in factory team

Option 2: Parse/Apply UCM configs by libasound.so or alsaucm
Pros:
  * No need to parse/apply UCM configs manually.
Cons:
  * How to load UCM configs outside /usr/share/alsa/ucm? Bind mount should work.
  * Cannot trace all amixer commands
    * We can trace libasound.so / alsaucm commands. They invokes amixer commands for us.
    * Cras service also depends on libasound.so. So this information should be sufficient for audio team / factory to debug.
Reply #10:

Yes. It's much easier than parsing/applying UCM configs by ourselves. Also, considering the extra effort on station mode as you mentioned, Option 3 seems to be a (strictly) better option.
Sorted out several core usages for alsaucm.

After entering alsaucm in interaction mode (option -i), one can do:

List all UCM configs:
> listcards

Assume we are dealing with card 'kblrt5514rt5663max'

List all verbs:
> open kblrt5514rt5663max
> list _verbs

List all devices under a verb 'HiFi':
> open kblrt5514rt5663max
> set _verb HiFi
> list _devices
All devices under the verb will be listed. For example:
0: Speaker
1: Headphone
2: Internal Mic
3: Mic
4: HDMI1
5: HDMI2
6: HDMI3

Enable the device 'Speaker':
> open kblrt5514rt5663max
> set _verb HiFi
> set _enadev Speaker

Reset sound card to default state:
> open kblrt5514rt5663max
> reset

Get playback PCM for device 'Speaker':
> open kblrt5514rt5663max
> set _verb HiFi
> get PlaybackPCM/Speaker
Output looks like: PlaybackPCM/Speaker=hw:kblrt5514rt5663,0

Get capture PCM for device 'Mic':
> open kblrt5514rt5663max
> set _verb HiFi
> get CapturePCM/Mic
Output looks like: CapturePCM/Mic=hw:kblrt5514rt5663,1

Jack name of device 'Mic' can also be fetched:
> open kblrt5514rt5663max
> set _verb HiFi
> get JackName/Mic
Output looks like: JackName/Mic=kblrt5514rt5663max Headset Jack

And for its jack type:
> open kblrt5514rt5663max
> set _verb HiFi
> get JackType/Mic
Output looks like: JackType/Mic=gpio

The playback/capture PCM should be of form:
hw:card-name,<num>
The <num> is the device index, which can be used for aplay/arecord.

References:
1. https://chromium.googlesource.com/chromiumos/third_party/adhd/+/master/cras/src/server/cras_alsa_ucm.c
2. https://patchwork.kernel.org/patch/9468495/
The audio conf (i.e., audio.conf / audio.json) we defined in our factory flow supports following operations:
1. Initialize sound card
2. Enable / Disable a certain device
3. Mute a certain device
4. Adjust volume for a certain device
5. Do customized amixer commands
6. Invoke customized script

A UCM config file can ONLY cover the first two operations. That is:
1. Initialize the sound card
2. Enable/Disable a certain device

For operations 3 and 4, they are not commonly used (e.g., they are not used in a recent board). And in case they are needed, we need to ask vendors to provide the amixer commands, which is basically the audio.conf.

For operation 5 and 6, they are customized amixer commands, so we need to prepare the audio.conf.

So, in conclusion, we need audio.conf to support operation 3~6. But, in most of the use case, we don't need it for a normal factory flow.

A new class will be implemented to use UCM files to support operation 1 and 2. An optional audio.conf can be passed to this new class to support operations 3~6.
Question: How to get a good guess for UCM config names?

UCM config names are the folder basename under /usr/share/alsa/ucm
For example:
localhost / # ls -al /usr/share/alsa/ucm                                                                                                                                                         
total 60
drwxr-xr-x. 15 root root 4096 Aug 23 18:03 .
drwxr-xr-x.  9 root root 4096 Aug 23 17:51 ..
drwxr-xr-x.  2 root root 4096 Aug 16 16:31 'Chat 150 C'
drwxr-xr-x.  2 root root 4096 Aug 17 17:04 DB410c
drwxr-xr-x.  2 root root 4096 Jul 17 02:50 GoogleNyan
drwxr-xr-x.  2 root root 4096 Jul 17 02:50 'Jabra SPEAK 810'
drwxr-xr-x.  2 root root 4096 Jul 17 02:50 PAZ00
drwxr-xr-x.  2 root root 4096 Jul 17 02:50 PandaBoard
drwxr-xr-x.  2 root root 4096 Jul 17 02:50 PandaBoardES
drwxr-xr-x.  2 root root 4096 Aug 16 17:22 SDP4430
drwxr-xr-x.  2 root root 4096 Jul 17 02:50 VEYRON-I2S
drwxr-xr-x.  2 root root 4096 Aug 16 17:23 broadwell-rt286
drwxr-xr-x.  2 root root 4096 Sep  1 11:55 kblrt5514rt5663max
drwxr-xr-x.  2 root root 4096 Jul 17 02:50 skylake-rt286
drwxr-xr-x.  2 root root 4096 Jul 17 02:50 tegraalc5632

The question is, how can we get a good guess to choose a folder?

Answer:
Thanks hychao@ to provide this.

For playback devices, use aplay -l. For example:
localhost kblrt5514rt5663max # aplay -l                                                                                                                                                                           
**** List of PLAYBACK Hardware Devices ****
card 0: kblrt5514rt5663 [kblrt5514rt5663max], device 0: Audio (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: kblrt5514rt5663 [kblrt5514rt5663max], device 4: Hdmi1 (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: kblrt5514rt5663 [kblrt5514rt5663max], device 5: Hdmi2 (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: kblrt5514rt5663 [kblrt5514rt5663max], device 6: Hdmi3 (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

The strings in the brackets should be the name.

Similarly, for recording devices, use arecord -l:
localhost kblrt5514rt5663max # arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: kblrt5514rt5663 [kblrt5514rt5663max], device 1: Audio Record (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: kblrt5514rt5663 [kblrt5514rt5663max], device 2: Wake on Voice (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: kblrt5514rt5663 [kblrt5514rt5663max], device 3: dmiccap (*) []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Re #14,

> 5. Do customized amixer commands
Is there any example for this?
Most of the commands in audio.schema.json are covered by case 1~4,
except last few items like "headphone_jack_detect", but I don't think we are using these now.

> 6. Invoke customized script
This is only for audio_quality test which needs to deal with special fixture,
We should remove this from audio api, and find a better place for them.
Re #16:

> > 5. Do customized amixer commands
> Is there any example for this?
> Most of the commands in audio.schema.json are covered by case 1~4,
> except last few items like "headphone_jack_detect", but I don't think we are > using these now.
To best of my knowledge, no customized amixer commands are spotted in our factory flow. But, the design of the audio.conf can indeed support these kind of operations. This is the only reason why I listed here.

> > 6. Invoke customized script
> This is only for audio_quality test which needs to deal with special fixture,
> We should remove this from audio api, and find a better place for them.
Great! After we did that, we can possibly remove audio.conf thoroughly.


Although one of the motivation is to remove audio.conf at all. But, at least for the first few CLs, I'd like to keep audio.conf for several reasons:

1. Backward compatibility

2. Able to do customized amixer commands
   As mentioned, this should not be necessary in normal cases. However, anythings can happen during an audio driver bring-up. I think it might be good to have a structured way to perform amixer commands, this is exactly what audio.conf does.

3. Still has great improvement. No audio.conf needed in most of the cases
   Audio.conf is now considered as an overwrite setting over UCM configs. So, in most of the cases, we still don't need audio.conf at all to control the audio devices. This matches our original motivation.
Project Member

Comment 18 by bugdroid1@chromium.org, Sep 9 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/platform/factory/+/3f24c8d7d062b0c1c6f7a41009aa43337c36c67a

commit 3f24c8d7d062b0c1c6f7a41009aa43337c36c67a
Author: Shen-En Shih <petershih@chromium.org>
Date: Sat Sep 09 07:14:06 2017

audio: Define device type

Define supported input and output audio devices.

TEST=make test
BUG= chromium:704439 

Change-Id: I07b9b8a32742109e65b70ca51fc19c4ca9d58544
Reviewed-on: https://chromium-review.googlesource.com/650267
Commit-Ready: Shen-En Shih <petershih@chromium.org>
Tested-by: Shen-En Shih <petershih@chromium.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>

[modify] https://crrev.com/3f24c8d7d062b0c1c6f7a41009aa43337c36c67a/py/device/audio/base.py

Project Member

Comment 19 by bugdroid1@chromium.org, Sep 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/platform/factory/+/cf65e6b6a1421b1095f2c783c960255cc829fec8

commit cf65e6b6a1421b1095f2c783c960255cc829fec8
Author: Shen-En Shih <petershih@chromium.org>
Date: Fri Sep 22 13:10:09 2017

audio: Refactor out MixerController and ConfigManager

Separate out the following two parts:
1. Dealing with mixer controller
2. Parse config files

To support this, two base classes are defined. One of them
deals with mixer controller, and the other one deals with
logics to parse and apply the audio config files.

BUG= chromium:704439 
TEST=make test
TEST=manually test

Change-Id: Ic095d1f42912914e7a9bcd0d1734810613f2e1e8
Reviewed-on: https://chromium-review.googlesource.com/650268
Commit-Ready: Shen-En Shih <petershih@chromium.org>
Tested-by: Shen-En Shih <petershih@chromium.org>
Reviewed-by: Shen-En Shih <petershih@chromium.org>

[modify] https://crrev.com/cf65e6b6a1421b1095f2c783c960255cc829fec8/py/device/audio/alsa.py
[add] https://crrev.com/cf65e6b6a1421b1095f2c783c960255cc829fec8/py/device/audio/config_manager.py
[modify] https://crrev.com/cf65e6b6a1421b1095f2c783c960255cc829fec8/py/device/audio/base.py
[modify] https://crrev.com/cf65e6b6a1421b1095f2c783c960255cc829fec8/py/device/audio/tinyalsa.py

Project Member

Comment 20 by bugdroid1@chromium.org, Sep 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/platform/factory/+/5e7af863810bad16d3f1bf56f949ade866399df5

commit 5e7af863810bad16d3f1bf56f949ade866399df5
Author: Shen-En Shih <petershih@chromium.org>
Date: Fri Sep 22 13:10:09 2017

audio: Refine return behavior for ApplyAudioConfig

The return behavior of ApplyAudioConfig is now refined as follows:
1. Return False if the operation is not defined in the config file.
2. Raise exception if the operations is failed to apply.
3. Return True if the operations are applied successfully.

BUG= chromium:704439 
TEST=make test

Change-Id: I0037fdd960586cacbb01ff1a4f68b0d6dbf5e551
Reviewed-on: https://chromium-review.googlesource.com/650269
Commit-Ready: Shen-En Shih <petershih@chromium.org>
Tested-by: Shen-En Shih <petershih@chromium.org>
Reviewed-by: Shen-En Shih <petershih@chromium.org>

[modify] https://crrev.com/5e7af863810bad16d3f1bf56f949ade866399df5/py/device/audio/config_manager.py
[modify] https://crrev.com/5e7af863810bad16d3f1bf56f949ade866399df5/py/device/audio/base.py

Project Member

Comment 21 by bugdroid1@chromium.org, Sep 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/platform/factory/+/8e9d319b1f6c98f0e8091cf9a14b56a8c108e172

commit 8e9d319b1f6c98f0e8091cf9a14b56a8c108e172
Author: Shen-En Shih <petershih@chromium.org>
Date: Fri Sep 22 15:08:56 2017

audio: Implement UCM config manager

Implement the UCM config manager to control
sound cards according to UCM config files.

BUG= chromium:704439 
TEST=make test
TEST=manually test

Change-Id: I775c00ac082cf66065af4fc486f5b8729f956289
Reviewed-on: https://chromium-review.googlesource.com/650270
Commit-Ready: Shen-En Shih <petershih@chromium.org>
Tested-by: Shen-En Shih <petershih@chromium.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>

[modify] https://crrev.com/8e9d319b1f6c98f0e8091cf9a14b56a8c108e172/py/device/audio/alsa.py
[modify] https://crrev.com/8e9d319b1f6c98f0e8091cf9a14b56a8c108e172/py/device/audio/config_manager.py

Status: Fixed (was: Assigned)
So now if a project does not define audio.conf, can we still run audio tests using system HiFi?

Can you update the audio test doc to explain what to do?

Comment 24 by dchan@chromium.org, Jan 22 2018

Status: Archived (was: Fixed)

Comment 25 by dchan@chromium.org, Jan 23 2018

Status: Fixed (was: Archived)

Sign in to add a comment