1 /* Copyright 2012 Mozilla Foundation and Mozilla contributors
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef mozilla_dom_system_b2g_audiomanager_h__
17 #define mozilla_dom_system_b2g_audiomanager_h__
18 
19 #include "mozilla/HalTypes.h"
20 #include "mozilla/Observer.h"
21 #include "mozilla/UniquePtr.h"
22 #include "nsAutoPtr.h"
23 #include "nsDataHashtable.h"
24 #include "nsIAudioManager.h"
25 #include "nsIObserver.h"
26 #include "android_audio/AudioSystem.h"
27 
28 // {b2b51423-502d-4d77-89b3-7786b562b084}
29 #define NS_AUDIOMANAGER_CID {0x94f6fd70, 0x7615, 0x4af9, \
30       {0x89, 0x10, 0xf9, 0x3c, 0x55, 0xe6, 0x62, 0xec}}
31 #define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"
32 
33 class nsISettingsServiceLock;
34 
35 namespace mozilla {
36 namespace hal {
37 class SwitchEvent;
38 typedef Observer<SwitchEvent> SwitchObserver;
39 } // namespace hal
40 
41 namespace dom {
42 namespace gonk {
43 
44 class VolumeInitCallback;
45 
46 class AudioManager final : public nsIAudioManager
47                          , public nsIObserver
48 {
49 public:
50   static already_AddRefed<AudioManager> GetInstance();
51 
52   NS_DECL_ISUPPORTS
53   NS_DECL_NSIAUDIOMANAGER
54   NS_DECL_NSIOBSERVER
55 
56   // Validate whether the volume index is within the range
57   nsresult ValidateVolumeIndex(int32_t aStream, uint32_t aIndex) const;
58 
59   // Called when android AudioFlinger in mediaserver is died
60   void HandleAudioFlingerDied();
61 
62   void HandleHeadphoneSwitchEvent(const hal::SwitchEvent& aEvent);
63 
64   class VolumeStreamState {
65   public:
66     explicit VolumeStreamState(AudioManager& aManager, int32_t aStreamType);
GetStreamType()67     int32_t GetStreamType()
68     {
69       return mStreamType;
70     }
71     bool IsDevicesChanged(bool aFromCache = true);
72     void ClearDevicesChanged();
GetLastDevices()73     uint32_t GetLastDevices()
74     {
75       return mLastDevices;
76     }
77     bool IsVolumeIndexesChanged();
78     void ClearVolumeIndexesChanged();
79     void InitStreamVolume();
80     uint32_t GetMaxIndex();
81     uint32_t GetDefaultIndex();
82     uint32_t GetVolumeIndex();
83     uint32_t GetVolumeIndex(uint32_t aDevice);
84     void ClearCurrentVolumeUpdated();
85     // Set volume index to all active devices.
86     // Active devices are chosen by android AudioPolicyManager.
87     nsresult SetVolumeIndexToActiveDevices(uint32_t aIndex);
88     // Set volume index to all alias streams for device. Alias streams have same volume.
89     nsresult SetVolumeIndexToAliasStreams(uint32_t aIndex, uint32_t aDevice);
90     nsresult SetVolumeIndexToConsistentDeviceIfNeeded(uint32_t aIndex, uint32_t aDevice);
91     nsresult SetVolumeIndex(uint32_t aIndex, uint32_t aDevice, bool aUpdateCache = true);
92     // Restore volume index to all devices. Called when AudioFlinger is restarted.
93     void RestoreVolumeIndexToAllDevices();
94   private:
95     AudioManager& mManager;
96     const int32_t mStreamType;
97     uint32_t mLastDevices;
98     bool mIsDevicesChanged;
99     bool mIsVolumeIndexesChanged;
100     nsDataHashtable<nsUint32HashKey, uint32_t> mVolumeIndexes;
101   };
102 
103 protected:
104   int32_t mPhoneState;
105 
106   bool mIsVolumeInited;
107 
108   // A bitwise variable for volume update of audio output devices,
109   // clear it after store the value into database.
110   uint32_t mAudioOutDevicesUpdated;
111 
112   // Connected devices that are controlled by setDeviceConnectionState()
113   nsDataHashtable<nsUint32HashKey, nsCString> mConnectedDevices;
114 
115   nsDataHashtable<nsUint32HashKey, uint32_t> mAudioDeviceTableIdMaps;
116 
117   bool mSwitchDone;
118 
119 #if defined(MOZ_B2G_BT) || ANDROID_VERSION >= 17
120   bool mBluetoothA2dpEnabled;
121 #endif
122 #ifdef MOZ_B2G_BT
123   bool mA2dpSwitchDone;
124 #endif
125   nsTArray<UniquePtr<VolumeStreamState> > mStreamStates;
126   uint32_t mLastChannelVolume[AUDIO_STREAM_CNT];
127 
128   bool IsFmOutConnected();
129 
130   nsresult SetStreamVolumeForDevice(int32_t aStream,
131                                     uint32_t aIndex,
132                                     uint32_t aDevice);
133   nsresult SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex);
134   nsresult GetStreamVolumeIndex(int32_t aStream, uint32_t* aIndex);
135 
136   void UpdateCachedActiveDevicesForStreams();
137   uint32_t GetDevicesForStream(int32_t aStream, bool aFromCache = true);
138   uint32_t GetDeviceForStream(int32_t aStream);
139   // Choose one device as representative of active devices.
140   static uint32_t SelectDeviceFromDevices(uint32_t aOutDevices);
141 
142 private:
143   nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
144 
145   void HandleBluetoothStatusChanged(nsISupports* aSubject,
146                                     const char* aTopic,
147                                     const nsCString aAddress);
148   void HandleAudioChannelProcessChanged();
149 
150   // Append the audio output device to the volume setting string.
151   nsAutoCString AppendDeviceToVolumeSetting(const char* aName,
152                                             uint32_t aDevice);
153 
154   // We store the volume setting in the database, these are related functions.
155   void InitVolumeFromDatabase();
156   void MaybeUpdateVolumeSettingToDatabase(bool aForce = false);
157 
158   // Promise functions.
159   void InitDeviceVolumeSucceeded();
160   void InitDeviceVolumeFailed(const char* aError);
161 
162   void AudioOutDeviceUpdated(uint32_t aDevice);
163 
164   void UpdateHeadsetConnectionState(hal::SwitchState aState);
165   void UpdateDeviceConnectionState(bool aIsConnected, uint32_t aDevice, const nsCString& aDeviceName);
166   void SetAllDeviceConnectionStates();
167 
168   AudioManager();
169   ~AudioManager();
170 
171   friend class VolumeInitCallback;
172   friend class VolumeStreamState;
173   friend class GonkAudioPortCallback;
174 };
175 
176 } /* namespace gonk */
177 } /* namespace dom */
178 } /* namespace mozilla */
179 
180 #endif // mozilla_dom_system_b2g_audiomanager_h__
181