diff options
Diffstat (limited to 'services')
| -rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 28 | ||||
| -rw-r--r-- | services/audioflinger/AudioFlinger.h | 3 | ||||
| -rw-r--r-- | services/audioflinger/AudioStreamOut.cpp | 85 | ||||
| -rw-r--r-- | services/audioflinger/AudioStreamOut.h | 13 | ||||
| -rw-r--r-- | services/audioflinger/SpdifStreamOut.cpp | 47 | ||||
| -rw-r--r-- | services/audioflinger/SpdifStreamOut.h | 9 | ||||
| -rw-r--r-- | services/audioflinger/Threads.cpp | 27 | ||||
| -rw-r--r-- | services/audioflinger/Threads.h | 20 | ||||
| -rwxr-xr-x | services/audiopolicy/common/include/Volume.h | 2 | ||||
| -rwxr-xr-x | services/audiopolicy/common/include/policy.h | 10 | ||||
| -rw-r--r-- | services/audiopolicy/common/managerdefinitions/Android.mk | 1 | ||||
| -rw-r--r-- | services/audiopolicy/common/managerdefinitions/include/SessionRoute.h | 118 | ||||
| -rw-r--r-- | services/audiopolicy/common/managerdefinitions/src/SessionRoute.cpp | 124 | ||||
| -rwxr-xr-x | services/audiopolicy/enginedefault/src/Engine.cpp | 14 | ||||
| -rw-r--r-- | services/audiopolicy/managerdefault/AudioPolicyManager.cpp | 96 | ||||
| -rw-r--r-- | services/audiopolicy/managerdefault/AudioPolicyManager.h | 88 | 
16 files changed, 395 insertions, 290 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 52fce34..8f1e050 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1252,11 +1252,9 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)      if (client == 0) {          return;      } -    bool clientAdded = false; +    pid_t pid = IPCThreadState::self()->getCallingPid();      {          Mutex::Autolock _cl(mClientLock); - -        pid_t pid = IPCThreadState::self()->getCallingPid();          if (mNotificationClients.indexOfKey(pid) < 0) {              sp<NotificationClient> notificationClient = new NotificationClient(this,                                                                                  client, @@ -1267,22 +1265,19 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)              sp<IBinder> binder = IInterface::asBinder(client);              binder->linkToDeath(notificationClient); -            clientAdded = true;          }      }      // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the      // ThreadBase mutex and the locking order is ThreadBase::mLock then AudioFlinger::mClientLock. -    if (clientAdded) { -        // the config change is always sent from playback or record threads to avoid deadlock -        // with AudioSystem::gLock -        for (size_t i = 0; i < mPlaybackThreads.size(); i++) { -            mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_OPENED); -        } +    // the config change is always sent from playback or record threads to avoid deadlock +    // with AudioSystem::gLock +    for (size_t i = 0; i < mPlaybackThreads.size(); i++) { +        mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_OPENED, pid); +    } -        for (size_t i = 0; i < mRecordThreads.size(); i++) { -            mRecordThreads.valueAt(i)->sendIoConfigEvent(AUDIO_INPUT_OPENED); -        } +    for (size_t i = 0; i < mRecordThreads.size(); i++) { +        mRecordThreads.valueAt(i)->sendIoConfigEvent(AUDIO_INPUT_OPENED, pid);      }  } @@ -1316,12 +1311,15 @@ void AudioFlinger::removeNotificationClient(pid_t pid)  }  void AudioFlinger::ioConfigChanged(audio_io_config_event event, -                                   const sp<AudioIoDescriptor>& ioDesc) +                                   const sp<AudioIoDescriptor>& ioDesc, +                                   pid_t pid)  {      Mutex::Autolock _l(mClientLock);      size_t size = mNotificationClients.size();      for (size_t i = 0; i < size; i++) { -        mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioDesc); +        if ((pid == 0) || (mNotificationClients.keyAt(i) == pid)) { +            mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioDesc); +        }      }  } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index d087ced..4f7e27d 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -559,7 +559,8 @@ private:                float streamVolume_l(audio_stream_type_t stream) const                                  { return mStreamTypes[stream].volume; }                void ioConfigChanged(audio_io_config_event event, -                                   const sp<AudioIoDescriptor>& ioDesc); +                                   const sp<AudioIoDescriptor>& ioDesc, +                                   pid_t pid = 0);                // Allocate an audio_io_handle_t, session ID, effect ID, or audio_module_handle_t.                // They all share the same ID space, but the namespaces are actually independent diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp index e6d8f09..f953cc8 100644 --- a/services/audioflinger/AudioStreamOut.cpp +++ b/services/audioflinger/AudioStreamOut.cpp @@ -27,25 +27,59 @@  namespace android {  // ---------------------------------------------------------------------------- -  AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags)          : audioHwDev(dev)          , stream(NULL)          , flags(flags) +        , mFramesWritten(0) +        , mFramesWrittenAtStandby(0) +        , mRenderPosition(0) +        , mRateMultiplier(1) +        , mHalFormatIsLinearPcm(false) +        , mHalFrameSize(0)  {  } -audio_hw_device_t* AudioStreamOut::hwDev() const +audio_hw_device_t *AudioStreamOut::hwDev() const  {      return audioHwDev->hwDevice();  } -status_t AudioStreamOut::getRenderPosition(uint32_t *frames) +status_t AudioStreamOut::getRenderPosition(uint64_t *frames)  {      if (stream == NULL) {          return NO_INIT;      } -    return stream->get_render_position(stream, frames); + +    uint32_t halPosition = 0; +    status_t status = stream->get_render_position(stream, &halPosition); +    if (status != NO_ERROR) { +        return status; +    } + +    // Maintain a 64-bit render position using the 32-bit result from the HAL. +    // This delta calculation relies on the arithmetic overflow behavior +    // of integers. For example (100 - 0xFFFFFFF0) = 116. +    uint32_t truncatedPosition = (uint32_t)mRenderPosition; +    int32_t deltaHalPosition = (int32_t)(halPosition - truncatedPosition); +    if (deltaHalPosition > 0) { +        mRenderPosition += deltaHalPosition; +    } +    // Scale from HAL sample rate to application rate. +    *frames = mRenderPosition / mRateMultiplier; + +    return status; +} + +// return bottom 32-bits of the render position +status_t AudioStreamOut::getRenderPosition(uint32_t *frames) +{ +    uint64_t position64 = 0; +    status_t status = getRenderPosition(&position64); +    if (status == NO_ERROR) { +        *frames = (uint32_t)position64; +    } +    return status;  }  status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) @@ -53,7 +87,26 @@ status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timesp      if (stream == NULL) {          return NO_INIT;      } -    return stream->get_presentation_position(stream, frames, timestamp); + +    uint64_t halPosition = 0; +    status_t status = stream->get_presentation_position(stream, &halPosition, timestamp); +    if (status != NO_ERROR) { +        return status; +    } + +    // Adjust for standby using HAL rate frames. +    // Only apply this correction if the HAL is getting PCM frames. +    if (mHalFormatIsLinearPcm) { +        uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ? +                0 : (halPosition - mFramesWrittenAtStandby); +        // Scale from HAL sample rate to application rate. +        *frames = adjustedPosition / mRateMultiplier; +    } else { +        // For offloaded MP3 and other compressed formats. +        *frames = halPosition; +    } + +    return status;  }  status_t AudioStreamOut::open( @@ -62,7 +115,7 @@ status_t AudioStreamOut::open(          struct audio_config *config,          const char *address)  { -    audio_stream_out_t* outStream; +    audio_stream_out_t *outStream;      int status = hwDev()->open_output_stream(              hwDev(),              handle, @@ -82,6 +135,9 @@ status_t AudioStreamOut::open(      if (status == NO_ERROR) {          stream = outStream; +        mHalFormatIsLinearPcm = audio_is_linear_pcm(config->format); +        ALOGI("AudioStreamOut::open(), mHalFormatIsLinearPcm = %d", (int)mHalFormatIsLinearPcm); +        mHalFrameSize = audio_stream_out_frame_size(stream);      }      return status; @@ -89,13 +145,15 @@ status_t AudioStreamOut::open(  size_t AudioStreamOut::getFrameSize()  { -    ALOG_ASSERT(stream != NULL); -    return audio_stream_out_frame_size(stream); +    return mHalFrameSize;  }  int AudioStreamOut::flush()  {      ALOG_ASSERT(stream != NULL); +    mRenderPosition = 0; +    mFramesWritten = 0; +    mFramesWrittenAtStandby = 0;      if (stream->flush != NULL) {          return stream->flush(stream);      } @@ -105,13 +163,20 @@ int AudioStreamOut::flush()  int AudioStreamOut::standby()  {      ALOG_ASSERT(stream != NULL); +    mRenderPosition = 0; +    mFramesWrittenAtStandby = mFramesWritten; +    ALOGI("AudioStreamOut::standby(), mFramesWrittenAtStandby = %llu", mFramesWrittenAtStandby);      return stream->common.standby(&stream->common);  } -ssize_t AudioStreamOut::write(const void* buffer, size_t bytes) +ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)  {      ALOG_ASSERT(stream != NULL); -    return stream->write(stream, buffer, bytes); +    ssize_t bytesWritten = stream->write(stream, buffer, numBytes); +    if (bytesWritten > 0 && mHalFrameSize > 0) { +        mFramesWritten += bytesWritten / mHalFrameSize; +    } +    return bytesWritten;  }  } // namespace android diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h index e91ca9c..761e771 100644 --- a/services/audioflinger/AudioStreamOut.h +++ b/services/audioflinger/AudioStreamOut.h @@ -53,7 +53,10 @@ public:      virtual ~AudioStreamOut() { } -    virtual status_t getRenderPosition(uint32_t *frames); +    // Get the bottom 32-bits of the 64-bit render position. +    status_t getRenderPosition(uint32_t *frames); + +    virtual status_t getRenderPosition(uint64_t *frames);      virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp); @@ -76,6 +79,14 @@ public:      virtual status_t flush();      virtual status_t standby(); + +protected: +    uint64_t             mFramesWritten; // reset by flush +    uint64_t             mFramesWrittenAtStandby; +    uint64_t             mRenderPosition; // reset by flush or standby +    int                  mRateMultiplier; +    bool                 mHalFormatIsLinearPcm; +    size_t               mHalFrameSize;  };  } // namespace android diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp index ac637ef..6af7bce 100644 --- a/services/audioflinger/SpdifStreamOut.cpp +++ b/services/audioflinger/SpdifStreamOut.cpp @@ -36,10 +36,7 @@ SpdifStreamOut::SpdifStreamOut(AudioHwDevice *dev,              audio_output_flags_t flags,              audio_format_t format)          : AudioStreamOut(dev,flags) -        , mRateMultiplier(1)          , mSpdifEncoder(this, format) -        , mRenderPositionHal(0) -        , mPreviousHalPosition32(0)  {  } @@ -97,62 +94,18 @@ status_t SpdifStreamOut::open(      return status;  } -// Account for possibly higher sample rate. -status_t SpdifStreamOut::getRenderPosition(uint32_t *frames) -{ -    uint32_t halPosition = 0; -    status_t status = AudioStreamOut::getRenderPosition(&halPosition); -    if (status != NO_ERROR) { -        return status; -    } - -    // Accumulate a 64-bit position so that we wrap at the right place. -    if (mRateMultiplier != 1) { -        // Maintain a 64-bit render position. -        int32_t deltaHalPosition = (int32_t)(halPosition - mPreviousHalPosition32); -        mPreviousHalPosition32 = halPosition; -        mRenderPositionHal += deltaHalPosition; - -        // Scale from device sample rate to application rate. -        uint64_t renderPositionApp = mRenderPositionHal / mRateMultiplier; -        ALOGV("SpdifStreamOut::getRenderPosition() " -            "renderPositionAppRate = %llu = %llu / %u\n", -            renderPositionApp, mRenderPositionHal, mRateMultiplier); - -        *frames = (uint32_t)renderPositionApp; -    } else { -        *frames = halPosition; -    } -    return status; -} -  int SpdifStreamOut::flush()  {      mSpdifEncoder.reset(); -    mRenderPositionHal = 0; -    mPreviousHalPosition32 = 0;      return AudioStreamOut::flush();  }  int SpdifStreamOut::standby()  {      mSpdifEncoder.reset(); -    mRenderPositionHal = 0; -    mPreviousHalPosition32 = 0;      return AudioStreamOut::standby();  } -// Account for possibly higher sample rate. -// This is much easier when all the values are 64-bit. -status_t SpdifStreamOut::getPresentationPosition(uint64_t *frames, -        struct timespec *timestamp) -{ -    uint64_t halFrames = 0; -    status_t status = AudioStreamOut::getPresentationPosition(&halFrames, timestamp); -    *frames = halFrames / mRateMultiplier; -    return status; -} -  size_t SpdifStreamOut::getFrameSize()  {      return sizeof(int8_t); diff --git a/services/audioflinger/SpdifStreamOut.h b/services/audioflinger/SpdifStreamOut.h index d81c064..a61a7bd 100644 --- a/services/audioflinger/SpdifStreamOut.h +++ b/services/audioflinger/SpdifStreamOut.h @@ -49,10 +49,6 @@ public:              struct audio_config *config,              const char *address); -    virtual status_t getRenderPosition(uint32_t *frames); - -    virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp); -      /**      * Write audio buffer to driver. Returns number of bytes written, or a      * negative status_t. If at least one frame was written successfully prior to the error, @@ -92,13 +88,8 @@ private:          SpdifStreamOut * const mSpdifStreamOut;      }; -    int                  mRateMultiplier;      MySPDIFEncoder       mSpdifEncoder; -    // Used to implement getRenderPosition() -    int64_t              mRenderPositionHal; -    uint32_t             mPreviousHalPosition32; -      ssize_t  writeDataBurst(const void* data, size_t bytes);      ssize_t  writeInternal(const void* buffer, size_t bytes); diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 966fb5c..d9f1a83 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -532,7 +532,8 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio          // RecordThread::readInputParameters_l()          //FIXME: mStandby should be true here. Is this some kind of hack?          mStandby(false), mOutDevice(outDevice), mInDevice(inDevice), -        mPrevInDevice(AUDIO_DEVICE_NONE), mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id), +        mPrevOutDevice(AUDIO_DEVICE_NONE), mPrevInDevice(AUDIO_DEVICE_NONE), +        mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),          // mName will be set by concrete (non-virtual) subclass          mDeathRecipient(new PMDeathRecipient(this)),          mSystemReady(systemReady) @@ -627,16 +628,16 @@ status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)      return status;  } -void AudioFlinger::ThreadBase::sendIoConfigEvent(audio_io_config_event event) +void AudioFlinger::ThreadBase::sendIoConfigEvent(audio_io_config_event event, pid_t pid)  {      Mutex::Autolock _l(mLock); -    sendIoConfigEvent_l(event); +    sendIoConfigEvent_l(event, pid);  }  // sendIoConfigEvent_l() must be called with ThreadBase::mLock held -void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event) +void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event, pid_t pid)  { -    sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event); +    sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, pid);      sendConfigEvent_l(configEvent);  } @@ -706,7 +707,7 @@ void AudioFlinger::ThreadBase::processConfigEvents_l()          } break;          case CFG_EVENT_IO: {              IoConfigEventData *data = (IoConfigEventData *)event->mData.get(); -            ioConfigChanged(data->mEvent); +            ioConfigChanged(data->mEvent, data->mPid);          } break;          case CFG_EVENT_SET_PARAMETER: {              SetParameterConfigEventData *data = (SetParameterConfigEventData *)event->mData.get(); @@ -1999,7 +2000,7 @@ String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)      return out_s8;  } -void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event event) { +void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event event, pid_t pid) {      sp<AudioIoDescriptor> desc = new AudioIoDescriptor();      ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event); @@ -2021,7 +2022,7 @@ void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event event)      default:          break;      } -    mAudioFlinger->ioConfigChanged(event, desc); +    mAudioFlinger->ioConfigChanged(event, desc, pid);  }  void AudioFlinger::PlaybackThread::writeCallback() @@ -3133,7 +3134,10 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat      for (size_t i = 0; i < mEffectChains.size(); i++) {          mEffectChains[i]->setDevice_l(type);      } -    bool configChanged = mOutDevice != type; + +    // mPrevOutDevice is the latest device set by createAudioPatch_l(). It is not set when +    // the thread is created so that the first patch creation triggers an ioConfigChanged callback +    bool configChanged = mPrevOutDevice != type;      mOutDevice = type;      mPatch = *patch; @@ -3163,6 +3167,7 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat          *handle = AUDIO_PATCH_HANDLE_NONE;      }      if (configChanged) { +        mPrevOutDevice = type;          sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);      }      return status; @@ -6871,7 +6876,7 @@ String8 AudioFlinger::RecordThread::getParameters(const String8& keys)      return out_s8;  } -void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event event) { +void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event event, pid_t pid) {      sp<AudioIoDescriptor> desc = new AudioIoDescriptor();      desc->mIoHandle = mId; @@ -6891,7 +6896,7 @@ void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event event) {      default:          break;      } -    mAudioFlinger->ioConfigChanged(event, desc); +    mAudioFlinger->ioConfigChanged(event, desc, pid);  }  void AudioFlinger::RecordThread::readInputParameters_l() diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 0783371..46ac300 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -104,21 +104,22 @@ public:      class IoConfigEventData : public ConfigEventData {      public: -        IoConfigEventData(audio_io_config_event event) : -            mEvent(event) {} +        IoConfigEventData(audio_io_config_event event, pid_t pid) : +            mEvent(event), mPid(pid) {}          virtual  void dump(char *buffer, size_t size) {              snprintf(buffer, size, "IO event: event %d\n", mEvent);          }          const audio_io_config_event mEvent; +        const pid_t                 mPid;      };      class IoConfigEvent : public ConfigEvent {      public: -        IoConfigEvent(audio_io_config_event event) : +        IoConfigEvent(audio_io_config_event event, pid_t pid) :              ConfigEvent(CFG_EVENT_IO) { -            mData = new IoConfigEventData(event); +            mData = new IoConfigEventData(event, pid);          }          virtual ~IoConfigEvent() {}      }; @@ -255,13 +256,13 @@ public:                                                      status_t& status) = 0;      virtual     status_t    setParameters(const String8& keyValuePairs);      virtual     String8     getParameters(const String8& keys) = 0; -    virtual     void        ioConfigChanged(audio_io_config_event event) = 0; +    virtual     void        ioConfigChanged(audio_io_config_event event, pid_t pid = 0) = 0;                  // sendConfigEvent_l() must be called with ThreadBase::mLock held                  // Can temporarily release the lock if waiting for a reply from                  // processConfigEvents_l().                  status_t    sendConfigEvent_l(sp<ConfigEvent>& event); -                void        sendIoConfigEvent(audio_io_config_event event); -                void        sendIoConfigEvent_l(audio_io_config_event event); +                void        sendIoConfigEvent(audio_io_config_event event, pid_t pid = 0); +                void        sendIoConfigEvent_l(audio_io_config_event event, pid_t pid = 0);                  void        sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio);                  void        sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio);                  status_t    sendSetParameterConfigEvent_l(const String8& keyValuePair); @@ -436,6 +437,7 @@ protected:                  bool                    mStandby;     // Whether thread is currently in standby.                  audio_devices_t         mOutDevice;   // output device                  audio_devices_t         mInDevice;    // input device +                audio_devices_t         mPrevOutDevice;   // previous output device                  audio_devices_t         mPrevInDevice;    // previous input device                  struct audio_patch      mPatch;                  audio_source_t          mAudioSource; @@ -572,7 +574,7 @@ public:                                  { return android_atomic_acquire_load(&mSuspended) > 0; }      virtual     String8     getParameters(const String8& keys); -    virtual     void        ioConfigChanged(audio_io_config_event event); +    virtual     void        ioConfigChanged(audio_io_config_event event, pid_t pid = 0);                  status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);                  // FIXME rename mixBuffer() to sinkBuffer() and remove int16_t* dependency.                  // Consider also removing and passing an explicit mMainBuffer initialization @@ -1254,7 +1256,7 @@ public:                                                 status_t& status);      virtual void        cacheParameters_l() {}      virtual String8     getParameters(const String8& keys); -    virtual void        ioConfigChanged(audio_io_config_event event); +    virtual void        ioConfigChanged(audio_io_config_event event, pid_t pid = 0);      virtual status_t    createAudioPatch_l(const struct audio_patch *patch,                                             audio_patch_handle_t *handle);      virtual status_t    releaseAudioPatch_l(const audio_patch_handle_t handle); diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h index 4205589..712f7a7 100755 --- a/services/audiopolicy/common/include/Volume.h +++ b/services/audiopolicy/common/include/Volume.h @@ -82,6 +82,8 @@ public:              //  - HDMI-CEC system audio mode only output: give priority to available item in order.              if (device & AUDIO_DEVICE_OUT_SPEAKER) {                  device = AUDIO_DEVICE_OUT_SPEAKER; +            } else if (device & AUDIO_DEVICE_OUT_SPEAKER_SAFE) { +                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;              } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {                  device = AUDIO_DEVICE_OUT_HDMI_ARC;              } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) { diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h index 4eef02f..4b73e3c 100755 --- a/services/audiopolicy/common/include/policy.h +++ b/services/audiopolicy/common/include/policy.h @@ -37,8 +37,9 @@   * A device mask for all audio input and output devices where matching inputs/outputs on device   * type alone is not enough: the address must match too   */ -#define APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX | \ -                                            AUDIO_DEVICE_OUT_REMOTE_SUBMIX) +#define APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL (AUDIO_DEVICE_OUT_REMOTE_SUBMIX) + +#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX)  /**   * Check if the state given correspond to an in call state. @@ -80,5 +81,8 @@ static inline bool is_virtual_input_device(audio_devices_t device)   */  static inline bool device_distinguishes_on_address(audio_devices_t device)  { -    return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0); +    return (((device & AUDIO_DEVICE_BIT_IN) != 0) && +            ((~AUDIO_DEVICE_BIT_IN & device & APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL) != 0)) || +           (((device & AUDIO_DEVICE_BIT_IN) == 0) && +            ((device & APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL) != 0));  } diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk index 7c265aa..8728ff3 100644 --- a/services/audiopolicy/common/managerdefinitions/Android.mk +++ b/services/audiopolicy/common/managerdefinitions/Android.mk @@ -16,6 +16,7 @@ LOCAL_SRC_FILES:= \      src/EffectDescriptor.cpp \      src/ConfigParsingUtils.cpp \      src/SoundTriggerSession.cpp \ +    src/SessionRoute.cpp \  LOCAL_SHARED_LIBRARIES := \      libcutils \ diff --git a/services/audiopolicy/common/managerdefinitions/include/SessionRoute.h b/services/audiopolicy/common/managerdefinitions/include/SessionRoute.h new file mode 100644 index 0000000..b4feaf0 --- /dev/null +++ b/services/audiopolicy/common/managerdefinitions/include/SessionRoute.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <system/audio.h> +#include <utils/KeyedVector.h> +#include <utils/RefBase.h> +#include <utils/Errors.h> + +namespace android { + +class DeviceDescriptor; + +class SessionRoute : public RefBase +{ +public: +    // For Input (Source) routes, use STREAM_TYPE_NA ("NA" = "not applicable)for the +    // streamType argument +    static const audio_stream_type_t STREAM_TYPE_NA = AUDIO_STREAM_DEFAULT; + +    // For Output (Sink) routes, use SOURCE_TYPE_NA ("NA" = "not applicable") for the +    // source argument + +    static const audio_source_t SOURCE_TYPE_NA = AUDIO_SOURCE_DEFAULT; + +    SessionRoute(audio_session_t session, +                 audio_stream_type_t streamType, +                 audio_source_t source, +                 sp<DeviceDescriptor> deviceDescriptor, +                 uid_t uid) +        : mUid(uid), +          mSession(session), +          mDeviceDescriptor(deviceDescriptor), +          mRefCount(0), +          mActivityCount(0), +          mChanged(false), +          mStreamType(streamType), +          mSource(source) +    {} + +    void log(const char* prefix); + +    bool isActive() { +        return (mDeviceDescriptor != 0) && (mChanged || (mActivityCount > 0)); +    } + +    uid_t                       mUid; +    audio_session_t             mSession; +    sp<DeviceDescriptor>        mDeviceDescriptor; + +    // "reference" counting +    int                         mRefCount;      // +/- on references +    int                         mActivityCount; // +/- on start/stop +    bool                        mChanged; +    // for outputs +    const audio_stream_type_t   mStreamType; +    // for inputs +    const audio_source_t        mSource; +}; + +class SessionRouteMap: public KeyedVector<audio_session_t, sp<SessionRoute> > +{ +public: +    // These constants identify the SessionRoutMap as holding EITHER input routes, +    // or output routes.  An error will occur if an attempt is made to add a SessionRoute +    // object with mStreamType == STREAM_TYPE_NA (i.e. an input SessionRoute) to a +    // SessionRoutMap that is marked for output (i.e. mMapType == SESSION_ROUTE_MAP_OUTPUT) +    // and similarly  for output SessionRoutes and Input SessionRouteMaps. +    typedef enum +    { +        MAPTYPE_INPUT = 0, +        MAPTYPE_OUTPUT = 1 +    } session_route_map_type_t; + +    SessionRouteMap(session_route_map_type_t mapType) : +        mMapType(mapType) +    {} + +    bool hasRoute(audio_session_t session); + +    void removeRoute(audio_session_t session); + +    int incRouteActivity(audio_session_t session); +    int decRouteActivity(audio_session_t session); +    bool hasRouteChanged(audio_session_t session); // also clears the changed flag +    void log(const char* caption); + +    // Specify an Output(Sink) route by passing SessionRoute::SOURCE_TYPE_NA in the +    // source argument. +    // Specify an Input(Source) rout by passing SessionRoute::AUDIO_STREAM_DEFAULT +    // in the streamType argument. +    void addRoute(audio_session_t session, +                  audio_stream_type_t streamType, +                  audio_source_t source, +                  sp<DeviceDescriptor> deviceDescriptor, +                  uid_t uid); + +private: +    // Used to mark a SessionRoute as for either inputs (mMapType == kSessionRouteMap_Input) +    // or outputs (mMapType == kSessionRouteMap_Output) +    const session_route_map_type_t mMapType; +}; + +}; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/SessionRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/SessionRoute.cpp new file mode 100644 index 0000000..7ecfa44 --- /dev/null +++ b/services/audiopolicy/common/managerdefinitions/src/SessionRoute.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "APM::SessionRoute" +//#define LOG_NDEBUG 0 + +#include "SessionRoute.h" +#include "HwModule.h" +#include "AudioGain.h" +#include "DeviceDescriptor.h" +#include <utils/Log.h> + +namespace android { + +// --- SessionRoute class implementation +void SessionRoute::log(const char* prefix) +{ +    ALOGI("%s[SessionRoute strm:0x%X, src:%d, sess:0x%X, dev:0x%X refs:%d act:%d", +          prefix, mStreamType, mSource, mSession, +          mDeviceDescriptor != 0 ? mDeviceDescriptor->type() : AUDIO_DEVICE_NONE, +          mRefCount, mActivityCount); +} + +// --- SessionRouteMap class implementation +bool SessionRouteMap::hasRoute(audio_session_t session) +{ +    return indexOfKey(session) >= 0 && valueFor(session)->mDeviceDescriptor != 0; +} + +bool SessionRouteMap::hasRouteChanged(audio_session_t session) +{ +    if (indexOfKey(session) >= 0) { +        if (valueFor(session)->mChanged) { +            valueFor(session)->mChanged = false; +            return true; +        } +    } +    return false; +} + +void SessionRouteMap::removeRoute(audio_session_t session) +{ +    sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0; +    if (route != 0) { +        ALOG_ASSERT(route->mRefCount > 0); +        --route->mRefCount; +        if (route->mRefCount <= 0) { +            removeItem(session); +        } +    } +} + +int SessionRouteMap::incRouteActivity(audio_session_t session) +{ +    sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0; +    return route != 0 ? ++(route->mActivityCount) : -1; +} + +int SessionRouteMap::decRouteActivity(audio_session_t session) +{ +    sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0; +    if (route != 0 && route->mActivityCount > 0) { +        return --(route->mActivityCount); +    } else { +        return -1; +    } +} + +void SessionRouteMap::log(const char* caption) +{ +    ALOGI("%s ----", caption); +    for(size_t index = 0; index < size(); index++) { +        valueAt(index)->log("  "); +    } +} + +void SessionRouteMap::addRoute(audio_session_t session, +                               audio_stream_type_t streamType, +                               audio_source_t source, +                               sp<DeviceDescriptor> descriptor, +                               uid_t uid) +{ +    if (mMapType == MAPTYPE_INPUT && streamType != SessionRoute::STREAM_TYPE_NA) { +        ALOGE("Adding Output Route to InputRouteMap"); +        return; +    } else if (mMapType == MAPTYPE_OUTPUT && source != SessionRoute::SOURCE_TYPE_NA) { +        ALOGE("Adding Input Route to OutputRouteMap"); +        return; +    } + +    sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0; + +    if (route != 0) { +        if (((route->mDeviceDescriptor == 0) && (descriptor != 0)) || +                ((route->mDeviceDescriptor != 0) && +                 ((descriptor == 0) || (!route->mDeviceDescriptor->equals(descriptor))))) { +            route->mChanged = true; +        } +        route->mRefCount++; +        route->mDeviceDescriptor = descriptor; +    } else { +        route = new SessionRoute(session, streamType, source, descriptor, uid); +        route->mRefCount++; +        add(session, route); +        if (descriptor != 0) { +            route->mChanged = true; +        } +    } +} + +} // namespace android diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp index 7a785eb..0686414 100755 --- a/services/audiopolicy/enginedefault/src/Engine.cpp +++ b/services/audiopolicy/enginedefault/src/Engine.cpp @@ -319,8 +319,11 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const              device = getDeviceForStrategy(STRATEGY_SONIFICATION);              //user "safe" speaker if available instead of normal speaker to avoid triggering              //other acoustic safety mechanisms for notification -            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) -                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE; +            if ((device & AUDIO_DEVICE_OUT_SPEAKER) && +                    (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { +                device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; +                device &= ~AUDIO_DEVICE_OUT_SPEAKER; +            }          } else if (outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {              // while media is playing (or has recently played), use the same device              device = getDeviceForStrategy(STRATEGY_MEDIA); @@ -329,8 +332,11 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const              device = getDeviceForStrategy(STRATEGY_SONIFICATION);              //user "safe" speaker if available instead of normal speaker to avoid triggering              //other acoustic safety mechanisms for notification -            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) -                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE; +            if ((device & AUDIO_DEVICE_OUT_SPEAKER) && +                    (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { +                device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; +                device &= ~AUDIO_DEVICE_OUT_SPEAKER; +            }          }          break; diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 6983b5c..6d99640 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -1076,6 +1076,9 @@ status_t AudioPolicyManager::startSource(sp<AudioOutputDescriptor> outputDesc,          beaconMuteLatency = handleEventForBeacon(STARTING_OUTPUT);      } +    // check active before incrementing usage count +    bool force = !outputDesc->isActive(); +      // increment usage count for this stream on the requested output:      // NOTE that the usage count is the same for duplicated output and hardware output which is      // necessary for a correct control of hardware output routing by startOutput() and stopOutput() @@ -1091,7 +1094,6 @@ status_t AudioPolicyManager::startSource(sp<AudioOutputDescriptor> outputDesc,                              (strategy == STRATEGY_SONIFICATION_RESPECTFUL) ||                              (beaconMuteLatency > 0);          uint32_t waitMs = beaconMuteLatency; -        bool force = false;          for (size_t i = 0; i < mOutputs.size(); i++) {              sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);              if (desc != outputDesc) { @@ -4721,99 +4723,7 @@ void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream,      }  } -// --- SessionRoute class implementation -void AudioPolicyManager::SessionRoute::log(const char* prefix) { -    ALOGI("%s[SessionRoute strm:0x%X, src:%d, sess:0x%X, dev:0x%X refs:%d act:%d", -          prefix, mStreamType, mSource, mSession, -          mDeviceDescriptor != 0 ? mDeviceDescriptor->type() : AUDIO_DEVICE_NONE, -          mRefCount, mActivityCount); -} - -// --- SessionRouteMap class implementation -bool AudioPolicyManager::SessionRouteMap::hasRoute(audio_session_t session) -{ -    return indexOfKey(session) >= 0 && valueFor(session)->mDeviceDescriptor != 0; -} - -bool AudioPolicyManager::SessionRouteMap::hasRouteChanged(audio_session_t session) -{ -    if (indexOfKey(session) >= 0) { -        if (valueFor(session)->mChanged) { -            valueFor(session)->mChanged = false; -            return true; -        } -    } -    return false; -} - -void AudioPolicyManager::SessionRouteMap::removeRoute(audio_session_t session) -{ -    sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0; -    if (route != 0) { -        ALOG_ASSERT(route->mRefCount > 0); -        --route->mRefCount; -        if (route->mRefCount <= 0) { -            removeItem(session); -        } -    } -} - -int AudioPolicyManager::SessionRouteMap::incRouteActivity(audio_session_t session) -{ -    sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0; -    return route != 0 ? ++(route->mActivityCount) : -1; -} -int AudioPolicyManager::SessionRouteMap::decRouteActivity(audio_session_t session) -{ -    sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0; -    if (route != 0 && route->mActivityCount > 0) { -        return --(route->mActivityCount); -    } else { -        return -1; -    } -} - -void AudioPolicyManager::SessionRouteMap::log(const char* caption) { -    ALOGI("%s ----", caption); -    for(size_t index = 0; index < size(); index++) { -        valueAt(index)->log("  "); -    } -} - -void AudioPolicyManager::SessionRouteMap::addRoute(audio_session_t session, -                                                   audio_stream_type_t streamType, -                                                   audio_source_t source, -                                                   sp<DeviceDescriptor> descriptor, -                                                   uid_t uid) -{ -    if (mMapType == MAPTYPE_INPUT && streamType != SessionRoute::STREAM_TYPE_NA) { -        ALOGE("Adding Output Route to InputRouteMap"); -        return; -    } else if (mMapType == MAPTYPE_OUTPUT && source != SessionRoute::SOURCE_TYPE_NA) { -        ALOGE("Adding Input Route to OutputRouteMap"); -        return; -    } - -    sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0; - -    if (route != 0) { -        if (((route->mDeviceDescriptor == 0) && (descriptor != 0)) || -                ((route->mDeviceDescriptor != 0) && -                 ((descriptor == 0) || (!route->mDeviceDescriptor->equals(descriptor))))) { -            route->mChanged = true; -        } -        route->mRefCount++; -        route->mDeviceDescriptor = descriptor; -    } else { -        route = new AudioPolicyManager::SessionRoute(session, streamType, source, descriptor, uid); -        route->mRefCount++; -        add(session, route); -        if (descriptor != 0) { -            route->mChanged = true; -        } -    } -}  void AudioPolicyManager::defaultAudioPolicyConfig(void)  { diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index cf64154..bf3ae4a 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -42,6 +42,7 @@  #include <EffectDescriptor.h>  #include <SoundTriggerSession.h>  #include <StreamDescriptor.h> +#include <SessionRoute.h>  namespace android { @@ -237,93 +238,6 @@ public:          routing_strategy getStrategy(audio_stream_type_t stream) const;  protected: -        class SessionRoute : public RefBase { -        public: -            // For Input (Source) routes, use STREAM_TYPE_NA ("NA" = "not applicable)for the -            // streamType argument -            static const audio_stream_type_t STREAM_TYPE_NA = AUDIO_STREAM_DEFAULT; - -            // For Output (Sink) routes, use SOURCE_TYPE_NA ("NA" = "not applicable") for the -            // source argument - -            static const audio_source_t SOURCE_TYPE_NA = AUDIO_SOURCE_DEFAULT; - -            SessionRoute(audio_session_t session, -                         audio_stream_type_t streamType, -                         audio_source_t source, -                         sp<DeviceDescriptor> deviceDescriptor, -                         uid_t uid) -               : mUid(uid), -                 mSession(session), -                 mDeviceDescriptor(deviceDescriptor), -                 mRefCount(0), -                 mActivityCount(0), -                 mChanged(false), -                 mStreamType(streamType), -                 mSource(source) -                  {} - -            void log(const char* prefix); - -            bool isActive() { -                return (mDeviceDescriptor != 0) && (mChanged || (mActivityCount > 0)); -            } - -            uid_t                       mUid; -            audio_session_t             mSession; -            sp<DeviceDescriptor>        mDeviceDescriptor; - -            // "reference" counting -            int                         mRefCount;      // +/- on references -            int                         mActivityCount; // +/- on start/stop -            bool                        mChanged; -            // for outputs -            const audio_stream_type_t   mStreamType; -            // for inputs -            const audio_source_t        mSource; -        }; - -        class SessionRouteMap: public KeyedVector<audio_session_t, sp<SessionRoute>> { -        public: -            // These constants identify the SessionRoutMap as holding EITHER input routes, -            // or output routes.  An error will occur if an attempt is made to add a SessionRoute -            // object with mStreamType == STREAM_TYPE_NA (i.e. an input SessionRoute) to a -            // SessionRoutMap that is marked for output (i.e. mMapType == SESSION_ROUTE_MAP_OUTPUT) -            // and similarly  for output SessionRoutes and Input SessionRouteMaps. -            typedef enum { -              MAPTYPE_INPUT = 0, -              MAPTYPE_OUTPUT = 1 -            } session_route_map_type_t; - -            SessionRouteMap(session_route_map_type_t mapType) : -                mMapType(mapType) { -            } - -            bool hasRoute(audio_session_t session); - -            void removeRoute(audio_session_t session); - -            int incRouteActivity(audio_session_t session); -            int decRouteActivity(audio_session_t session); -            bool hasRouteChanged(audio_session_t session); // also clears the changed flag -            void log(const char* caption); - -            // Specify an Output(Sink) route by passing SessionRoute::SOURCE_TYPE_NA in the -            // source argument. -            // Specify an Input(Source) rout by passing SessionRoute::AUDIO_STREAM_DEFAULT -            // in the streamType argument. -            void addRoute(audio_session_t session, -                          audio_stream_type_t streamType, -                          audio_source_t source, -                          sp<DeviceDescriptor> deviceDescriptor, -                          uid_t uid); - -        private: -            // Used to mark a SessionRoute as for either inputs (mMapType == kSessionRouteMap_Input) -            // or outputs (mMapType == kSessionRouteMap_Output) -            const session_route_map_type_t mMapType; -        }; -          // From AudioPolicyManagerObserver          virtual const AudioPatchCollection &getAudioPatches() const          {  | 
