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

Commit a9034e0e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "add native IPlayer interface implementation" into oc-dev

parents 40e76f5f b5323222
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ cc_library_shared {
        "IEffect.cpp",
        "IEffectClient.cpp",
        "ToneGenerator.cpp",
        "PlayerBase.cpp",
        "TrackPlayerBase.cpp",
    ],
    shared_libs: [
        "liblog",
@@ -30,6 +32,7 @@ cc_library_shared {
        "libbinder",
        "libdl",
        "libaudioutils",
        "libaudiomanager",
    ],
    export_shared_lib_headers: ["libbinder"],

+165 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

#include <binder/IServiceManager.h>
#include <media/PlayerBase.h>

#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))

namespace android {

//--------------------------------------------------------------------------------------------------
PlayerBase::PlayerBase() : BnPlayer(),
        mPanMultiplierL(1.0f), mPanMultiplierR(1.0f),
        mVolumeMultiplierL(1.0f), mVolumeMultiplierR(1.0f),
        mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN)
{
    ALOGD("PlayerBase::PlayerBase()");
    // use checkService() to avoid blocking if audio service is not up yet
    sp<IBinder> binder = defaultServiceManager()->checkService(String16("audio"));
    if (binder == 0) {
        ALOGE("PlayerBase(): binding to audio service failed, service up?");
    } else {
        mAudioManager = interface_cast<IAudioManager>(binder);
    }
}


PlayerBase::~PlayerBase() {
    ALOGD("PlayerBase::~PlayerBase()");
    baseDestroy();
}

void PlayerBase::init(player_type_t playerType, audio_usage_t usage) {
    if (mAudioManager == 0) {
                ALOGE("AudioPlayer realize: no audio service, player will not be registered");
    } else {
        mPIId = mAudioManager->trackPlayer(playerType, usage, AUDIO_CONTENT_TYPE_UNKNOWN, this);
    }
}

void PlayerBase::baseDestroy() {
    serviceReleasePlayer();
    if (mAudioManager != 0) {
        mAudioManager.clear();
    }
}

//------------------------------------------------------------------------------
void PlayerBase::servicePlayerEvent(player_state_t event) {
    if (mAudioManager != 0) {
        // only report state change
        Mutex::Autolock _l(mPlayerStateLock);
        if (event != mLastReportedEvent
                && mPIId != PLAYER_PIID_INVALID) {
            mLastReportedEvent = event;
            mAudioManager->playerEvent(mPIId, event);
        }
    }
}

void PlayerBase::serviceReleasePlayer() {
    if (mAudioManager != 0
            && mPIId != PLAYER_PIID_INVALID) {
        mAudioManager->releasePlayer(mPIId);
    }
}

//FIXME temporary method while some AudioTrack state is outside of this class
void PlayerBase::reportEvent(player_state_t event) {
    servicePlayerEvent(event);
}

//------------------------------------------------------------------------------
// Implementation of IPlayer
void PlayerBase::start() {
    if (playerStart() == NO_ERROR) {
        ALOGD("PlayerBase::start() from IPlayer");
        servicePlayerEvent(PLAYER_STATE_STARTED);
    } else {
        ALOGD("PlayerBase::start() no AudioTrack to start from IPlayer");
    }
}

void PlayerBase::pause() {
    if (playerPause() == NO_ERROR) {
        ALOGD("PlayerBase::pause() from IPlayer");
        servicePlayerEvent(PLAYER_STATE_PAUSED);
    } else {
        ALOGD("PlayerBase::pause() no AudioTrack to pause from IPlayer");
    }
}


void PlayerBase::stop() {
    if (playerStop() == NO_ERROR) {
        ALOGD("PlayerBase::stop() from IPlayer");
        servicePlayerEvent(PLAYER_STATE_STOPPED);
    } else {
        ALOGD("PlayerBase::stop() no AudioTrack to stop from IPlayer");
    }
}

void PlayerBase::setVolume(float vol) {
    {
        Mutex::Autolock _l(mSettingsLock);
        mVolumeMultiplierL = vol;
        mVolumeMultiplierR = vol;
    }
    if (playerSetVolume() == NO_ERROR) {
        ALOGD("PlayerBase::setVolume() from IPlayer");
    } else {
        ALOGD("PlayerBase::setVolume() no AudioTrack for volume control from IPlayer");
    }
}

void PlayerBase::setPan(float pan) {
    {
        Mutex::Autolock _l(mSettingsLock);
        pan = min(max(-1.0f, pan), 1.0f);
        if (pan >= 0.0f) {
            mPanMultiplierL = 1.0f - pan;
            mPanMultiplierR = 1.0f;
        } else {
            mPanMultiplierL = 1.0f;
            mPanMultiplierR = 1.0f + pan;
        }
    }
    if (playerSetVolume() == NO_ERROR) {
        ALOGD("PlayerBase::setPan() from IPlayer");
    } else {
        ALOGD("PlayerBase::setPan() no AudioTrack for volume control from IPlayer");
    }
}

void PlayerBase::setStartDelayMs(int32_t delayMs __unused) {
    ALOGW("setStartDelay() is not supported");
}

void PlayerBase::applyVolumeShaper(
        const sp<VolumeShaper::Configuration>& configuration  __unused,
        const sp<VolumeShaper::Operation>& operation __unused) {
    ALOGW("applyVolumeShaper() is not supported");
}

status_t PlayerBase::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    return BnPlayer::onTransact(code, data, reply, flags);
}

} // namespace android
+121 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

#include <media/TrackPlayerBase.h>

namespace android {

//--------------------------------------------------------------------------------------------------
TrackPlayerBase::TrackPlayerBase() : PlayerBase(),
        mPlayerVolumeL(1.0f), mPlayerVolumeR(1.0f)
{
    ALOGD("TrackPlayerBase::TrackPlayerBase()");
}


TrackPlayerBase::~TrackPlayerBase() {
    ALOGD("TrackPlayerBase::~TrackPlayerBase()");
    doDestroy();
}

void TrackPlayerBase::init(AudioTrack* pat, player_type_t playerType, audio_usage_t usage) {
    PlayerBase::init(playerType, usage);
    mAudioTrack = pat;
}

void TrackPlayerBase::destroy() {
    doDestroy();
    baseDestroy();
}

void TrackPlayerBase::doDestroy() {
    if (mAudioTrack != 0) {
        mAudioTrack->stop();
        // Note that there may still be another reference in post-unlock phase of SetPlayState
        mAudioTrack.clear();
    }
}

void TrackPlayerBase::setPlayerVolume(float vl, float vr) {
    {
        Mutex::Autolock _l(mSettingsLock);
        mPlayerVolumeL = vl;
        mPlayerVolumeR = vr;
    }
    doSetVolume();
}

//------------------------------------------------------------------------------
// Implementation of IPlayer
status_t TrackPlayerBase::playerStart() {
    status_t status = NO_INIT;
    if (mAudioTrack != 0) {
        status = mAudioTrack->start();
    }
    return status;
}

status_t TrackPlayerBase::playerPause() {
    status_t status = NO_INIT;
    if (mAudioTrack != 0) {
        mAudioTrack->pause();
        status = NO_ERROR;
    }
    return status;
}


status_t TrackPlayerBase::playerStop() {
    status_t status = NO_INIT;
    if (mAudioTrack != 0) {
        mAudioTrack->stop();
        status = NO_ERROR;
    }
    return status;
}

status_t TrackPlayerBase::playerSetVolume() {
    return doSetVolume();
}

status_t TrackPlayerBase::doSetVolume() {
    status_t status = NO_INIT;
    if (mAudioTrack != 0) {
        float tl = mPlayerVolumeL * mPanMultiplierL * mVolumeMultiplierL;
        float tr = mPlayerVolumeR * mPanMultiplierR * mVolumeMultiplierR;
        mAudioTrack->setVolume(tl, tr);
        status = NO_ERROR;
    }
    return status;
}


void TrackPlayerBase::applyVolumeShaper(
        const sp<VolumeShaper::Configuration>& configuration,
        const sp<VolumeShaper::Operation>& operation) {
    if (mAudioTrack != 0) {
        ALOGD("TrackPlayerBase::applyVolumeShaper() from IPlayer");
        VolumeShaper::Status status = mAudioTrack->applyVolumeShaper(configuration, operation);
        if (status < 0) { // a non-negative value is the volume shaper id.
            ALOGE("TrackPlayerBase::applyVolumeShaper() failed with status %d", status);
        }
    } else {
        ALOGD("TrackPlayerBase::applyVolumeShaper()"
                " no AudioTrack for volume control from IPlayer");
    }
}

} // namespace android
+89 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

#ifndef __ANDROID_PLAYER_BASE_H__
#define __ANDROID_PLAYER_BASE_H__

#include <audiomanager/IPlayer.h>
#include <audiomanager/AudioManager.h>
#include <audiomanager/IAudioManager.h>


namespace android {

class PlayerBase : public BnPlayer
{
public:
    explicit PlayerBase();
    virtual ~PlayerBase();

    virtual void destroy() = 0;

    //IPlayer implementation
    virtual void start();
    virtual void pause();
    virtual void stop();
    virtual void setVolume(float vol);
    virtual void setPan(float pan);
    virtual void setStartDelayMs(int32_t delayMs);
    virtual void applyVolumeShaper(
            const sp<VolumeShaper::Configuration>& configuration,
            const sp<VolumeShaper::Operation>& operation) override;

    virtual status_t onTransact(
                uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);


            //FIXME temporary method while some player state is outside of this class
            void reportEvent(player_state_t event);

protected:

            void init(player_type_t playerType, audio_usage_t usage);
            void baseDestroy();

    //IPlayer methods handlers for derived classes
    virtual status_t playerStart()  { return NO_ERROR; }
    virtual status_t playerPause()  { return NO_ERROR; }
    virtual status_t playerStop()  { return NO_ERROR; }
    virtual status_t playerSetVolume()  { return NO_ERROR; }

    // mutex for IPlayer volume and pan, and player-specific volume
    Mutex mSettingsLock;

    // volume multipliers coming from the IPlayer volume and pan controls
    float mPanMultiplierL, mPanMultiplierR;
    float mVolumeMultiplierL, mVolumeMultiplierR;

private:
            // report events to AudioService
            void servicePlayerEvent(player_state_t event);
            void serviceReleasePlayer();

    // native interface to AudioService
    android::sp<android::IAudioManager> mAudioManager;

    // player interface ID, uniquely identifies the player in the system
    audio_unique_id_t mPIId;

    // Mutex for state reporting
    Mutex mPlayerStateLock;
    player_state_t mLastReportedEvent;
};

} // namespace android

#endif /* __ANDROID_PLAYER_BASE_H__ */
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

#ifndef __ANDROID_TRACK_PLAYER_BASE_H__
#define __ANDROID_TRACK_PLAYER_BASE_H__

#include <media/AudioTrack.h>
#include <media/PlayerBase.h>

namespace android {

class TrackPlayerBase : public PlayerBase
{
public:
    explicit TrackPlayerBase();
    virtual ~TrackPlayerBase();

            void init(AudioTrack* pat, player_type_t playerType, audio_usage_t usage);
    virtual void destroy();

    //IPlayer implementation
    virtual void applyVolumeShaper(
            const sp<VolumeShaper::Configuration>& configuration,
            const sp<VolumeShaper::Operation>& operation);

    //FIXME move to protected field, so far made public to minimize changes to AudioTrack logic
    sp<AudioTrack> mAudioTrack;

            void setPlayerVolume(float vl, float vr);

protected:

    //PlayerBase virtuals
    virtual status_t playerStart();
    virtual status_t playerPause();
    virtual status_t playerStop();
    virtual status_t playerSetVolume();

private:
            void doDestroy();
            status_t doSetVolume();

    // volume coming from the player volume API
    float mPlayerVolumeL, mPlayerVolumeR;
};

} // namespace android

#endif /* __ANDROID_TRACK_PLAYER_BASE_H__ */