Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "APM::AudioSession"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <AudioPolicyInterface.h>
     21 #include "policy.h"
     22 #include "AudioSession.h"
     23 #include "AudioGain.h"
     24 #include "TypeConverter.h"
     25 
     26 #include <log/log.h>
     27 #include <utils/String8.h>
     28 
     29 namespace android {
     30 
     31 AudioSession::AudioSession(audio_session_t session,
     32                            audio_source_t inputSource,
     33                            audio_format_t format,
     34                            uint32_t sampleRate,
     35                            audio_channel_mask_t channelMask,
     36                            audio_input_flags_t flags,
     37                            uid_t uid,
     38                            bool isSoundTrigger,
     39                            AudioMix* policyMix,
     40                            AudioPolicyClientInterface *clientInterface) :
     41     mSession(session), mInputSource(inputSource),
     42     mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
     43     mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger),
     44     mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface),
     45     mInfoProvider(NULL)
     46 {
     47 }
     48 
     49 uint32_t AudioSession::changeOpenCount(int delta)
     50 {
     51     if ((delta + (int)mOpenCount) < 0) {
     52         ALOGW("%s invalid delta %d, open count %d",
     53               __FUNCTION__, delta, mOpenCount);
     54         mOpenCount = (uint32_t)(-delta);
     55     }
     56     mOpenCount += delta;
     57     ALOGV("%s open count %d", __FUNCTION__, mOpenCount);
     58     return mOpenCount;
     59 }
     60 
     61 uint32_t AudioSession::changeActiveCount(int delta)
     62 {
     63     const uint32_t oldActiveCount = mActiveCount;
     64     if ((delta + (int)mActiveCount) < 0) {
     65         ALOGW("%s invalid delta %d, active count %d",
     66               __FUNCTION__, delta, mActiveCount);
     67         mActiveCount = (uint32_t)(-delta);
     68     }
     69     mActiveCount += delta;
     70     ALOGV("%s active count %d", __FUNCTION__, mActiveCount);
     71     int event = RECORD_CONFIG_EVENT_NONE;
     72 
     73     if ((oldActiveCount == 0) && (mActiveCount > 0)) {
     74         event = RECORD_CONFIG_EVENT_START;
     75     } else if ((oldActiveCount > 0) && (mActiveCount == 0)) {
     76         event = RECORD_CONFIG_EVENT_STOP;
     77     }
     78 
     79     if (event != RECORD_CONFIG_EVENT_NONE) {
     80         // Dynamic policy callback:
     81         // if input maps to a dynamic policy with an activity listener, notify of state change
     82         if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
     83         {
     84             mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
     85                     (event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
     86         }
     87 
     88         // Recording configuration callback:
     89         const AudioSessionInfoProvider* provider = mInfoProvider;
     90         const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
     91                 AUDIO_CONFIG_BASE_INITIALIZER;
     92         const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
     93                 AUDIO_PATCH_HANDLE_NONE;
     94         if (patchHandle != AUDIO_PATCH_HANDLE_NONE) {
     95             mClientInterface->onRecordingConfigurationUpdate(event, mSession, mInputSource,
     96                     &mConfig, &deviceConfig, patchHandle);
     97         }
     98     }
     99 
    100     return mActiveCount;
    101 }
    102 
    103 bool AudioSession::matches(const sp<AudioSession> &other) const
    104 {
    105     if (other->session() == mSession &&
    106         other->inputSource() == mInputSource &&
    107         other->format() == mConfig.format &&
    108         other->sampleRate() == mConfig.sample_rate &&
    109         other->channelMask() == mConfig.channel_mask &&
    110         other->flags() == mFlags &&
    111         other->uid() == mUid) {
    112         return true;
    113     }
    114     return false;
    115 }
    116 
    117 void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider)
    118 {
    119     mInfoProvider = provider;
    120 }
    121 
    122 void AudioSession::onSessionInfoUpdate() const
    123 {
    124     if (mActiveCount > 0) {
    125         // resend the callback after requerying the informations from the info provider
    126         const AudioSessionInfoProvider* provider = mInfoProvider;
    127         const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
    128                 AUDIO_CONFIG_BASE_INITIALIZER;
    129         const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
    130                 AUDIO_PATCH_HANDLE_NONE;
    131         if (patchHandle != AUDIO_PATCH_HANDLE_NONE) {
    132             mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
    133                     mSession, mInputSource,
    134                     &mConfig, &deviceConfig, patchHandle);
    135         }
    136     }
    137 }
    138 
    139 status_t AudioSession::dump(int fd, int spaces, int index) const
    140 {
    141     const size_t SIZE = 256;
    142     char buffer[SIZE];
    143     String8 result;
    144 
    145     snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1);
    146     result.append(buffer);
    147     snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mSession);
    148     result.append(buffer);
    149     snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
    150     result.append(buffer);
    151     snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mInputSource);
    152     result.append(buffer);
    153     snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mConfig.format);
    154     result.append(buffer);
    155     snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mConfig.sample_rate);
    156     result.append(buffer);
    157     snprintf(buffer, SIZE, "%*s- channel mask: %08x\n",
    158              spaces, "", mConfig.channel_mask);
    159     result.append(buffer);
    160     snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n",
    161              spaces, "", mIsSoundTrigger ? "true" : "false");
    162     result.append(buffer);
    163     snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount);
    164     result.append(buffer);
    165     snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount);
    166     result.append(buffer);
    167 
    168     write(fd, result.string(), result.size());
    169     return NO_ERROR;
    170 }
    171 
    172 status_t AudioSessionCollection::addSession(audio_session_t session,
    173                                          const sp<AudioSession>& audioSession,
    174                                          AudioSessionInfoProvider *provider)
    175 {
    176     ssize_t index = indexOfKey(session);
    177 
    178     if (index >= 0) {
    179         ALOGW("addSession() session %d already in", session);
    180         return ALREADY_EXISTS;
    181     }
    182     audioSession->setInfoProvider(provider);
    183     add(session, audioSession);
    184     ALOGV("addSession() session %d  client %d source %d",
    185             session, audioSession->uid(), audioSession->inputSource());
    186     return NO_ERROR;
    187 }
    188 
    189 status_t AudioSessionCollection::removeSession(audio_session_t session)
    190 {
    191     ssize_t index = indexOfKey(session);
    192 
    193     if (index < 0) {
    194         ALOGW("removeSession() session %d not in", session);
    195         return ALREADY_EXISTS;
    196     }
    197     ALOGV("removeSession() session %d", session);
    198     valueAt(index)->setInfoProvider(NULL);
    199     removeItemsAt(index);
    200     return NO_ERROR;
    201 }
    202 
    203 uint32_t AudioSessionCollection::getOpenCount() const
    204 {
    205     uint32_t openCount = 0;
    206     for (size_t i = 0; i < size(); i++) {
    207         openCount += valueAt(i)->openCount();
    208     }
    209     return openCount;
    210 }
    211 
    212 AudioSessionCollection AudioSessionCollection::getActiveSessions() const
    213 {
    214     AudioSessionCollection activeSessions;
    215     for (size_t i = 0; i < size(); i++) {
    216         if (valueAt(i)->activeCount() != 0) {
    217             activeSessions.add(valueAt(i)->session(), valueAt(i));
    218         }
    219     }
    220     return activeSessions;
    221 }
    222 
    223 size_t AudioSessionCollection::getActiveSessionCount() const
    224 {
    225     size_t activeCount = 0;
    226     for (size_t i = 0; i < size(); i++) {
    227         if (valueAt(i)->activeCount() != 0) {
    228             activeCount++;
    229         }
    230     }
    231     return activeCount;
    232 }
    233 
    234 bool AudioSessionCollection::hasActiveSession() const
    235 {
    236     return getActiveSessionCount() != 0;
    237 }
    238 
    239 bool AudioSessionCollection::isSourceActive(audio_source_t source) const
    240 {
    241     for (size_t i = 0; i < size(); i++) {
    242         const sp<AudioSession>  audioSession = valueAt(i);
    243         // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
    244         // corresponds to an active capture triggered by a hardware hotword recognition
    245         if (audioSession->activeCount() > 0 &&
    246                 ((audioSession->inputSource() == source) ||
    247                 ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
    248                  (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) &&
    249                  audioSession->isSoundTrigger()))) {
    250             return true;
    251         }
    252     }
    253     return false;
    254 }
    255 
    256 audio_source_t AudioSessionCollection::getHighestPrioritySource(bool activeOnly) const
    257 {
    258     audio_source_t source = AUDIO_SOURCE_DEFAULT;
    259     int32_t priority = -1;
    260 
    261     for (size_t i = 0; i < size(); i++) {
    262         const sp<AudioSession>  audioSession = valueAt(i);
    263         if (activeOnly && audioSession->activeCount() == 0) {
    264             continue;
    265         }
    266         int32_t curPriority = source_priority(audioSession->inputSource());
    267         if (curPriority > priority) {
    268             priority = curPriority;
    269             source = audioSession->inputSource();
    270         }
    271     }
    272     return source;
    273 }
    274 
    275 void AudioSessionCollection::onSessionInfoUpdate() const
    276 {
    277     for (size_t i = 0; i < size(); i++) {
    278         valueAt(i)->onSessionInfoUpdate();
    279     }
    280 }
    281 
    282 status_t AudioSessionCollection::dump(int fd, int spaces) const
    283 {
    284     const size_t SIZE = 256;
    285     char buffer[SIZE];
    286     snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, "");
    287     write(fd, buffer, strlen(buffer));
    288     for (size_t i = 0; i < size(); i++) {
    289         valueAt(i)->dump(fd, spaces + 2, i);
    290     }
    291     return NO_ERROR;
    292 }
    293 
    294 }; // namespace android
    295