Hi, I'm Glen from the Android Audio Team.
I focus on performance.
And in audio, that means one thing, latency.
The time it takes for signal to pass through a system.
For example, from the microphone to your app,
to the operating system to an audio codec and amplifier,
and finally out the speakers.
Basically there's a delay in how long
it takes sound to move through your CPU
all the way to your ears.
As the delay gets bigger, that's where buffering comes in.
But I'm getting ahead of myself.
Let me explain this using a chicken.
Imagine a chicken wants to cross the road.
It's an unusual road.
The cars all move at the same speed
and they're all the same distance apart.
Maybe they're self-driving cars.
Not too hard for our chicken.
If she makes a run for it between cars
she'll get across safely.
But there's an obstacle between the chicken
and the other side of the road.
A fence and a gate.
The colonel manages the gate.
He has nothing against chickens crossing the road,
but he likes to keep things neat and orderly.
So the colonel only opens the gate when he thinks it's time.
He opens the gate right after a car passes,
so there's plenty of time for the chicken
to cross the road before the next car comes.
The colonel works hard.
He cares about his job.
But every once in awhile the colonel
gets distracted and doesn't open the gate on time.
And if he's too late, [TIRES SCREECHING]
[CHICKEN SQUAWKS LOUDLY] uh.
The chicken in this analogy is the code
that processes audio data, both in your application
and in the Android audio framework.
The overall traffic flow represents the audio hardware,
which consumes data at a constant rate, no matter what.
Each car is a deadline.
Feed me data now.
In Android, audio samples are grouped together
into fixed size buffers.
The space between the cars is the buffer size.
You can think of this buffer size as either samples or time,
they're equivalent.
Each time a buffer is completed, the hardware
raises an interrupt request for a handler
to service the audio hardware.
I ate that buffer but I'm still hungry.
Feed me more data.
After servicing the hardware, the handler
wakes up a task to do the remaining work.
Now audio tasks are among the highest priority
real time tasks in the system.
So an audio I/O completion preempts
the current unrelated task, and we run the audio task instead.
Let's return to our chicken analogy.
The colonel with a c is the Linux kernel with a k.
The scheduler decides when the audio code should run
and the contexts which makes it so.
And this unfortunate situation?
Well, that's what happens if our code doesn't
meet the audio hardware deadline,
just because the colonel was distracted.
If this were video or UI code, we'd
say that we just janked or dropped a frame.
It looks bad, but it's not a huge problem
if it's only occasional.
But nobody likes it when you jank audio.
We call it popcorn, and it sounds awful.
Like this.
[AUDIO PLAYBACK]
[END AUDIO PLAYBACK]
If you're a manufacturer of an Android device,
and your QA team hears popcorn, that's
going to be a hard problem for you to solve.
Remember, audio tasks are among the highest priority
real time tasks in the system.
So what could possibly go wrong?
Well, there are many things that can
distract the kernel with a k from running
our audio tasks on time.
For example, a random kernel module,
perhaps an unrelated device driver disables
interrupts or disables preemption for too long.
Either way this kind of excessive disabling
will delay the kernel context switch code
from switching to the right audio task on time.
We use a tool called systrace to visualize this.
Here's a real example of a preemption latency bug.
The audio rights should be regular like our cars,
but zooming in we see that one audio write actually
took 130 milliseconds to complete.
That's a pop for sure.
It's like the colonel with a c distracted
from opening the gate, perhaps by a long phone call,
so that chicken didn't get released on time.
What would you do if this happened to you?
Well the easiest thing to do is just bloat up your buffers
like this puffer fish.
Just keep increasing the buffer sizes until the popcorn stops.
Rather than understanding and really fixing the root causes,
I have to admit I've done this once or twice also.
So it's pretty tempting to do it that way, but so wrong.
Uh-uh.
I'm not going to do it that way anymore.
My job now is to find all those places in the kernel
where this happens and fix them.
If you've ever looked at the Linux kernel,
you know how large and complicated
a project this might be.
It involves testing and reviewing
and fixing a lot of code.
Fortunately we're not doing this alone.
We're working with our silicon and device partners
to fix such bugs.
This will allow buffer sizes to be made smaller,
and reduce total audio latency.
Together we've made progress in reducing latency.
Many audio applications are now possible that weren't before.
Check out these resources to learn
how you can take advantage of the improvements already
available.
Now there's more to latency than distracted colonels.
Look for other videos in this series
as we delve into the root causes of latency,
what we're doing to reduce it, and how
you can take advantage of improvements
to write great audio apps.
Thank you for watching.
And remember, don't distract the colonel.
[SCREAMS]
[MUSIC PLAYING]