1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include "Sound.h" 20 21 #include <mutex> 22 #include <unordered_map> 23 24 #include <android-base/thread_annotations.h> 25 26 namespace android { 27 28 class SoundPool; 29 30 // for queued events 31 class SoundPoolEvent { 32 public: 33 explicit SoundPoolEvent(int msg, int arg1 = 0, int arg2 = 0) : mMsg(msg)34 mMsg(msg), mArg1(arg1), mArg2(arg2) {} 35 const int mMsg; // MessageType 36 const int mArg1; // soundID 37 const int mArg2; // status 38 enum MessageType { INVALID, SOUND_LOADED }; 39 }; 40 41 // callback function prototype 42 typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user); 43 44 } // namespace android 45 46 namespace android::soundpool { 47 48 // This class manages Sounds for the SoundPool. 49 class SoundManager { 50 public: 51 SoundManager(); 52 ~SoundManager(); 53 54 // Matches corresponding SoundPool API functions 55 int32_t load(int fd, int64_t offset, int64_t length, int32_t priority); 56 bool unload(int32_t soundID); 57 void setCallback(SoundPool* soundPool, SoundPoolCallback* callback, void* user); 58 void* getUserData() const; 59 60 // SoundPool and SoundDecoder access 61 std::shared_ptr<Sound> findSound(int32_t soundID) const; 62 63 // from the SoundDecoder 64 void notify(SoundPoolEvent event); 65 66 private: 67 68 // CallbackHandler is used to manage notifications back to the app when a sound 69 // has been loaded. It uses a recursive lock to allow setting the callback 70 // during the callback. 71 class CallbackHandler { 72 public: setCallback(SoundPool * soundPool,SoundPoolCallback * callback,void * userData)73 void setCallback(SoundPool *soundPool, SoundPoolCallback* callback, void* userData) 74 { 75 std::lock_guard<std::recursive_mutex> lock(mCallbackLock); 76 mSoundPool = soundPool; 77 mCallback = callback; 78 mUserData = userData; 79 } notify(SoundPoolEvent event)80 void notify(SoundPoolEvent event) const 81 { 82 std::lock_guard<std::recursive_mutex> lock(mCallbackLock); 83 if (mCallback != nullptr) { 84 mCallback(event, mSoundPool, mUserData); 85 // Note: mCallback may call setCallback(). 86 // so mCallback, mUserData may have changed. 87 } 88 } getUserData()89 void* getUserData() const 90 { 91 std::lock_guard<std::recursive_mutex> lock(mCallbackLock); 92 return mUserData; 93 } 94 private: 95 mutable std::recursive_mutex mCallbackLock; // allow mCallback to setCallback(). 96 // No thread-safety checks in R for recursive_mutex. 97 SoundPool* mSoundPool = nullptr; // GUARDED_BY(mCallbackLock) 98 SoundPoolCallback* mCallback = nullptr; // GUARDED_BY(mCallbackLock) 99 void* mUserData = nullptr; // GUARDED_BY(mCallbackLock) 100 }; 101 102 std::shared_ptr<Sound> findSound_l(int32_t soundID) const REQUIRES(mSoundManagerLock); 103 104 // The following variables are initialized in constructor and can be accessed anytime. 105 CallbackHandler mCallbackHandler; // has its own lock 106 const std::unique_ptr<SoundDecoder> mDecoder; // has its own lock 107 108 mutable std::mutex mSoundManagerLock; 109 std::unordered_map<int, std::shared_ptr<Sound>> mSounds GUARDED_BY(mSoundManagerLock); 110 int32_t mNextSoundID GUARDED_BY(mSoundManagerLock) = 0; 111 }; 112 113 } // namespace android::soundpool 114