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