audio policy: load audio hw modules.

Audio HW modules are now loaded upon request from audio policy manager
according to the configuration in audio_policy.conf.
Removed hard coded HW module loading by AudioFlinger at init time.
Added methods to IAudioFlinger and AudioPolicyInterface
to control the loading of audio HW modules.
Added methods to open an output or input stream on a specific hw module.

Change-Id: I361b294ece1a9b56b2fb39cc64259dbb73b804f4
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e926292..9e6a6df 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -149,13 +149,6 @@
     return rc;
 }
 
-static const char * const audio_interfaces[] = {
-    AUDIO_HARDWARE_MODULE_ID_PRIMARY,
-    AUDIO_HARDWARE_MODULE_ID_A2DP,
-    AUDIO_HARDWARE_MODULE_ID_USB,
-};
-#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
-
 // ----------------------------------------------------------------------------
 
 AudioFlinger::AudioFlinger()
@@ -191,87 +184,9 @@
         }
     }
 
-    for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
-        const hw_module_t *mod;
-        audio_hw_device_t *dev;
-
-        rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
-        if (rc)
-            continue;
-
-        ALOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
-            mod->name, mod->id);
-        mAudioHwDevs.push(dev);
-
-        if (mPrimaryHardwareDev == NULL) {
-            mPrimaryHardwareDev = dev;
-            ALOGI("Using '%s' (%s.%s) as the primary audio interface",
-                mod->name, mod->id, audio_interfaces[i]);
-        }
-    }
-
-    if (mPrimaryHardwareDev == NULL) {
-        ALOGE("Primary audio interface not found");
-        // proceed, all later accesses to mPrimaryHardwareDev verify it's safe with initCheck()
-    }
-
-    // Currently (mPrimaryHardwareDev == NULL) == (mAudioHwDevs.size() == 0), but the way the
-    // primary HW dev is selected can change so these conditions might not always be equivalent.
-    // When that happens, re-visit all the code that assumes this.
-
-    AutoMutex lock(mHardwareLock);
-
-    // Determine the level of master volume support the primary audio HAL has,
-    // and set the initial master volume at the same time.
-    float initialVolume = 1.0;
-    mMasterVolumeSupportLvl = MVS_NONE;
-    if (0 == mPrimaryHardwareDev->init_check(mPrimaryHardwareDev)) {
-        audio_hw_device_t *dev = mPrimaryHardwareDev;
-
-        mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
-        if ((NULL != dev->get_master_volume) &&
-            (NO_ERROR == dev->get_master_volume(dev, &initialVolume))) {
-            mMasterVolumeSupportLvl = MVS_FULL;
-        } else {
-            mMasterVolumeSupportLvl = MVS_SETONLY;
-            initialVolume = 1.0;
-        }
-
-        mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
-        if ((NULL == dev->set_master_volume) ||
-            (NO_ERROR != dev->set_master_volume(dev, initialVolume))) {
-            mMasterVolumeSupportLvl = MVS_NONE;
-        }
-        mHardwareStatus = AUDIO_HW_IDLE;
-    }
-
-    // Set the mode for each audio HAL, and try to set the initial volume (if
-    // supported) for all of the non-primary audio HALs.
-    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
-        audio_hw_device_t *dev = mAudioHwDevs[i];
-
-        mHardwareStatus = AUDIO_HW_INIT;
-        rc = dev->init_check(dev);
-        mHardwareStatus = AUDIO_HW_IDLE;
-        if (rc == 0) {
-            mMode = AUDIO_MODE_NORMAL;  // assigned multiple times with same value
-            mHardwareStatus = AUDIO_HW_SET_MODE;
-            dev->set_mode(dev, mMode);
-
-            if ((dev != mPrimaryHardwareDev) &&
-                (NULL != dev->set_master_volume)) {
-                mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
-                dev->set_master_volume(dev, initialVolume);
-            }
-
-            mHardwareStatus = AUDIO_HW_IDLE;
-        }
-    }
-
-    mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl)
-                    ? initialVolume
-                    : 1.0;
-    mMasterVolume   = initialVolume;
+    mMode = AUDIO_MODE_NORMAL;
+    mMasterVolumeSW = 1.0;
+    mMasterVolume   = 1.0;
     mHardwareStatus = AUDIO_HW_IDLE;
 }
 
@@ -289,18 +204,41 @@
 
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
         // no mHardwareLock needed, as there are no other references to this
-        audio_hw_device_close(mAudioHwDevs[i]);
+        audio_hw_device_close(mAudioHwDevs.valueAt(i)->hwDevice());
+        delete mAudioHwDevs.valueAt(i);
     }
 }
 
-audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
+static const char * const audio_interfaces[] = {
+    AUDIO_HARDWARE_MODULE_ID_PRIMARY,
+    AUDIO_HARDWARE_MODULE_ID_A2DP,
+    AUDIO_HARDWARE_MODULE_ID_USB,
+};
+#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
+
+audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(audio_module_handle_t module, uint32_t devices)
 {
-    /* first matching HW device is returned */
+    // if module is 0, the request comes from an old policy manager and we should load
+    // well known modules
+    if (module == 0) {
+        ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
+        for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
+            loadHwModule_l(audio_interfaces[i]);
+        }
+    } else {
+        // check a match for the requested module handle
+        AudioHwDevice *audioHwdevice = mAudioHwDevs.valueFor(module);
+        if (audioHwdevice != NULL) {
+            return audioHwdevice->hwDevice();
+        }
+    }
+    // then try to find a module supporting the requested device.
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
-        audio_hw_device_t *dev = mAudioHwDevs[i];
+        audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
         if ((dev->get_supported_devices(dev) & devices) == devices)
             return dev;
     }
+
     return NULL;
 }
 
@@ -411,7 +349,7 @@
 
         // dump all hardware devs
         for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
-            audio_hw_device_t *dev = mAudioHwDevs[i];
+            audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
             dev->dump(dev, fd);
         }
         if (locked) mLock.unlock();
@@ -610,11 +548,13 @@
 
     float swmv = value;
 
+    Mutex::Autolock _l(mLock);
+
     // when hw supports master volume, don't scale in sw mixer
     if (MVS_NONE != mMasterVolumeSupportLvl) {
         for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
             AutoMutex lock(mHardwareLock);
-            audio_hw_device_t *dev = mAudioHwDevs[i];
+            audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
 
             mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
             if (NULL != dev->set_master_volume) {
@@ -626,7 +566,6 @@
         swmv = 1.0;
     }
 
-    Mutex::Autolock _l(mLock);
     mMasterVolume   = value;
     mMasterVolumeSW = swmv;
     for (size_t i = 0; i < mPlaybackThreads.size(); i++)
@@ -853,22 +792,22 @@
 
     // ioHandle == 0 means the parameters are global to the audio hardware interface
     if (ioHandle == 0) {
+        Mutex::Autolock _l(mLock);
         status_t final_result = NO_ERROR;
         {
-        AutoMutex lock(mHardwareLock);
-        mHardwareStatus = AUDIO_HW_SET_PARAMETER;
-        for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
-            audio_hw_device_t *dev = mAudioHwDevs[i];
-            status_t result = dev->set_parameters(dev, keyValuePairs.string());
-            final_result = result ?: final_result;
-        }
-        mHardwareStatus = AUDIO_HW_IDLE;
+            AutoMutex lock(mHardwareLock);
+            mHardwareStatus = AUDIO_HW_SET_PARAMETER;
+            for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+                audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
+                status_t result = dev->set_parameters(dev, keyValuePairs.string());
+                final_result = result ?: final_result;
+            }
+            mHardwareStatus = AUDIO_HW_IDLE;
         }
         // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
         AudioParameter param = AudioParameter(keyValuePairs);
         String8 value;
         if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
-            Mutex::Autolock _l(mLock);
             bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
             if (mBtNrecIsOff != btNrecIsOff) {
                 for (size_t i = 0; i < mRecordThreads.size(); i++) {
@@ -923,6 +862,8 @@
 //    ALOGV("getParameters() io %d, keys %s, tid %d, calling pid %d",
 //            ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
 
+    Mutex::Autolock _l(mLock);
+
     if (ioHandle == 0) {
         String8 out_s8;
 
@@ -931,7 +872,7 @@
             {
             AutoMutex lock(mHardwareLock);
             mHardwareStatus = AUDIO_HW_GET_PARAMETER;
-            audio_hw_device_t *dev = mAudioHwDevs[i];
+            audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
             s = dev->get_parameters(dev, keys.string());
             mHardwareStatus = AUDIO_HW_IDLE;
             }
@@ -941,8 +882,6 @@
         return out_s8;
     }
 
-    Mutex::Autolock _l(mLock);
-
     PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
     if (playbackThread != NULL) {
         return playbackThread->getParameters(keys);
@@ -5663,28 +5602,84 @@
 
 // ----------------------------------------------------------------------------
 
-audio_io_handle_t AudioFlinger::openOutput(uint32_t *pDevices,
-                                uint32_t *pSamplingRate,
-                                audio_format_t *pFormat,
-                                uint32_t *pChannels,
-                                uint32_t *pLatencyMs,
-                                audio_policy_output_flags_t flags)
+audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
+{
+    if (!settingsAllowed()) {
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+    return loadHwModule_l(name);
+}
+
+// loadHwModule_l() must be called with AudioFlinger::mLock held
+audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
+{
+    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+        if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
+            ALOGW("loadHwModule() module %s already loaded", name);
+            return mAudioHwDevs.keyAt(i);
+        }
+    }
+
+    const hw_module_t *mod;
+    audio_hw_device_t *dev;
+
+    int rc = load_audio_interface(name, &mod, &dev);
+    if (rc) {
+        ALOGI("loadHwModule() error %d loading module %s ", rc, name);
+        return 0;
+    }
+
+    mHardwareStatus = AUDIO_HW_INIT;
+    rc = dev->init_check(dev);
+    mHardwareStatus = AUDIO_HW_IDLE;
+    if (rc) {
+        ALOGI("loadHwModule() init check error %d for module %s ", rc, name);
+        return 0;
+    }
+
+    if ((mMasterVolumeSupportLvl != MVS_NONE) &&
+        (NULL != dev->set_master_volume)) {
+        AutoMutex lock(mHardwareLock);
+        mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+        dev->set_master_volume(dev, mMasterVolume);
+        mHardwareStatus = AUDIO_HW_IDLE;
+    }
+
+    audio_module_handle_t handle = nextUniqueId();
+    mAudioHwDevs.add(handle, new AudioHwDevice(name, dev));
+
+    ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d",
+          name, mod->name, mod->id, handle);
+
+    return handle;
+
+}
+
+audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
+                                           audio_devices_t *pDevices,
+                                           uint32_t *pSamplingRate,
+                                           audio_format_t *pFormat,
+                                           audio_channel_mask_t *pChannelMask,
+                                           uint32_t *pLatencyMs,
+                                           audio_policy_output_flags_t flags)
 {
     status_t status;
     PlaybackThread *thread = NULL;
     uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
     audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
-    uint32_t channels = pChannels ? *pChannels : 0;
+    audio_channel_mask_t channelMask = pChannelMask ? *pChannelMask : 0;
     uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
     audio_stream_out_t *outStream;
     audio_hw_device_t *outHwDev;
 
-    ALOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
-            pDevices ? *pDevices : 0,
-            samplingRate,
-            format,
-            channels,
-            flags);
+    ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
+              module,
+              pDevices ? *pDevices : 0,
+              samplingRate,
+              format,
+              channelMask,
+              flags);
 
     if (pDevices == NULL || *pDevices == 0) {
         return 0;
@@ -5692,19 +5687,19 @@
 
     Mutex::Autolock _l(mLock);
 
-    outHwDev = findSuitableHwDev_l(*pDevices);
+    outHwDev = findSuitableHwDev_l(module, *pDevices);
     if (outHwDev == NULL)
         return 0;
 
     mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
     status = outHwDev->open_output_stream(outHwDev, *pDevices, &format,
-                                          &channels, &samplingRate, &outStream);
+                                          &channelMask, &samplingRate, &outStream);
     mHardwareStatus = AUDIO_HW_IDLE;
     ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
             outStream,
             samplingRate,
             format,
-            channels,
+            channelMask,
             status);
 
     if (outStream != NULL) {
@@ -5713,7 +5708,7 @@
 
         if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
             (format != AUDIO_FORMAT_PCM_16_BIT) ||
-            (channels != AUDIO_CHANNEL_OUT_STEREO)) {
+            (channelMask != AUDIO_CHANNEL_OUT_STEREO)) {
             thread = new DirectOutputThread(this, output, id, *pDevices);
             ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
         } else {
@@ -5724,11 +5719,55 @@
 
         if (pSamplingRate != NULL) *pSamplingRate = samplingRate;
         if (pFormat != NULL) *pFormat = format;
-        if (pChannels != NULL) *pChannels = channels;
+        if (pChannelMask != NULL) *pChannelMask = channelMask;
         if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
 
         // notify client processes of the new output creation
         thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
+
+        // the first primary output opened designates the primary hw device
+        if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_POLICY_OUTPUT_FLAG_PRIMARY)) {
+            ALOGI("Using module %d has the primary audio interface", module);
+            mPrimaryHardwareDev = outHwDev;
+
+            AutoMutex lock(mHardwareLock);
+            mHardwareStatus = AUDIO_HW_SET_MODE;
+            outHwDev->set_mode(outHwDev, mMode);
+
+            // Determine the level of master volume support the primary audio HAL has,
+            // and set the initial master volume at the same time.
+            float initialVolume = 1.0;
+            mMasterVolumeSupportLvl = MVS_NONE;
+
+            mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
+            if ((NULL != outHwDev->get_master_volume) &&
+                (NO_ERROR == outHwDev->get_master_volume(outHwDev, &initialVolume))) {
+                mMasterVolumeSupportLvl = MVS_FULL;
+            } else {
+                mMasterVolumeSupportLvl = MVS_SETONLY;
+                initialVolume = 1.0;
+            }
+
+            mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+            if ((NULL == outHwDev->set_master_volume) ||
+                (NO_ERROR != outHwDev->set_master_volume(outHwDev, initialVolume))) {
+                mMasterVolumeSupportLvl = MVS_NONE;
+            }
+            // now that we have a primary device, initialize master volume on other devices
+            for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+                audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
+
+                if ((dev != mPrimaryHardwareDev) &&
+                    (NULL != dev->set_master_volume)) {
+                    dev->set_master_volume(dev, initialVolume);
+                }
+            }
+            mHardwareStatus = AUDIO_HW_IDLE;
+            mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl)
+                                    ? initialVolume
+                                    : 1.0;
+            mMasterVolume   = initialVolume;
+        }
         return id;
     }
 
@@ -5826,20 +5865,20 @@
     return NO_ERROR;
 }
 
-audio_io_handle_t AudioFlinger::openInput(uint32_t *pDevices,
-                                uint32_t *pSamplingRate,
-                                audio_format_t *pFormat,
-                                uint32_t *pChannels,
-                                audio_in_acoustics_t acoustics)
+audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
+                                          audio_devices_t *pDevices,
+                                          uint32_t *pSamplingRate,
+                                          audio_format_t *pFormat,
+                                          uint32_t *pChannelMask)
 {
     status_t status;
     RecordThread *thread = NULL;
     uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
     audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
-    uint32_t channels = pChannels ? *pChannels : 0;
+    audio_channel_mask_t channelMask = pChannelMask ? *pChannelMask : 0;
     uint32_t reqSamplingRate = samplingRate;
     audio_format_t reqFormat = format;
-    uint32_t reqChannels = channels;
+    audio_channel_mask_t reqChannels = channelMask;
     audio_stream_in_t *inStream;
     audio_hw_device_t *inHwDev;
 
@@ -5849,20 +5888,19 @@
 
     Mutex::Autolock _l(mLock);
 
-    inHwDev = findSuitableHwDev_l(*pDevices);
+    inHwDev = findSuitableHwDev_l(module, *pDevices);
     if (inHwDev == NULL)
         return 0;
 
     status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
-                                        &channels, &samplingRate,
-                                        acoustics,
+                                        &channelMask, &samplingRate,
+                                        (audio_in_acoustics_t)0,
                                         &inStream);
-    ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
+    ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, status %d",
             inStream,
             samplingRate,
             format,
-            channels,
-            acoustics,
+            channelMask,
             status);
 
     // If the input could not be opened with the requested parameters and we can handle the conversion internally,
@@ -5871,11 +5909,11 @@
     if (inStream == NULL && status == BAD_VALUE &&
         reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
         (samplingRate <= 2 * reqSamplingRate) &&
-        (popcount(channels) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) {
+        (popcount(channelMask) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) {
         ALOGV("openInput() reopening with proposed sampling rate and channels");
         status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
-                                            &channels, &samplingRate,
-                                            acoustics,
+                                            &channelMask, &samplingRate,
+                                            (audio_in_acoustics_t)0,
                                             &inStream);
     }
 
@@ -5897,7 +5935,7 @@
         ALOGV("openInput() created record thread: ID %d thread %p", id, thread);
         if (pSamplingRate != NULL) *pSamplingRate = reqSamplingRate;
         if (pFormat != NULL) *pFormat = format;
-        if (pChannels != NULL) *pChannels = reqChannels;
+        if (pChannelMask != NULL) *pChannelMask = reqChannels;
 
         input->stream->common.standby(&input->stream->common);