MediaPlayerService.h revision f2c87b3f88d987d2af6322e9763eb8224a2bae48
199e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten/* 265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Copyright 2008, The Android Open Source Project 465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Licensed under the Apache License, Version 2.0 (the "License"); 665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** you may not use this file except in compliance with the License. 765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** You may obtain a copy of the License at 865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** http://www.apache.org/licenses/LICENSE-2.0 1065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 1165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Unless required by applicable law or agreed to in writing, software 1265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** distributed under the License is distributed on an "AS IS" BASIS, 1365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** See the License for the specific language governing permissions and 1565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** limitations under the License. 1665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian*/ 1765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#ifndef ANDROID_MEDIAPLAYERSERVICE_H 1965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define ANDROID_MEDIAPLAYERSERVICE_H 2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <arpa/inet.h> 2265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <utils/threads.h> 2465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <utils/Errors.h> 2565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <utils/KeyedVector.h> 2665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <utils/String8.h> 279ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wang#include <utils/Vector.h> 2865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/MediaPlayerInterface.h> 3065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/Metadata.h> 3165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/stagefright/foundation/ABase.h> 3265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <system/audio.h> 3438ccae2c0324daa305f3fe77d25fdf5edec0b0e1Eric Laurent 3565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace android { 36fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin 3765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstruct AudioPlaybackRate; 38f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kastenclass AudioTrack; 3965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstruct AVSyncSettings; 409ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wangclass IDataSource; 4125b248eb52a0a16adaef6b79c9d92cb88b9a2bc2Glenn Kastenclass IMediaRecorder; 4265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianclass IMediaMetadataRetriever; 4365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianclass IOMX; 4465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianclass IRemoteDisplay; 45fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavinclass IRemoteDisplayClient; 4664760240f931714858a59c1579f07264d7182ba2Dima Zavinclass MediaRecorderClient; 477394a4f358fa9908a9f0a7c954b65c399f4268e6Dima Zavin 4865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define CALLBACK_ANTAGONIZER 0 4965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if CALLBACK_ANTAGONIZER 5065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianclass Antagonizer { 5144deb053252a3bd2f57a007ab9560f4924f62394Glenn Kastenpublic: 5265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian Antagonizer(notify_callback_f cb, void* client); 5365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian void start() { mActive = true; } 546d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent void stop() { mActive = false; } 5559bd0da8373af0e5159b799495fda51e03120ea4Eric Laurent void kill(); 5659bd0da8373af0e5159b799495fda51e03120ea4Eric Laurentprivate: 5765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian static const int interval; 583b21c50ef95fe4e7ac3426ca14b365749e66ff08Glenn Kasten Antagonizer(); 593b21c50ef95fe4e7ac3426ca14b365749e66ff08Glenn Kasten static int callbackThread(void* cookie); 604d8d0c30abfa4b8d75866d42094cc797e05068faGlenn Kasten Mutex mLock; 61feb0db689c17dced50afaee54c659f1676e2d505Eric Laurent Condition mCondition; 624d8d0c30abfa4b8d75866d42094cc797e05068faGlenn Kasten bool mExit; 634d8d0c30abfa4b8d75866d42094cc797e05068faGlenn Kasten bool mActive; 644ff14bae91075eb274eb1c2975982358946e7e63John Grossman void* mClient; 654ff14bae91075eb274eb1c2975982358946e7e63John Grossman notify_callback_f mCb; 664ff14bae91075eb274eb1c2975982358946e7e63John Grossman}; 6765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 6865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 69de070137f11d346fba77605bd76a44c040a618fcEric Laurentclass MediaPlayerService : public BnMediaPlayerService 7065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 7165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian class Client; 72ec1d6b5e17281a066d618f7fcd2b63b3ce11f421Glenn Kasten 73ec1d6b5e17281a066d618f7fcd2b63b3ce11f421Glenn Kasten class AudioOutput : public MediaPlayerBase::AudioSink 7465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian { 7565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian class CallbackData; 76b1cf75c4935001f61057989ee3cf27bbf09ecd9cGlenn Kasten 7765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian public: 7865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioOutput(audio_session_t sessionId, int uid, int pid, 7965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const audio_attributes_t * attr); 8065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual ~AudioOutput(); 8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 8265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual bool ready() const { return mTrack != 0; } 8365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual ssize_t bufferSize() const; 8465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual ssize_t frameCount() const; 8565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual ssize_t channelCount() const; 8665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual ssize_t frameSize() const; 8765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual uint32_t latency() const; 887dede876998ff56351d495ec3a798c1b131193e8Glenn Kasten virtual float msecsPerFrame() const; 8965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t getPosition(uint32_t *position) const; 907dede876998ff56351d495ec3a798c1b131193e8Glenn Kasten virtual status_t getTimestamp(AudioTimestamp &ts) const; 917dede876998ff56351d495ec3a798c1b131193e8Glenn Kasten virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const; 9265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t getFramesWritten(uint32_t *frameswritten) const; 937c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent virtual audio_session_t getSessionId() const; 947c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent virtual uint32_t getSampleRate() const; 9565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual int64_t getBufferDurationInUs() const; 967dede876998ff56351d495ec3a798c1b131193e8Glenn Kasten 977dede876998ff56351d495ec3a798c1b131193e8Glenn Kasten virtual status_t open( 9860cd0a0d488e604d27fc7dbb02b00348693dfde2Eric Laurent uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, 997cafbb32999049873d4746ba83bd20c88abe6ce6Eric Laurent audio_format_t format, int bufferCount, 1007cafbb32999049873d4746ba83bd20c88abe6ce6Eric Laurent AudioCallback cb, void *cookie, 1017cafbb32999049873d4746ba83bd20c88abe6ce6Eric Laurent audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, 1027cafbb32999049873d4746ba83bd20c88abe6ce6Eric Laurent const audio_offload_info_t *offloadInfo = NULL, 1037cafbb32999049873d4746ba83bd20c88abe6ce6Eric Laurent bool doNotReconnect = false, 1044ff14bae91075eb274eb1c2975982358946e7e63John Grossman uint32_t suggestedFrameCount = 0); 1057cafbb32999049873d4746ba83bd20c88abe6ce6Eric Laurent 10665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t start(); 10765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual ssize_t write(const void* buffer, size_t size, bool blocking = true); 1089ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wang virtual void stop(); 1099ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wang virtual void flush(); 11025b248eb52a0a16adaef6b79c9d92cb88b9a2bc2Glenn Kasten virtual void pause(); 11125b248eb52a0a16adaef6b79c9d92cb88b9a2bc2Glenn Kasten virtual void close(); 11225b248eb52a0a16adaef6b79c9d92cb88b9a2bc2Glenn Kasten void setAudioStreamType(audio_stream_type_t streamType); 1139ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wang virtual audio_stream_type_t getAudioStreamType() const { return mStreamType; } 1149ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wang void setAudioAttributes(const audio_attributes_t * attributes); 1159ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wang 1169ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wang void setVolume(float left, float right); 1179ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wang virtual status_t setPlaybackRate(const AudioPlaybackRate& rate); 1189ee159b79022b2e1a050acb3890ce948e99e9ccbGloria Wang virtual status_t getPlaybackRate(AudioPlaybackRate* rate /* nonnull */); 119799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 120799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin status_t setAuxEffectSendLevel(float level); 121799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin status_t attachAuxEffect(int effectId); 122799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t dump(int fd, const Vector<String16>& args) const; 123799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 124799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin static bool isOnEmulator(); 125799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin static int getMinBufferCount(); 126799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin void setNextOutput(const sp<AudioOutput>& nextOutput); 127799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin void switchToNextOutput(); 128799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual bool needsTrailingPadding() { return mNextOutput == NULL; } 12929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block virtual status_t setParameters(const String8& keyValuePairs); 130799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual String8 getParameters(const String8& keys); 131799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 132799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin private: 133799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin static void setMinBufferCount(); 134799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin static void CallbackWrapper( 135799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin int event, void *me, void *info); 136799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin void deleteRecycledTrack_l(); 137799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin void close_l(); 138799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 139799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin sp<AudioTrack> mTrack; 140799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin sp<AudioTrack> mRecycledTrack; 141799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin sp<AudioOutput> mNextOutput; 142ec1d6b5e17281a066d618f7fcd2b63b3ce11f421Glenn Kasten AudioCallback mCallback; 143799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin void * mCallbackCookie; 144799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin CallbackData * mCallbackData; 145799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin audio_stream_type_t mStreamType; 146799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin audio_attributes_t * mAttributes; 147799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin float mLeftVolume; 148799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin float mRightVolume; 14965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioPlaybackRate mPlaybackRate; 15065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t mSampleRateHz; // sample rate of the content, as set in open() 15165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian float mMsecsPerFrame; 15265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t mFrameSize; 1534ff14bae91075eb274eb1c2975982358946e7e63John Grossman audio_session_t mSessionId; 1544ff14bae91075eb274eb1c2975982358946e7e63John Grossman int mUid; 1554ff14bae91075eb274eb1c2975982358946e7e63John Grossman int mPid; 1564ff14bae91075eb274eb1c2975982358946e7e63John Grossman float mSendLevel; 1574ff14bae91075eb274eb1c2975982358946e7e63John Grossman int mAuxEffectId; 1584ff14bae91075eb274eb1c2975982358946e7e63John Grossman audio_output_flags_t mFlags; 1594ff14bae91075eb274eb1c2975982358946e7e63John Grossman mutable Mutex mLock; 1604ff14bae91075eb274eb1c2975982358946e7e63John Grossman 16165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // static variables below not protected by mutex 1625a61d2f277af3098fc10b2881babca16391362daDima Zavin static bool mIsOnEmulator; 1635a61d2f277af3098fc10b2881babca16391362daDima Zavin static int mMinBufferCount; // 12 for emulator; otherwise 4 1645a61d2f277af3098fc10b2881babca16391362daDima Zavin 1655a61d2f277af3098fc10b2881babca16391362daDima Zavin // CallbackData is what is passed to the AudioTrack as the "user" data. 166799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin // We need to be able to target this to a different Output on the fly, 167fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin // so we can't use the Output itself for this. 168935752053ef2691dbb6d5a6d149e0e362c6e3c74Eric Laurent class CallbackData { 169935752053ef2691dbb6d5a6d149e0e362c6e3c74Eric Laurent friend AudioOutput; 170799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin public: 1714ff14bae91075eb274eb1c2975982358946e7e63John Grossman CallbackData(AudioOutput *cookie) { 1724ff14bae91075eb274eb1c2975982358946e7e63John Grossman mData = cookie; 1734ff14bae91075eb274eb1c2975982358946e7e63John Grossman mSwitching = false; 1744ff14bae91075eb274eb1c2975982358946e7e63John Grossman } 1754ff14bae91075eb274eb1c2975982358946e7e63John Grossman AudioOutput * getOutput() const { return mData; } 1764ff14bae91075eb274eb1c2975982358946e7e63John Grossman void setOutput(AudioOutput* newcookie) { mData = newcookie; } 1774ff14bae91075eb274eb1c2975982358946e7e63John Grossman // lock/unlock are used by the callback before accessing the payload of this object 1784ff14bae91075eb274eb1c2975982358946e7e63John Grossman void lock() const { mLock.lock(); } 1794ff14bae91075eb274eb1c2975982358946e7e63John Grossman void unlock() const { mLock.unlock(); } 1804ff14bae91075eb274eb1c2975982358946e7e63John Grossman 1814ff14bae91075eb274eb1c2975982358946e7e63John Grossman // tryBeginTrackSwitch/endTrackSwitch are used when the CallbackData is handed over 1824ff14bae91075eb274eb1c2975982358946e7e63John Grossman // to the next sink. 18365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 184799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin // tryBeginTrackSwitch() returns true only if it obtains the lock. 185799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin bool tryBeginTrackSwitch() { 186799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin LOG_ALWAYS_FATAL_IF(mSwitching, "tryBeginTrackSwitch() already called"); 187fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin if (mLock.tryLock() != OK) { 188799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin return false; 189799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin } 190799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin mSwitching = true; 191799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin return true; 192df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block } 193799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin void endTrackSwitch() { 194799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin if (mSwitching) { 195799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin mLock.unlock(); 1962b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten } 197799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin mSwitching = false; 198df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block } 1995a61d2f277af3098fc10b2881babca16391362daDima Zavin private: 200799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin AudioOutput * mData; 201799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin mutable Mutex mLock; // a recursive mutex might make this unnecessary. 20265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian bool mSwitching; 2032b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten DISALLOW_EVIL_CONSTRUCTORS(CallbackData); 20429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block }; 2052b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten 206799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin }; // AudioOutput 207799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 2082b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten 2092b213bc220768d2b984239511cd4554a96bc0079Glenn Kastenpublic: 2102b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten static void instantiate(); 2112b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten 2122b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten // IMediaPlayerService interface 2132b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName); 2144ff14bae91075eb274eb1c2975982358946e7e63John Grossman void removeMediaRecorderClient(wp<MediaRecorderClient> client); 2154ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual sp<IMediaMetadataRetriever> createMetadataRetriever(); 2164ff14bae91075eb274eb1c2975982358946e7e63John Grossman 2174ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, 2184ff14bae91075eb274eb1c2975982358946e7e63John Grossman audio_session_t audioSessionId); 2194ff14bae91075eb274eb1c2975982358946e7e63John Grossman 2204ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual sp<IMediaCodecList> getCodecList() const; 2214ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual sp<IOMX> getOMX(); 2224ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual sp<ICrypto> makeCrypto(); 2234ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual sp<IDrm> makeDrm(); 2244ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual sp<IHDCP> makeHDCP(bool createEncryptionModule); 2254ff14bae91075eb274eb1c2975982358946e7e63John Grossman 2264ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName, 2274ff14bae91075eb274eb1c2975982358946e7e63John Grossman const sp<IRemoteDisplayClient>& client, const String8& iface); 2284ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual status_t dump(int fd, const Vector<String16>& args); 2294ff14bae91075eb274eb1c2975982358946e7e63John Grossman 2304ff14bae91075eb274eb1c2975982358946e7e63John Grossman void removeClient(wp<Client> client); 2314ff14bae91075eb274eb1c2975982358946e7e63John Grossman 2324ff14bae91075eb274eb1c2975982358946e7e63John Grossman // For battery usage tracking purpose 2334ff14bae91075eb274eb1c2975982358946e7e63John Grossman struct BatteryUsageInfo { 2344ff14bae91075eb274eb1c2975982358946e7e63John Grossman // how many streams are being played by one UID 2354ff14bae91075eb274eb1c2975982358946e7e63John Grossman int refCount; 2364ff14bae91075eb274eb1c2975982358946e7e63John Grossman // a temp variable to store the duration(ms) of audio codecs 2374ff14bae91075eb274eb1c2975982358946e7e63John Grossman // when we start a audio codec, we minus the system time from audioLastTime 2384ff14bae91075eb274eb1c2975982358946e7e63John Grossman // when we pause it, we add the system time back to the audioLastTime 2394ff14bae91075eb274eb1c2975982358946e7e63John Grossman // so after the pause, audioLastTime = pause time - start time 240799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin // if multiple audio streams are played (or recorded), then audioLastTime 241799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin // = the total playing time of all the streams 242799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin int32_t audioLastTime; 243799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin // when all the audio streams are being paused, we assign audioLastTime to 244799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin // this variable, so this value could be provided to the battery app 2452b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten // in the next pullBatteryData call 246799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin int32_t audioTotalTime; 2472b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten 248799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin int32_t videoLastTime; 249799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin int32_t videoTotalTime; 2504ff14bae91075eb274eb1c2975982358946e7e63John Grossman }; 2514ff14bae91075eb274eb1c2975982358946e7e63John Grossman KeyedVector<int, BatteryUsageInfo> mBatteryData; 2524ff14bae91075eb274eb1c2975982358946e7e63John Grossman 2534ff14bae91075eb274eb1c2975982358946e7e63John Grossman enum { 2544ff14bae91075eb274eb1c2975982358946e7e63John Grossman SPEAKER, 2554ff14bae91075eb274eb1c2975982358946e7e63John Grossman OTHER_AUDIO_DEVICE, 2564ff14bae91075eb274eb1c2975982358946e7e63John Grossman SPEAKER_AND_OTHER, 2574ff14bae91075eb274eb1c2975982358946e7e63John Grossman NUM_AUDIO_DEVICES 258799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin }; 25965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2604ff14bae91075eb274eb1c2975982358946e7e63John Grossman struct BatteryAudioFlingerUsageInfo { 2614ff14bae91075eb274eb1c2975982358946e7e63John Grossman int refCount; // how many audio streams are being played 2624ff14bae91075eb274eb1c2975982358946e7e63John Grossman int deviceOn[NUM_AUDIO_DEVICES]; // whether the device is currently used 2634ff14bae91075eb274eb1c2975982358946e7e63John Grossman int32_t lastTime[NUM_AUDIO_DEVICES]; // in ms 2644ff14bae91075eb274eb1c2975982358946e7e63John Grossman // totalTime[]: total time of audio output devices usage 2654ff14bae91075eb274eb1c2975982358946e7e63John Grossman int32_t totalTime[NUM_AUDIO_DEVICES]; // in ms 26665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian }; 26765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 26865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // This varialble is used to record the usage of audio output device 26965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // for battery app 270799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin BatteryAudioFlingerUsageInfo mBatteryAudio; 27165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 27265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Collect info of the codec usage from media player and media recorder 27365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual void addBatteryData(uint32_t params); 27465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // API for the Battery app to pull the data of codecs usage 27565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t pullBatteryData(Parcel* reply); 27665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianprivate: 27765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 27865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian class Client : public BnMediaPlayer { 279799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin // IMediaPlayer interface 2802b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten virtual void disconnect(); 2812b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten virtual status_t setVideoSurfaceTexture( 2822b213bc220768d2b984239511cd4554a96bc0079Glenn Kasten const sp<IGraphicBufferProducer>& bufferProducer); 28365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t prepareAsync(); 28465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t start(); 28565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t stop(); 286799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t pause(); 287799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t isPlaying(bool* state); 288799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t setPlaybackSettings(const AudioPlaybackRate& rate); 289799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */); 290799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t setSyncSettings(const AVSyncSettings& rate, float videoFpsHint); 291799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t getSyncSettings(AVSyncSettings* rate /* nonnull */, 292799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin float* videoFps /* nonnull */); 293799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t seekTo(int msec); 294799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t getCurrentPosition(int* msec); 295799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin virtual status_t getDuration(int* msec); 29665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t reset(); 29765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t setAudioStreamType(audio_stream_type_t type); 29865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t setLooping(int loop); 29965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t setVolume(float leftVolume, float rightVolume); 30065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t invoke(const Parcel& request, Parcel *reply); 30165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t setMetadataFilter(const Parcel& filter); 30265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t getMetadata(bool update_only, 30365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian bool apply_filter, 30465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian Parcel *reply); 30577c1119ea0b5cb32287088ceeeb7e3b6bd14a85dGlenn Kasten virtual status_t setAuxEffectSendLevel(float level); 30677c1119ea0b5cb32287088ceeeb7e3b6bd14a85dGlenn Kasten virtual status_t attachAuxEffect(int effectId); 30777c1119ea0b5cb32287088ceeeb7e3b6bd14a85dGlenn Kasten virtual status_t setParameter(int key, const Parcel &request); 30877c1119ea0b5cb32287088ceeeb7e3b6bd14a85dGlenn Kasten virtual status_t getParameter(int key, Parcel *reply); 30965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint); 31065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint); 3113a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen virtual status_t setNextPlayer(const sp<IMediaPlayer>& player); 3123a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 3133a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen sp<MediaPlayerBase> createPlayer(player_type playerType); 3143a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 3153a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen virtual status_t setDataSource( 3163a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen const sp<IMediaHTTPService> &httpService, 3173a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen const char *url, 3183a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen const KeyedVector<String8, String8> *headers); 31965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 32065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t setDataSource(int fd, int64_t offset, int64_t length); 32165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 32265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t setDataSource(const sp<IStreamSource> &source); 32365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual status_t setDataSource(const sp<IDataSource> &source); 32465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 32565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 32665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sp<MediaPlayerBase> setDataSource_pre(player_type playerType); 32765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian void setDataSource_post(const sp<MediaPlayerBase>& p, 32865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian status_t status); 329a4454b4765c5905f14186893b0688be375642283Glenn Kasten 33065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian static void notify(void* cookie, int msg, 3314ff14bae91075eb274eb1c2975982358946e7e63John Grossman int ext1, int ext2, const Parcel *obj); 3324ff14bae91075eb274eb1c2975982358946e7e63John Grossman 3334ff14bae91075eb274eb1c2975982358946e7e63John Grossman pid_t pid() const { return mPid; } 3344ff14bae91075eb274eb1c2975982358946e7e63John Grossman virtual status_t dump(int fd, const Vector<String16>& args); 33565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 33665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian audio_session_t getAudioSessionId() { return mAudioSessionId; } 33765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 33865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian private: 33965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian friend class MediaPlayerService; 34065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian Client( const sp<MediaPlayerService>& service, 34165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian pid_t pid, 34265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t connId, 34365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const sp<IMediaPlayerClient>& client, 34465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian audio_session_t audioSessionId, 34565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uid_t uid); 34665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian Client(); 34765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual ~Client(); 34865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 34965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian void deletePlayer(); 35065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 35165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sp<MediaPlayerBase> getPlayer() const { Mutex::Autolock lock(mLock); return mPlayer; } 35265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 35365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 35465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 35565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // @param type Of the metadata to be tested. 35665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // @return true if the metadata should be dropped according to 35765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // the filters. 35865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian bool shouldDropMetadata(media::Metadata::Type type) const; 35965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 36065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Add a new element to the set of metadata updated. Noop if 36165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // the element exists already. 3627dede876998ff56351d495ec3a798c1b131193e8Glenn Kasten // @param type Of the metadata to be recorded. 36365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian void addNewMetadataUpdate(media::Metadata::Type type); 36465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 36565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Disconnect from the currently connected ANativeWindow. 36665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian void disconnectNativeWindow(); 36765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 36865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian status_t setAudioAttributes_l(const Parcel &request); 36944deb053252a3bd2f57a007ab9560f4924f62394Glenn Kasten 37065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mutable Mutex mLock; 37165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sp<MediaPlayerBase> mPlayer; 37265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sp<MediaPlayerService> mService; 37365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sp<IMediaPlayerClient> mClient; 37465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sp<AudioOutput> mAudioOutput; 37565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian pid_t mPid; 37665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian status_t mStatus; 37765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian bool mLoop; 37865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t mConnId; 37965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian audio_session_t mAudioSessionId; 38065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian audio_attributes_t * mAudioAttributes; 38165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uid_t mUID; 38265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sp<ANativeWindow> mConnectedWindow; 38365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sp<IBinder> mConnectedWindowBinder; 38465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian struct sockaddr_in mRetransmitEndpoint; 38565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian bool mRetransmitEndpointValid; 38665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sp<Client> mNextClient; 38765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 38865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Metadata filters. 38965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian media::Metadata::Filter mMetadataAllow; // protected by mLock 39065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian media::Metadata::Filter mMetadataDrop; // protected by mLock 39165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 39265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Metadata updated. For each MEDIA_INFO_METADATA_UPDATE 39365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // notification we try to update mMetadataUpdated which is a 39465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // set: no duplicate. 39565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // getMetadata clears this set. 39665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian media::Metadata::Filter mMetadataUpdated; // protected by mLock 39765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 39865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if CALLBACK_ANTAGONIZER 39965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian Antagonizer* mAntagonizer; 40065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 40165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian }; // Client 402799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 403799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin// ---------------------------------------------------------------------------- 404799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin 405799a70e7028a4d714436c3a744a775acfbd31aaeDima Zavin MediaPlayerService(); 40665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian virtual ~MediaPlayerService(); 40765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 40865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mutable Mutex mLock; 40965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian SortedVector< wp<Client> > mClients; 41065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian SortedVector< wp<MediaRecorderClient> > mMediaRecorderClients; 41165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t mNextConnId; 41298ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten sp<IOMX> mOMX; 41398ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten sp<ICrypto> mCrypto; 41498ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten}; 41598ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten 41698ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten// ---------------------------------------------------------------------------- 41798ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten 41898ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten}; // namespace android 41998ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten 42098ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten#endif // ANDROID_MEDIAPLAYERSERVICE_H 42198ec94c5854daccc3474758524e7f4adfe535ce0Glenn Kasten