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 "AudioSession.h"
     22 #include "AudioGain.h"
     23 #include "TypeConverter.h"
     24 #include <cutils/log.h>
     25 #include <utils/String8.h>
     26 
     27 namespace android {
     28 
     29 AudioSession::AudioSession(audio_session_t session,
     30                            audio_source_t inputSource,
     31                            audio_format_t format,
     32                            uint32_t sampleRate,
     33                            audio_channel_mask_t channelMask,
     34                            audio_input_flags_t flags,
     35                            uid_t uid,
     36                            bool isSoundTrigger,
     37                            AudioMix* policyMix,
     38                            AudioPolicyClientInterface *clientInterface) :
     39     mSession(session), mInputSource(inputSource),
     40     mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
     41     mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger),
     42     mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface),
     43     mInfoProvider(NULL)
     44 {
     45 }
     46 
     47 uint32_t AudioSession::changeOpenCount(int delta)
     48 {
     49     if ((delta + (int)mOpenCount) < 0) {
     50         ALOGW("%s invalid delta %d, open count %d",
     51               __FUNCTION__, delta, mOpenCount);
     52         mOpenCount = (uint32_t)(-delta);
     53     }
     54     mOpenCount += delta;
     55     ALOGV("%s open count %d", __FUNCTION__, mOpenCount);
     56     return mOpenCount;
     57 }
     58 
     59 uint32_t AudioSession::changeActiveCount(int delta)
     60 {
     61     const uint32_t oldActiveCount = mActiveCount;
     62     if ((delta + (int)mActiveCount) < 0) {
     63         ALOGW("%s invalid delta %d, active count %d",
     64               __FUNCTION__, delta, mActiveCount);
     65         mActiveCount = (uint32_t)(-delta);
     66     }
     67     mActiveCount += delta;
     68     ALOGV("%s active count %d", __FUNCTION__, mActiveCount);
     69     int event = RECORD_CONFIG_EVENT_NONE;
     70 
     71     if ((oldActiveCount == 0) && (mActiveCount > 0)) {
     72         event = RECORD_CONFIG_EVENT_START;
     73     } else if ((oldActiveCount > 0) && (mActiveCount == 0)) {
     74         event = RECORD_CONFIG_EVENT_STOP;
     75     }
     76 
     77     if (event != RECORD_CONFIG_EVENT_NONE) {
     78         // Dynamic policy callback:
     79         // if input maps to a dynamic policy with an activity listener, notify of state change
     80         if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
     81         {
     82             mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
     83                     (event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
     84         }
     85 
     86         // Recording configuration callback:
     87         const AudioSessionInfoProvider* provider = mInfoProvider;
     88         const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
     89                 AUDIO_CONFIG_BASE_INITIALIZER;
     90         const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
     91                 AUDIO_PATCH_HANDLE_NONE;
     92         mClientInterface->onRecordingConfigurationUpdate(event, mSession, mInputSource,
     93                 &mConfig, &deviceConfig, patchHandle);
     94     }
     95 
     96     return mActiveCount;
     97 }
     98 
     99 bool AudioSession::matches(const sp<AudioSession> &other) const
    100 {
    101     if (other->session() == mSession &&
    102         other->inputSource() == mInputSource &&
    103         other->format() == mConfig.format &&
    104         other->sampleRate() == mConfig.sample_rate &&
    105         other->channelMask() == mConfig.channel_mask &&
    106         other->flags() == mFlags &&
    107         other->uid() == mUid) {
    108         return true;
    109     }
    110     return false;
    111 }
    112 
    113 void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider)
    114 {
    115     mInfoProvider = provider;
    116 }
    117 
    118 void AudioSession::onSessionInfoUpdate() const
    119 {
    120     if (mActiveCount > 0) {
    121         // resend the callback after requerying the informations from the info provider
    122         const AudioSessionInfoProvider* provider = mInfoProvider;
    123         const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
    124                 AUDIO_CONFIG_BASE_INITIALIZER;
    125         const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
    126                 AUDIO_PATCH_HANDLE_NONE;
    127         mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
    128                 mSession, mInputSource,
    129                 &mConfig, &deviceConfig, patchHandle);
    130     }
    131 }
    132 
    133 status_t AudioSession::dump(int fd, int spaces, int index) const
    134 {
    135     const size_t SIZE = 256;
    136     char buffer[SIZE];
    137     String8 result;
    138 
    139     snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1);
    140     result.append(buffer);
    141     snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mSession);
    142     result.append(buffer);
    143     snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
    144     result.append(buffer);
    145     snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mInputSource);
    146     result.append(buffer);
    147     snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mConfig.format);
    148     result.append(buffer);
    149     snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mConfig.sample_rate);
    150     result.append(buffer);
    151     snprintf(buffer, SIZE, "%*s- channel mask: %08x\n",
    152              spaces, "", mConfig.channel_mask);
    153     result.append(buffer);
    154     snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n",
    155              spaces, "", mIsSoundTrigger ? "true" : "false");
    156     result.append(buffer);
    157     snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount);
    158     result.append(buffer);
    159     snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount);
    160     result.append(buffer);
    161 
    162     write(fd, result.string(), result.size());
    163     return NO_ERROR;
    164 }
    165 
    166 status_t AudioSessionCollection::addSession(audio_session_t session,
    167                                          const sp<AudioSession>& audioSession,
    168                                          AudioSessionInfoProvider *provider)
    169 {
    170     ssize_t index = indexOfKey(session);
    171 
    172     if (index >= 0) {
    173         ALOGW("addSession() session %d already in", session);
    174         return ALREADY_EXISTS;
    175     }
    176     audioSession->setInfoProvider(provider);
    177     add(session, audioSession);
    178     ALOGV("addSession() session %d  client %d source %d",
    179             session, audioSession->uid(), audioSession->inputSource());
    180     return NO_ERROR;
    181 }
    182 
    183 status_t AudioSessionCollection::removeSession(audio_session_t session)
    184 {
    185     ssize_t index = indexOfKey(session);
    186 
    187     if (index < 0) {
    188         ALOGW("removeSession() session %d not in", session);
    189         return ALREADY_EXISTS;
    190     }
    191     ALOGV("removeSession() session %d", session);
    192     valueAt(index)->setInfoProvider(NULL);
    193     removeItemsAt(index);
    194     return NO_ERROR;
    195 }
    196 
    197 uint32_t AudioSessionCollection::getOpenCount() const
    198 {
    199     uint32_t openCount = 0;
    200     for (size_t i = 0; i < size(); i++) {
    201         openCount += valueAt(i)->openCount();
    202     }
    203     return openCount;
    204 }
    205 
    206 AudioSessionCollection AudioSessionCollection::getActiveSessions() const
    207 {
    208     AudioSessionCollection activeSessions;
    209     for (size_t i = 0; i < size(); i++) {
    210         if (valueAt(i)->activeCount() != 0) {
    211             activeSessions.add(valueAt(i)->session(), valueAt(i));
    212         }
    213     }
    214     return activeSessions;
    215 }
    216 
    217 bool AudioSessionCollection::hasActiveSession() const
    218 {
    219     return getActiveSessions().size() != 0;
    220 }
    221 
    222 bool AudioSessionCollection::isSourceActive(audio_source_t source) const
    223 {
    224     for (size_t i = 0; i < size(); i++) {
    225         const sp<AudioSession>  audioSession = valueAt(i);
    226         // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
    227         // corresponds to an active capture triggered by a hardware hotword recognition
    228         if (audioSession->activeCount() > 0 &&
    229                 ((audioSession->inputSource() == source) ||
    230                 ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
    231                  (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) &&
    232                  audioSession->isSoundTrigger()))) {
    233             return true;
    234         }
    235     }
    236     return false;
    237 }
    238 
    239 void AudioSessionCollection::onSessionInfoUpdate() const
    240 {
    241     for (size_t i = 0; i < size(); i++) {
    242         valueAt(i)->onSessionInfoUpdate();
    243     }
    244 }
    245 
    246 
    247 status_t AudioSessionCollection::dump(int fd, int spaces) const
    248 {
    249     const size_t SIZE = 256;
    250     char buffer[SIZE];
    251     snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, "");
    252     write(fd, buffer, strlen(buffer));
    253     for (size_t i = 0; i < size(); i++) {
    254         valueAt(i)->dump(fd, spaces + 2, i);
    255     }
    256     return NO_ERROR;
    257 }
    258 
    259 }; // namespace android
    260