summaryrefslogtreecommitdiffstats
path: root/dom/system/gonk/AudioManager.h
blob: f56eaad6cfb8e2b49e027d6abe6a88a5c5efaf17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef mozilla_dom_system_b2g_audiomanager_h__
#define mozilla_dom_system_b2g_audiomanager_h__

#include "mozilla/HalTypes.h"
#include "mozilla/Observer.h"
#include "mozilla/UniquePtr.h"
#include "nsAutoPtr.h"
#include "nsDataHashtable.h"
#include "nsIAudioManager.h"
#include "nsIObserver.h"
#include "android_audio/AudioSystem.h"

// {b2b51423-502d-4d77-89b3-7786b562b084}
#define NS_AUDIOMANAGER_CID {0x94f6fd70, 0x7615, 0x4af9, \
      {0x89, 0x10, 0xf9, 0x3c, 0x55, 0xe6, 0x62, 0xec}}
#define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"

class nsISettingsServiceLock;

namespace mozilla {
namespace hal {
class SwitchEvent;
typedef Observer<SwitchEvent> SwitchObserver;
} // namespace hal

namespace dom {
namespace gonk {

class VolumeInitCallback;

class AudioManager final : public nsIAudioManager
                         , public nsIObserver
{
public:
  static already_AddRefed<AudioManager> GetInstance();

  NS_DECL_ISUPPORTS
  NS_DECL_NSIAUDIOMANAGER
  NS_DECL_NSIOBSERVER

  // Validate whether the volume index is within the range
  nsresult ValidateVolumeIndex(int32_t aStream, uint32_t aIndex) const;

  // Called when android AudioFlinger in mediaserver is died
  void HandleAudioFlingerDied();

  void HandleHeadphoneSwitchEvent(const hal::SwitchEvent& aEvent);

  class VolumeStreamState {
  public:
    explicit VolumeStreamState(AudioManager& aManager, int32_t aStreamType);
    int32_t GetStreamType()
    {
      return mStreamType;
    }
    bool IsDevicesChanged(bool aFromCache = true);
    void ClearDevicesChanged();
    uint32_t GetLastDevices()
    {
      return mLastDevices;
    }
    bool IsVolumeIndexesChanged();
    void ClearVolumeIndexesChanged();
    void InitStreamVolume();
    uint32_t GetMaxIndex();
    uint32_t GetDefaultIndex();
    uint32_t GetVolumeIndex();
    uint32_t GetVolumeIndex(uint32_t aDevice);
    void ClearCurrentVolumeUpdated();
    // Set volume index to all active devices.
    // Active devices are chosen by android AudioPolicyManager.
    nsresult SetVolumeIndexToActiveDevices(uint32_t aIndex);
    // Set volume index to all alias streams for device. Alias streams have same volume.
    nsresult SetVolumeIndexToAliasStreams(uint32_t aIndex, uint32_t aDevice);
    nsresult SetVolumeIndexToConsistentDeviceIfNeeded(uint32_t aIndex, uint32_t aDevice);
    nsresult SetVolumeIndex(uint32_t aIndex, uint32_t aDevice, bool aUpdateCache = true);
    // Restore volume index to all devices. Called when AudioFlinger is restarted.
    void RestoreVolumeIndexToAllDevices();
  private:
    AudioManager& mManager;
    const int32_t mStreamType;
    uint32_t mLastDevices;
    bool mIsDevicesChanged;
    bool mIsVolumeIndexesChanged;
    nsDataHashtable<nsUint32HashKey, uint32_t> mVolumeIndexes;
  };

protected:
  int32_t mPhoneState;

  bool mIsVolumeInited;

  // A bitwise variable for volume update of audio output devices,
  // clear it after store the value into database.
  uint32_t mAudioOutDevicesUpdated;

  // Connected devices that are controlled by setDeviceConnectionState()
  nsDataHashtable<nsUint32HashKey, nsCString> mConnectedDevices;

  nsDataHashtable<nsUint32HashKey, uint32_t> mAudioDeviceTableIdMaps;

  bool mSwitchDone;

#if defined(MOZ_B2G_BT) || ANDROID_VERSION >= 17
  bool mBluetoothA2dpEnabled;
#endif
#ifdef MOZ_B2G_BT
  bool mA2dpSwitchDone;
#endif
  nsTArray<UniquePtr<VolumeStreamState> > mStreamStates;
  uint32_t mLastChannelVolume[AUDIO_STREAM_CNT];

  bool IsFmOutConnected();

  nsresult SetStreamVolumeForDevice(int32_t aStream,
                                    uint32_t aIndex,
                                    uint32_t aDevice);
  nsresult SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex);
  nsresult GetStreamVolumeIndex(int32_t aStream, uint32_t* aIndex);

  void UpdateCachedActiveDevicesForStreams();
  uint32_t GetDevicesForStream(int32_t aStream, bool aFromCache = true);
  uint32_t GetDeviceForStream(int32_t aStream);
  // Choose one device as representative of active devices.
  static uint32_t SelectDeviceFromDevices(uint32_t aOutDevices);

private:
  nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;

  void HandleBluetoothStatusChanged(nsISupports* aSubject,
                                    const char* aTopic,
                                    const nsCString aAddress);
  void HandleAudioChannelProcessChanged();

  // Append the audio output device to the volume setting string.
  nsAutoCString AppendDeviceToVolumeSetting(const char* aName,
                                            uint32_t aDevice);

  // We store the volume setting in the database, these are related functions.
  void InitVolumeFromDatabase();
  void MaybeUpdateVolumeSettingToDatabase(bool aForce = false);

  // Promise functions.
  void InitDeviceVolumeSucceeded();
  void InitDeviceVolumeFailed(const char* aError);

  void AudioOutDeviceUpdated(uint32_t aDevice);

  void UpdateHeadsetConnectionState(hal::SwitchState aState);
  void UpdateDeviceConnectionState(bool aIsConnected, uint32_t aDevice, const nsCString& aDeviceName);
  void SetAllDeviceConnectionStates();

  AudioManager();
  ~AudioManager();

  friend class VolumeInitCallback;
  friend class VolumeStreamState;
  friend class GonkAudioPortCallback;
};

} /* namespace gonk */
} /* namespace dom */
} /* namespace mozilla */

#endif // mozilla_dom_system_b2g_audiomanager_h__