Snap for 8870366 from 73e9304bee44bd435a408a8a9cd2a21f2d867fac to mainline-go-art-release

Change-Id: I4c7c2953404001691c712ffe9d2feb3e30d13f10
diff --git a/audio/device_port_sink.cpp b/audio/device_port_sink.cpp
index 3936805..a42f692 100644
--- a/audio/device_port_sink.cpp
+++ b/audio/device_port_sink.cpp
@@ -46,6 +46,13 @@
 constexpr int kMaxJitterUs = 3000;  // Enforced by CTS, should be <= 6ms
 
 struct TinyalsaSink : public DevicePortSink {
+    // Mostly magic numbers.
+    // In pcm, the hardware works with `period_size` granularity.
+    // The `period_count` is the number of `period_size` units in the pcm
+    // buffer.
+    static constexpr size_t kPcmPeriodCount = 8;
+    static constexpr size_t kPcmPeriodSizeMultiplier = 2;
+
     TinyalsaSink(unsigned pcmCard, unsigned pcmDevice,
                  const AudioConfig &cfg,
                  uint64_t &frames)
@@ -60,7 +67,8 @@
             , mPcm(talsa::pcmOpen(pcmCard, pcmDevice,
                                   util::countChannels(cfg.base.channelMask),
                                   cfg.base.sampleRateHz,
-                                  cfg.frameCount,
+                                  kPcmPeriodCount,
+                                  kPcmPeriodSizeMultiplier * cfg.frameCount / kPcmPeriodCount,
                                   true /* isOut */)) {
         if (mPcm) {
             LOG_ALWAYS_FATAL_IF(!talsa::pcmPrepare(mPcm.get()));
@@ -75,6 +83,15 @@
         mConsumeThread.join();
     }
 
+    static int getLatencyMs(const AudioConfig &cfg) {
+        constexpr size_t inMs = 1000;
+        const size_t numerator = kPcmPeriodSizeMultiplier * cfg.frameCount;
+        const size_t denominator = kPcmPeriodCount * cfg.base.sampleRateHz / inMs;
+
+        // integer division with rounding
+        return (numerator + (denominator >> 1)) / denominator;
+    }
+
     Result getPresentationPosition(uint64_t &frames, TimeSpec &ts) override {
         const AutoMutex lock(mFrameCountersMutex);
 
@@ -244,6 +261,10 @@
             , mInitialFrames(frames)
             , mFrames(frames) {}
 
+    static int getLatencyMs(const AudioConfig &) {
+        return 1;
+    }
+
     Result getPresentationPosition(uint64_t &frames, TimeSpec &ts) override {
         const AutoMutex lock(mFrameCountersMutex);
 
@@ -377,6 +398,22 @@
     return NullSink::create(cfg, readerBufferSizeHint, frames);
 }
 
+int DevicePortSink::getLatencyMs(const DeviceAddress &address, const AudioConfig &cfg) {
+    switch (xsd::stringToAudioDevice(address.deviceType)) {
+    default:
+        ALOGW("%s:%d unsupported device: '%s'", __func__, __LINE__, address.deviceType.c_str());
+        return FAILURE(-1);
+
+    case xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT:
+    case xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER:
+        return TinyalsaSink::getLatencyMs(cfg);
+
+    case xsd::AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX:
+    case xsd::AudioDevice::AUDIO_DEVICE_OUT_BUS:
+        return NullSink::getLatencyMs(cfg);
+    }
+}
+
 bool DevicePortSink::validateDeviceAddress(const DeviceAddress& address) {
     switch (xsd::stringToAudioDevice(address.deviceType)) {
     default:
diff --git a/audio/device_port_sink.h b/audio/device_port_sink.h
index 0276b25..9e9e3c5 100644
--- a/audio/device_port_sink.h
+++ b/audio/device_port_sink.h
@@ -40,6 +40,7 @@
                                                   const hidl_vec<AudioInOutFlag> &,
                                                   uint64_t &frames);
 
+    static int getLatencyMs(const DeviceAddress &, const AudioConfig &);
     static bool validateDeviceAddress(const DeviceAddress &);
 };
 
diff --git a/audio/device_port_source.cpp b/audio/device_port_source.cpp
index e4c4528..c3d9b84 100644
--- a/audio/device_port_source.cpp
+++ b/audio/device_port_source.cpp
@@ -50,6 +50,13 @@
 constexpr int kMaxJitterUs = 3000;  // Enforced by CTS, should be <= 6ms
 
 struct TinyalsaSource : public DevicePortSource {
+    // Mostly magic numbers.
+    // In pcm, the hardware works with `period_size` granularity.
+    // The `period_count` is the number of `period_size` units in the pcm
+    // buffer.
+    static constexpr size_t kPcmPeriodCount = 8;
+    static constexpr size_t kPcmPeriodSizeMultiplier = 2;
+
     TinyalsaSource(unsigned pcmCard, unsigned pcmDevice,
                    const AudioConfig &cfg, uint64_t &frames)
             : mStartNs(systemTime(SYSTEM_TIME_MONOTONIC))
@@ -62,7 +69,8 @@
             , mPcm(talsa::pcmOpen(pcmCard, pcmDevice,
                                   util::countChannels(cfg.base.channelMask),
                                   cfg.base.sampleRateHz,
-                                  cfg.frameCount,
+                                  kPcmPeriodCount,
+                                  kPcmPeriodSizeMultiplier * cfg.frameCount / kPcmPeriodCount,
                                   false /* isOut */)) {
         if (mPcm) {
             LOG_ALWAYS_FATAL_IF(!talsa::pcmPrepare(mPcm.get()));
diff --git a/audio/policy/primary_audio_policy_configuration.xml b/audio/policy/primary_audio_policy_configuration.xml
index 9307816..601453f 100644
--- a/audio/policy/primary_audio_policy_configuration.xml
+++ b/audio/policy/primary_audio_policy_configuration.xml
@@ -10,12 +10,12 @@
     </attachedDevices>
     <defaultOutputDevice>Speaker</defaultOutputDevice>
     <mixPorts>
-        <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+        <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY" maxOpenCount="1" maxActiveCount="1">
             <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                      samplingRates="8000 11025 16000 32000 44100 48000"
                      channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
         </mixPort>
-        <mixPort name="primary input" role="sink">
+        <mixPort name="primary input" role="sink" maxOpenCount="1" maxActiveCount="1">
             <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                      samplingRates="8000 11025 16000 32000 44100 48000"
                      channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
diff --git a/audio/stream_out.cpp b/audio/stream_out.cpp
index 0c8e518..1eabed3 100644
--- a/audio/stream_out.cpp
+++ b/audio/stream_out.cpp
@@ -212,8 +212,16 @@
     IStreamOut::WriteStatus doGetLatency() {
         IStreamOut::WriteStatus status;
 
-        status.retval = Result::OK;
-        status.reply.latencyMs = mStream->getLatency();
+        const int latencyMs =
+            DevicePortSink::getLatencyMs(mStream->getDeviceAddress(),
+                                         mStream->getAudioConfig());
+
+        if (latencyMs >= 0) {
+            status.retval = Result::OK;
+            status.reply.latencyMs = latencyMs;
+        } else {
+            status.retval = Result::INVALID_STATE;
+        }
 
         return status;
     }
@@ -358,7 +366,10 @@
 }
 
 Return<uint32_t> StreamOut::getLatency() {
-    return mCommon.getFrameCount() * 1000 / mCommon.getSampleRate();
+    const int latencyMs = DevicePortSink::getLatencyMs(getDeviceAddress(), getAudioConfig());
+
+    return (latencyMs >= 0) ? latencyMs :
+        (mCommon.getFrameCount() * 1000 / mCommon.getSampleRate());
 }
 
 Return<Result> StreamOut::setVolume(float left, float right) {
diff --git a/audio/talsa.cpp b/audio/talsa.cpp
index 4bc0c4f..a0fc73c 100644
--- a/audio/talsa.cpp
+++ b/audio/talsa.cpp
@@ -105,16 +105,16 @@
                                            const unsigned int card,
                                            const unsigned int nChannels,
                                            const size_t sampleRateHz,
-                                           const size_t frameCount,
+                                           const size_t periodCount,
+                                           const size_t periodSize,
                                            const bool isOut) {
     struct pcm_config pcm_config;
     memset(&pcm_config, 0, sizeof(pcm_config));
 
     pcm_config.channels = nChannels;
     pcm_config.rate = sampleRateHz;
-    pcm_config.period_count = 8; // Approx interrupts per buffer
-    // Approx frames between interrupts
-    pcm_config.period_size = 2 * frameCount / pcm_config.period_count;
+    pcm_config.period_count = periodCount; // Approx interrupts per buffer
+    pcm_config.period_size = periodSize; // Approx frames between interrupts
     pcm_config.format = PCM_FORMAT_S16_LE;
 
     PcmPtr pcm =
@@ -125,8 +125,8 @@
         return pcm;
     } else {
         ALOGE("%s:%d pcm_open failed for nChannels=%u sampleRateHz=%zu "
-              "frameCount=%zu isOut=%d with %s", __func__, __LINE__,
-              nChannels, sampleRateHz, frameCount, isOut,
+              "period_count=%zu period_size=%zu isOut=%d with %s", __func__, __LINE__,
+              nChannels, sampleRateHz, periodCount, periodSize, isOut,
               pcm_get_error(pcm.get()));
         return FAILURE(nullptr);
     }
diff --git a/audio/talsa.h b/audio/talsa.h
index c77b08f..6024158 100644
--- a/audio/talsa.h
+++ b/audio/talsa.h
@@ -31,7 +31,9 @@
 typedef struct pcm pcm_t;
 struct PcmDeleter { void operator()(pcm_t *x) const; };
 typedef std::unique_ptr<pcm_t, PcmDeleter> PcmPtr;
-PcmPtr pcmOpen(unsigned int dev, unsigned int card, unsigned int nChannels, size_t sampleRateHz, size_t frameCount, bool isOut);
+PcmPtr pcmOpen(unsigned int dev, unsigned int card, unsigned int nChannels,
+               size_t sampleRateHz, size_t periodCount, size_t periodSize,
+               bool isOut);
 bool pcmPrepare(pcm_t *pcm);
 bool pcmStart(pcm_t *pcm);
 bool pcmStop(pcm_t *pcm);
diff --git a/emulator-info.txt b/emulator-info.txt
index 13def53..43c68fc 100644
--- a/emulator-info.txt
+++ b/emulator-info.txt
@@ -1,2 +1,2 @@
 # Emulator (stable) version
-require version-emulator=8681204
+require version-emulator=8735603