Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a94d69d authored by Eric Laurent's avatar Eric Laurent
Browse files

audio policy: implement routing control

Add implementation of audio routing control via AudioSystem APIs.

The following APIs are implemented:
- listAudioPorts(): return a list of devices and output/input mixers ports
that can be used as sources or sinks for audio patches.
- createAudioPatch()/releaseAudioPatch(): create/release a connection patch between
two audio ports (e.g. to connect input from an HDMI device to a speaker output device).
Only one client application can own a patch from a given source.
When an audio port (device or mix) is part of an application created patch, its routing cannot
not be changed by a policy decision.
- listAudioPatches(): return a list of existing patches.

Each audio port addition/removal and each audio patch creation/release increments a generation count.
This generation count is used to ensure consistency betwen calls to
listAudioPorts() and listAudioPatches().

Bug: 14815883.

Change-Id: I022b638c2f5f0bb41543c7cfca7488fb45cfdd80
parent 32f93b7b
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -179,11 +179,11 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa
                ALOGW("createAudioPatch() bad src hw module %d", src_module);
                return BAD_VALUE;
            }
            AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index);
            for (unsigned int i = 0; i < patch->num_sinks; i++) {
                // limit to connections between devices and output streams
                if (patch->sinks[i].type != AUDIO_PORT_TYPE_MIX) {
                    ALOGW("createAudioPatch() invalid sink type %d for device source",
                          patch->sinks[i].type);
                // reject connection to different sink types
                if (patch->sinks[i].type != patch->sinks[0].type) {
                    ALOGW("createAudioPatch() different sink types in same patch not supported");
                    return BAD_VALUE;
                }
                // limit to connections between sinks and sources on same HW module
@@ -192,9 +192,16 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa
                            "sink on module %d", src_module, patch->sinks[i].ext.mix.hw_module);
                    return BAD_VALUE;
                }

                // limit to connections between devices and output streams for HAL before 3.0
                if ((audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) &&
                        (patch->sinks[i].type != AUDIO_PORT_TYPE_MIX)) {
                    ALOGW("createAudioPatch() invalid sink type %d for device source",
                          patch->sinks[i].type);
                    return BAD_VALUE;
                }
            }

            AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index);
            if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) {
                if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
                    sp<ThreadBase> thread = audioflinger->checkRecordThread_l(
+18 −0
Original line number Diff line number Diff line
@@ -162,6 +162,24 @@ public:
    virtual status_t    dump(int fd) = 0;

    virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo) = 0;

    virtual status_t listAudioPorts(audio_port_role_t role,
                                    audio_port_type_t type,
                                    unsigned int *num_ports,
                                    struct audio_port *ports,
                                    unsigned int *generation) = 0;
    virtual status_t getAudioPort(struct audio_port *port) = 0;
    virtual status_t createAudioPatch(const struct audio_patch *patch,
                                       audio_patch_handle_t *handle,
                                       uid_t uid) = 0;
    virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
                                          uid_t uid) = 0;
    virtual status_t listAudioPatches(unsigned int *num_patches,
                                      struct audio_patch *patches,
                                      unsigned int *generation) = 0;
    virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
    virtual void clearAudioPatches(uid_t uid) = 0;

};


+48 −19
Original line number Diff line number Diff line
@@ -463,43 +463,72 @@ bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
    return mAudioPolicyManager->isOffloadSupported(info);
}

status_t AudioPolicyService::listAudioPorts(audio_port_role_t role __unused,
                                            audio_port_type_t type __unused,
status_t AudioPolicyService::listAudioPorts(audio_port_role_t role,
                                            audio_port_type_t type,
                                            unsigned int *num_ports,
                                            struct audio_port *ports __unused,
                                            unsigned int *generation __unused)
                                            struct audio_port *ports,
                                            unsigned int *generation)
{
    *num_ports = 0;
    return INVALID_OPERATION;
    Mutex::Autolock _l(mLock);
    if (mAudioPolicyManager == NULL) {
        return NO_INIT;
    }

    return mAudioPolicyManager->listAudioPorts(role, type, num_ports, ports, generation);
}

status_t AudioPolicyService::getAudioPort(struct audio_port *port __unused)
status_t AudioPolicyService::getAudioPort(struct audio_port *port)
{
    return INVALID_OPERATION;
    Mutex::Autolock _l(mLock);
    if (mAudioPolicyManager == NULL) {
        return NO_INIT;
    }

status_t AudioPolicyService::createAudioPatch(const struct audio_patch *patch __unused,
        audio_patch_handle_t *handle __unused)
    return mAudioPolicyManager->getAudioPort(port);
}

status_t AudioPolicyService::createAudioPatch(const struct audio_patch *patch,
        audio_patch_handle_t *handle)
{
    return INVALID_OPERATION;
    Mutex::Autolock _l(mLock);
    if (mAudioPolicyManager == NULL) {
        return NO_INIT;
    }
    return mAudioPolicyManager->createAudioPatch(patch, handle,
                                                  IPCThreadState::self()->getCallingUid());
}

status_t AudioPolicyService::releaseAudioPatch(audio_patch_handle_t handle __unused)
status_t AudioPolicyService::releaseAudioPatch(audio_patch_handle_t handle)
{
    return INVALID_OPERATION;
    Mutex::Autolock _l(mLock);
    if (mAudioPolicyManager == NULL) {
        return NO_INIT;
    }

    return mAudioPolicyManager->releaseAudioPatch(handle,
                                                     IPCThreadState::self()->getCallingUid());
}

status_t AudioPolicyService::listAudioPatches(unsigned int *num_patches,
        struct audio_patch *patches __unused,
        unsigned int *generation __unused)
        struct audio_patch *patches,
        unsigned int *generation)
{
    *num_patches = 0;
    return INVALID_OPERATION;
    Mutex::Autolock _l(mLock);
    if (mAudioPolicyManager == NULL) {
        return NO_INIT;
    }

status_t AudioPolicyService::setAudioPortConfig(const struct audio_port_config *config __unused)
    return mAudioPolicyManager->listAudioPatches(num_patches, patches, generation);
}

status_t AudioPolicyService::setAudioPortConfig(const struct audio_port_config *config)
{
    return INVALID_OPERATION;
    Mutex::Autolock _l(mLock);
    if (mAudioPolicyManager == NULL) {
        return NO_INIT;
    }

    return mAudioPolicyManager->setAudioPortConfig(config);
}

}; // namespace android
+701 −65

File changed.

Preview size limit exceeded, changes collapsed.

+57 −7
Original line number Diff line number Diff line
@@ -140,6 +140,23 @@ public:

        virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);

        virtual status_t listAudioPorts(audio_port_role_t role,
                                        audio_port_type_t type,
                                        unsigned int *num_ports,
                                        struct audio_port *ports,
                                        unsigned int *generation);
        virtual status_t getAudioPort(struct audio_port *port);
        virtual status_t createAudioPatch(const struct audio_patch *patch,
                                           audio_patch_handle_t *handle,
                                           uid_t uid);
        virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
                                              uid_t uid);
        virtual status_t listAudioPatches(unsigned int *num_patches,
                                          struct audio_patch *patches,
                                          unsigned int *generation);
        virtual status_t setAudioPortConfig(const struct audio_port_config *config);
        virtual void clearAudioPatches(uid_t uid);

protected:

        enum routing_strategy {
@@ -213,6 +230,18 @@ protected:
            HwModule *mModule;                     // audio HW module exposing this I/O stream
        };

        class AudioPatch: public RefBase
        {
        public:
            AudioPatch(audio_patch_handle_t handle,
                       const struct audio_patch *patch, uid_t uid) :
                           mHandle(handle), mPatch(*patch), mUid(uid), mAfPatchHandle(0) {}

            audio_patch_handle_t mHandle;
            struct audio_patch mPatch;
            uid_t mUid;
            audio_patch_handle_t mAfPatchHandle;
        };

        class DeviceDescriptor: public AudioPort
        {
@@ -236,7 +265,8 @@ protected:
            virtual ~DeviceDescriptor() {}

            bool equals(const sp<DeviceDescriptor>& other) const;
            void toAudioPortConfig(struct audio_port_config *config) const;
            void toAudioPortConfig(struct audio_port_config *dstConfig,
                                   const struct audio_port_config *srcConfig = NULL) const;
            virtual void toAudioPort(struct audio_port *port) const;

            status_t dump(int fd, int spaces) const;
@@ -262,6 +292,7 @@ protected:
            void loadDevicesFromType(audio_devices_t types);
            sp<DeviceDescriptor> getDevice(audio_devices_t type, String8 address) const;
            DeviceVector getDevicesFromType(audio_devices_t types) const;
            sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;

        private:
            void refreshTypes();
@@ -335,7 +366,8 @@ protected:
                             uint32_t inPastMs = 0,
                             nsecs_t sysTime = 0) const;

            void toAudioPortConfig(struct audio_port_config *config) const;
            void toAudioPortConfig(struct audio_port_config *dstConfig,
                                   const struct audio_port_config *srcConfig = NULL) const;
            void toAudioPort(struct audio_port *port) const;

            audio_port_handle_t mId;
@@ -379,7 +411,8 @@ protected:
            audio_source_t mInputSource;                // input source selected by application (mediarecorder.h)
            const sp<IOProfile> mProfile;                  // I/O profile this output derives from

            void toAudioPortConfig(struct audio_port_config *config) const;
            void toAudioPortConfig(struct audio_port_config *dstConfig,
                                   const struct audio_port_config *srcConfig = NULL) const;
            void toAudioPort(struct audio_port *port) const;
        };

@@ -439,13 +472,17 @@ protected:
        uint32_t setOutputDevice(audio_io_handle_t output,
                             audio_devices_t device,
                             bool force = false,
                             int delayMs = 0);
                             int delayMs = 0,
                             audio_patch_handle_t *patchHandle = NULL);
        status_t resetOutputDevice(audio_io_handle_t output,
                                   int delayMs = 0);
                                   int delayMs = 0,
                                   audio_patch_handle_t *patchHandle = NULL);
        status_t setInputDevice(audio_io_handle_t input,
                                audio_devices_t device,
                                bool force = false);
        status_t resetInputDevice(audio_io_handle_t input);
                                bool force = false,
                                audio_patch_handle_t *patchHandle = NULL);
        status_t resetInputDevice(audio_io_handle_t input,
                                  audio_patch_handle_t *patchHandle = NULL);

        // select input device corresponding to requested audio source
        virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource);
@@ -589,6 +626,13 @@ protected:

        bool isNonOffloadableEffectEnabled();

        status_t addAudioPatch(audio_patch_handle_t handle,
                               const sp<AudioPatch>& patch);
        status_t removeAudioPatch(audio_patch_handle_t handle);

        AudioOutputDescriptor *getOutputFromId(audio_port_handle_t id) const;
        AudioInputDescriptor *getInputFromId(audio_port_handle_t id) const;
        HwModule *getModuleForDevice(audio_devices_t device) const;
        //
        // Audio policy configuration file parsing (audio_policy.conf)
        //
@@ -610,6 +654,7 @@ protected:
        void defaultAudioPolicyConfig(void);


        uid_t mUidCached;
        AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
        audio_io_handle_t mPrimaryOutput;              // primary output handle
        // list of descriptors for outputs currently opened
@@ -644,6 +689,9 @@ protected:

        Vector <HwModule *> mHwModules;
        volatile int32_t mNextUniqueId;
        volatile int32_t mAudioPortGeneration;

        DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;

#ifdef AUDIO_POLICY_TEST
        Mutex   mLock;
@@ -668,6 +716,8 @@ private:
        void handleNotificationRoutingForStream(audio_stream_type_t stream);
        static bool isVirtualInputDevice(audio_devices_t device);
        uint32_t nextUniqueId();
        uint32_t nextAudioPortGeneration();
        uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
        // converts device address to string sent to audio HAL via setParameters
        static String8 addressToParameter(audio_devices_t device, const String8 address);
};