Coder Social home page Coder Social logo

pulseaudio-modules-droid2's Introduction

PulseAudio Droid modules
========================

Building of droid modules is split to two packages
 * common (and common-devel) which contains shared library code for use in
   PulseAudio modules in this package and for inclusion in other projects
 * droid with actual PulseAudio modules

Supported Android versions:

 * 4.1.x with Qualcomm extensions (tested with 4.1.2)
 * 4.2.x
 * 4.4.x
 * 5.x
 * 6.0.x
 * 7.x

Headers for defining devices and strings for different droid versions are in
src/common/droid-util-audio.h (legacy headers for Jolla 1 in droid-util-41qc.h).

When new devices with relevant new enums appear, add enum check to configure.ac,
for example: (the CC_CHECK_DROID_ENUM m4 macro will create define HAVE_ENUM_FOO
if the enum FOO exists in HAL audio.h)
    CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_DEVICE_OUT_IP])

and then in droid-util-audio.h add the enum to proper tables with ifdefs:
    /* string_conversion_table_output_device[] */
    #ifdef HAVE_ENUM_AUDIO_DEVICE_OUT_IP
        STRING_ENTRY( AUDIO_DEVICE_OUT_IP ),
    #endif

    /* string_conversion_table_output_device_fancy[] */
    #ifdef HAVE_ENUM_AUDIO_DEVICE_OUT_IP
        { AUDIO_DEVICE_OUT_IP, "output-ip" },
    #endif

The purpose of droid-modules is to "replace AudioFlinger". Many hardware
adaptations use ALSA as the kernel interface, but there is no saying that
someday vendor would create and use something proprietary or otherwise
different from ALSA. Also the ALSA implementation in droid devices may contain
funny ways to achieve things (notable example is voicecall) which might be
difficult to do if interfacing directly with ALSA to replace AudioFlinger.
Also using ALSA directly would mean that the whole HAL adaptation would need to
be ported for each new device adaptation. With droid-modules this is much more
simpler, with somewhat stable HAL (HALv3 as of now, also different vendors add
their own incompatible extensions) API. In best scenarios using droid-modules
with new device is just compiling against target.

Components
==========

module-droid-card
-----------------

Ideally only module-droid-card is loaded and then droid-card loads
configuration, creates profiles and loads sinks and sources based on the
selected profile.

Droid-card reads configuration from /vendor/etc/audio_policy.conf or
/system/etc/audio_policy.conf, depending on which is found first. If vendor
config is found, configuration is read from there, otherwise from system
configuration.

default profile
---------------

When module-droid-card is loaded with default arguments, droid-card will try
to create a default profile (called surprisingly "default"). The default
profile will try to merge useful output and input streams to one profile,
to allow use of possible low latency outputs or multiple inputs if the
input streams are split to multiple devices.

For example configuration with

    audio_hw_modules {
        primary {
            outputs {
                primary {}
                deep_buffer {}
            }
            inputs {
                builtin {}
                external {}
            }
        }
        other {
            ...
        }
    }

The default profile would contain two sinks, sink.primary and sink.deep_buffer
and one source, source.builtin_external. Then this combined source would use
either "builtin" or "external" input stream, depending on which one has the
input route currently in use (for example, input-wired_headset from "external"
and input-back_mic from "builtin" input stream).

Usually this default profile is everything that is needed in normal use, and
additional profiles created should be needed only for testing things out etc.

additional profiles
-------------------

In addition to the default profile all input and output definitions are
translated to PulseAudio card profiles. For example configuration with

    audio_hw_modules {
        primary {
            outputs {
                primary {}
                lpa {}
            }
            inputs {
                primary {}
            }
        }
        other {
            ...
        }
    }

Would map to card profiles (input-output) primary-primary and lpa-primary.
When module-droid-card is run without module_id argument, as default "primary"
is used.

virtual profiles
----------------

In addition to aforementioned card profiles, droid-card creates some additional
virtual profiles. These virtual profiles are used when enabling voicecall
routings etc. When virtual profile is enabled, possible sinks and sources
previously active profile had are not removed.

As an illustration, following command line sequence enables voicecall mode and
routes audio to internal handsfree (ihf - "handsfree speaker"):

(Before starting, droid_card.primary is using profile primary-primary and
sink.primary port output-speaker)

pactl set-card-profile droid_card.primary voicecall
pactl set-sink-port sink.primary output-parking
pactl set-sink-port sink.primary output-speaker

After this, when there is an active voicecall (created by ofono for example),
voice audio starts to flow between modem and audio chip.

To disable voicecall and return to media audio:

pactl set-card-profile droid_card.primary primary-primary
pactl set-sink-port sink.primary output-parking
pactl set-sink-port sink.primary output-speaker

With this example sequence sinks and sources are the ones from primary-primary
card profile, and they are maintained for the whole duration of the voicecall
and after.

This sequence follows the droid HAL idea that when changing audio mode the mode
change is done when next routing change happens. output-parking and
input-parking ports are just convenience for PulseAudio, where setting already
active port is a no-op (output/input-parking doesn't do any real routing
changes).

Current virtual profiles are:
 * voicecall
 * voicecall-record
 * communication
 * ringtone

Communication profile is used for VoIP-like applications, to enable some
voicecall related algorithms without being in voicecall. Ringtone profile
should be used when ringtone is playing, to again enable possible loudness
related optimizations etc. Voicecall-record profile can be enabled when
voicecall profile is active.

module-droid-sink and module-droid-source
-----------------------------------------

Normally user should not need to load droid-sink or droid-source modules by
hand, but droid-card loads appropriate modules based on the active card
profile.

Output and input ports for droid-sink and droid-source are generated from the
audio_policy.conf, where each device generates (usually) one port, for example:

    audio_hw_modules {
        primary {
            outputs {
                primary {
                    devices = AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADPHONE
                    }
                lpa {}
            }
            inputs {
                primary {
                    devices = AUDIO_DEVICE_IN_BUILTIN_MIC
                    }
            }
        }
    }

Would create following ports for sink.primary:
 * output-speaker
 * output-earpiece
 * output-wired_headphone
 * output-speaker+wired_headphone

And for source.primary:
 * input-builtin_mic

Only exception to one device one port rule is if output device list has both
OUT_SPEAKER and OUT_WIRED_HEADPHONE, then one additional combination port is
generated. How the devices are called in sink and source ports are defined in
droid-util-XXX.h

Changing output routing is then as simple as

pactl set-sink-port sink.primary output-wired_headphone

Sink or source do not track possible headphone/other wired accessory plugging,
but this needs to be handled elsewhere and then that other entity needs to
control sinks and sources. (For example in SailfishOS this entity is OHM with
accessory-plugin and pulseaudio-policy-enforcement module for actually making
the port switching)

Classifying sinks and sources
-----------------------------

Certain property values are set to all active sinks and sources based on their
functionality to ease device classification.

Currently following properties are set:

 * For droid sinks
  * droid.output.primary
  * droid.output.low_latency
  * droid.output.media_latency
  * droid.output.offload
 * For droid sources
  * droid.input.builtin
  * droid.input.external

If the property is set and with value "true", the sink or source should be
used for the property type. If the property is not defined or contains
value "false" it shouldn't be used for the property type.

For example, we might have sink.primary and sink.low_latency with following
properties:

 * sink.primary
  * droid.output.primary "true"
  * droid.output.media_latency "true"
 * sink.low_latency
  * droid.output.low_latency "true"

There also may be just one sink, with all the properties defined as "true"
and so on.

Similarly if there is only one input device the sole source would have both
input type properties set as "true", but it also might be that the different
input type properties are split to two different sources.

Quirks
------

There are some adaptations that require hacks to get things working. These
hacks can be enabled or disabled with module argument "quirks". Some quirks
are enabled by default with some adaptations etc.

Currently there are following quirks:

 * input_atoi
  * Enabled by default with Android versions 5 and up.
  * Due to how atoi works in bionic vs libc we need to pass the input
    route a bit funny. If input routing doesn't work switch this on or off.
 * set_parameters
  * Disabled by default.
  * Some adaptations need to use hw module's generic set_parameters call
    to change input routing. If input routing doesn't work switch this
    on or off. (mostly just older adaptations)
 * close_input
  * Enabled by default.
  * Close input stream when not in use instead of suspending the stream.
    Cannot be changed when multiple inputs are merged to single source.
 * unload_no_close
  * Disabled by default.
  * Don't call audio_hw_device_close() for the hw module when unloading.
    Mostly useful for tracking module unload issues.
 * no_hw_volume
  * Disabled by default.
  * Some broken implementations are incorrectly probed for supporting hw
    volume control. This is manifested by always full volume with volume
    control not affecting volume level. To fix this enable this quirk.

For example, to disable input_atoi and enable close_input quirks, use module
argument

    quirks=-input_atoi,+close_input

Volume control during voicecall
-------------------------------

When voicecall virtual profile is enabled, active droid-sink is internally
switched to voicecall volume control mode. What this means is changing the sink
volume or volume of normal streams connected to the sink do not change active
voicecall volume. Special stream is needed to control the voicecall volume
level. By default this stream is identified by stream property media.role,
with value "phone". This can be changed by providing module arguments
voice_property_key and voice_property_value to module-droid-card.

Usually droid HAL has 6 volume levels for voicecall.

Temporary sink audio routing
----------------------------

It is possible to add temporary route to sink audio routing with specific
stream property. When stream with property key
droid.device.additional-route connects to droid-sink, this extra route is set
(if possible) as the enabled route for the duration of the stream.

For example, if droid-sink has active port output-wired_headphone:

paplay --property=droid.device.additional-route=AUDIO_DEVICE_OUT_SPEAKER a.wav

As long as the new stream is connected to droid-sink, output routing is
SPEAKER.

module-droid-keepalive
----------------------

Keepalive module is MCE (https://github.com/nemomobile/mce) specific module
tracking sink/source activity and keeping a WAKELOCK when there are active
streams.

pulseaudio-modules-droid2's People

Contributors

jusa avatar sledges avatar mariogrip avatar mlehtima avatar kimmoli avatar lbt avatar siteshwar avatar martinbrook avatar ballock avatar litew avatar saukko avatar elros34 avatar

Stargazers

Lee Nelson avatar

Watchers

Ricardo Mendoza avatar James Cloos avatar  avatar Johannah Sprinz avatar Flo Lee avatar Ubports yumi bot avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.