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

Commit a920ee99 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 6636

* changes:
  Implemented the metadata changed notification filters.
parents 699f095c a7e0e8b4
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -52,8 +52,13 @@ public:
    // @param request Parcel that must start with the media player
    // interface token.
    // @param[out] reply Parcel to hold the reply data. Cannot be null.
    // @return OK if the invocation was made. PERMISSION_DENIED otherwise.
    // @return OK if the invocation was made successfully.
    virtual status_t        invoke(const Parcel& request, Parcel *reply) = 0;

    // Set a new metadata filter.
    // @param filter A set of allow and drop rules serialized in a Parcel.
    // @return OK if the invocation was made successfully.
    virtual status_t        setMetadataFilter(const Parcel& filter) = 0;
};

// ----------------------------------------------------------------------------
+3 −0
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@ enum media_info_type {
    MEDIA_INFO_BAD_INTERLEAVING = 800,
    // The media is not seekable (e.g live stream).
    MEDIA_INFO_NOT_SEEKABLE = 801,
    // New media metadata is available.
    MEDIA_INFO_METADATA_UPDATE = 802,
};


@@ -152,6 +154,7 @@ public:
    static  sp<IMemory>     decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
    static  sp<IMemory>     decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
            status_t        invoke(const Parcel& request, Parcel *reply);
            status_t        setMetadataFilter(const Parcel& filter);
private:
            void            clear_l();
            status_t        seekTo_l(int msec);
+15 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ enum {
    SET_LOOPING,
    SET_VOLUME,
    INVOKE,
    SET_METADATA_FILTER,
};

class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -178,6 +179,15 @@ public:
        status_t retcode = remote()->transact(INVOKE, request, reply);
        return retcode;
    }

    status_t setMetadataFilter(const Parcel& request)
    {
        Parcel reply;
        // Avoid doing any extra copy of the request. The interface
        // descriptor should have been set by MediaPlayer.java.
        remote()->transact(SET_METADATA_FILTER, request, &reply);
        return reply.readInt32();
    }
};

IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -273,6 +283,11 @@ status_t BnMediaPlayer::onTransact(
            invoke(data, reply);
            return NO_ERROR;
        } break;
        case SET_METADATA_FILTER: {
            CHECK_INTERFACE(IMediaPlayer, data, reply);
            reply->writeInt32(setMetadataFilter(data));
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
+10 −1
Original line number Diff line number Diff line
@@ -208,7 +208,16 @@ status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
    return INVALID_OPERATION;
}


status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
{
    LOGD("setMetadataFilter");
    Mutex::Autolock _l(mLock);
    if (mPlayer == NULL)
    {
        return NO_INIT;
    }
    return mPlayer->setMetadataFilter(filter);
}

status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
{
+185 −0
Original line number Diff line number Diff line
@@ -69,6 +69,150 @@ pid_t gettid() { return syscall(__NR_gettid);}
#undef __KERNEL__
#endif

namespace {
using android::status_t;
using android::OK;
using android::BAD_VALUE;
using android::NOT_ENOUGH_DATA;
using android::Parcel;
using android::Vector;

// Max number of entries in the filter.
const int kMaxFilterSize = 64;  // I pulled that out of thin air.

// Keep in sync with ANY in Metadata.java
const int32_t kAny = 0;

// To order the metadata types in the vector-filter.
int lessThan(const int32_t *lhs, const int32_t *rhs)
{
    return *lhs < *rhs ? 0 : 1;
}

// Unmarshall a filter from a Parcel.
// Filter format in a parcel:
//
//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |                       number of entries (n)                   |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |                       metadata type 1                         |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |                       metadata type 2                         |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  ....
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |                       metadata type n                         |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// @param p Parcel that should start with a filter.
// @param[out] filter On exit contains the list of metadata type to be
//                    filtered.
// @param[out] status On exit contains the status code to be returned.
// @return true if the parcel starts with a valid filter.
bool unmarshallFilter(const Parcel& p,
                      Vector<int32_t> *filter,
                      status_t *status)
{
    int32_t s;
    if (p.readInt32(&s) != OK)
    {
        LOGE("Failed to read filter's length");
        *status = NOT_ENOUGH_DATA;
        return false;
    }

    if( s > kMaxFilterSize || s < 0)
    {
        LOGE("Invalid filter len %d", s);
        *status = BAD_VALUE;
        return false;
    }

    size_t size = s;

    filter->clear();
    filter->setCapacity(size);

    s *= sizeof(int32_t);

    if (p.dataAvail() < static_cast<size_t>(s))
    {
        LOGE("Filter too short expected %d but got %d", s, p.dataAvail());
        *status = NOT_ENOUGH_DATA;
        return false;
    }

    const int32_t *data = static_cast<const int32_t*>(p.readInplace(s));

    if (NULL == data )
    {
        LOGE("Filter had no data");
        *status = BAD_VALUE;
        return false;
    }

    // TODO: The stl impl of vector would be more efficient here
    // because it degenerates into a memcpy on pod types. Try to
    // replace later or use stl::set.
    for (size_t i = 0; i < size; ++i)
    {
        filter->push(*data);
        ++data;
    }
    *status = OK;
    return true;
}

bool unmarshallBothFilters(const Parcel& p,
                           Vector<int32_t> *allow,
                           Vector<int32_t> *block,
                           status_t *status)
{
    if (!(unmarshallFilter(p, allow, status) && unmarshallFilter(p, block, status)))
    {
        return false;
    }
    allow->sort(lessThan);
    block->sort(lessThan);
    return true;
}

// @param filter Should be sorted in ascending order.
// @param val To be searched.
// @return true if a match was found.
bool findMetadata(const Vector<int32_t> filter, const int32_t val)
{
    // Deal with empty and ANY right away
    if (filter.isEmpty()) return false;
    if (filter[0] == kAny) return true;

    ssize_t min = 0;
    ssize_t max = filter.size() - 1;
    ssize_t mid;
    do
    {
        mid = (min + max) / 2;
        if (val > filter[mid])
        {
            min = mid + 1;
        }
        else
        {
            max = mid - 1;
        }
        if (filter[mid] == val)
        {
            return true;
        }
    }
    while(min <= max);
    return false;
}

}  // anonymous namespace


namespace android {

// TODO: Temp hack until we can register players
@@ -686,6 +830,22 @@ status_t MediaPlayerService::Client::invoke(const Parcel& request,
    return p->invoke(request, reply);
}

// This call doesn't need to access the native player.
status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
{
    status_t status;
    Vector<int32_t> allow, drop;

    if (unmarshallBothFilters(filter, &allow, &drop, &status))
    {
        Mutex::Autolock l(mLock);

        mMetadataAllow = allow;
        mMetadataDrop = drop;
    }
    return status;
}

status_t MediaPlayerService::Client::prepareAsync()
{
    LOGV("[%d] prepareAsync", mConnId);
@@ -808,10 +968,35 @@ status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolu
void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
{
    Client* client = static_cast<Client*>(cookie);

    if (MEDIA_INFO == msg &&
        MEDIA_INFO_METADATA_UPDATE == ext1 &&
        client->shouldDropMetadata(ext2 /* metadata type */)) {
        return;
    }
    LOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
    client->mClient->notify(msg, ext1, ext2);
}

bool MediaPlayerService::Client::shouldDropMetadata(int code) const
{
    Mutex::Autolock l(mLock);

    if (findMetadata(mMetadataDrop, code))
    {
        return true;
    }

    if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code))
    {
        return false;
    }
    else
    {
        return true;
    }
}

#if CALLBACK_ANTAGONIZER
const int Antagonizer::interval = 10000; // 10 msecs

Loading