1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROMEOS_AUDIO_CRAS_AUDIO_HANDLER_H_
6 #define CHROMEOS_AUDIO_CRAS_AUDIO_HANDLER_H_
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/observer_list.h"
14 #include "base/timer/timer.h"
15 #include "chromeos/audio/audio_device.h"
16 #include "chromeos/audio/audio_pref_observer.h"
17 #include "chromeos/dbus/audio_node.h"
18 #include "chromeos/dbus/cras_audio_client.h"
19 #include "chromeos/dbus/session_manager_client.h"
20 #include "chromeos/dbus/volume_state.h"
22 class PrefRegistrySimple
;
27 class AudioDevicesPrefHandler
;
29 class CHROMEOS_EXPORT CrasAudioHandler
: public CrasAudioClient::Observer
,
30 public AudioPrefObserver
,
31 public SessionManagerClient::Observer
{
33 typedef std::priority_queue
<AudioDevice
,
34 std::vector
<AudioDevice
>,
35 AudioDeviceCompare
> AudioDevicePriorityQueue
;
36 typedef std::vector
<uint64_t> NodeIdList
;
40 // Called when an active output volume changed.
41 virtual void OnOutputNodeVolumeChanged(uint64_t node_id
, int volume
);
43 // Called when output mute state changed.
44 virtual void OnOutputMuteChanged(bool mute_on
);
46 // Called when active input node's gain changed.
47 virtual void OnInputNodeGainChanged(uint64_t node_id
, int gain
);
49 // Called when input mute state changed.
50 virtual void OnInputMuteChanged(bool mute_on
);
52 // Called when audio nodes changed.
53 virtual void OnAudioNodesChanged();
55 // Called when active audio node changed.
56 virtual void OnActiveOutputNodeChanged();
58 // Called when active audio input node changed.
59 virtual void OnActiveInputNodeChanged();
63 virtual ~AudioObserver();
64 DISALLOW_COPY_AND_ASSIGN(AudioObserver
);
67 // Sets the global instance. Must be called before any calls to Get().
68 static void Initialize(
69 scoped_refptr
<AudioDevicesPrefHandler
> audio_pref_handler
);
71 // Sets the global instance for testing.
72 static void InitializeForTesting();
74 // Destroys the global instance.
75 static void Shutdown();
77 // Returns true if the global instance is initialized.
78 static bool IsInitialized();
80 // Gets the global instance. Initialize must be called first.
81 static CrasAudioHandler
* Get();
83 // Adds an audio observer.
84 virtual void AddAudioObserver(AudioObserver
* observer
);
86 // Removes an audio observer.
87 virtual void RemoveAudioObserver(AudioObserver
* observer
);
89 // Returns true if keyboard mic exists.
90 virtual bool HasKeyboardMic();
92 // Returns true if audio output is muted for the system.
93 virtual bool IsOutputMuted();
95 // Returns true if audio output is muted for a device.
96 virtual bool IsOutputMutedForDevice(uint64_t device_id
);
98 // Returns true if audio input is muted.
99 virtual bool IsInputMuted();
101 // Returns true if audio input is muted for a device.
102 virtual bool IsInputMutedForDevice(uint64_t device_id
);
104 // Returns true if the output volume is below the default mute volume level.
105 virtual bool IsOutputVolumeBelowDefaultMuteLevel();
107 // Returns volume level in 0-100% range at which the volume should be muted.
108 virtual int GetOutputDefaultVolumeMuteThreshold();
110 // Gets volume level in 0-100% range (0 being pure silence) for the current
112 virtual int GetOutputVolumePercent();
114 // Gets volume level in 0-100% range (0 being pure silence) for a device.
115 virtual int GetOutputVolumePercentForDevice(uint64_t device_id
);
117 // Gets gain level in 0-100% range (0 being pure silence) for the current
119 virtual int GetInputGainPercent();
121 // Gets volume level in 0-100% range (0 being pure silence) for a device.
122 virtual int GetInputGainPercentForDevice(uint64_t device_id
);
124 // Returns node_id of the primary active output node.
125 virtual uint64_t GetPrimaryActiveOutputNode() const;
127 // Returns the node_id of the primary active input node.
128 virtual uint64_t GetPrimaryActiveInputNode() const;
130 // Gets the audio devices back in |device_list|.
131 // This call can be invoked from I/O thread or UI thread because
132 // it does not need to access CrasAudioClient on DBus.
133 virtual void GetAudioDevices(AudioDeviceList
* device_list
) const;
135 virtual bool GetPrimaryActiveOutputDevice(AudioDevice
* device
) const;
137 // Whether there is alternative input/output audio device.
138 virtual bool has_alternative_input() const;
139 virtual bool has_alternative_output() const;
141 // Sets all active output devices' volume level to |volume_percent|, whose
142 // range is from 0-100%.
143 virtual void SetOutputVolumePercent(int volume_percent
);
145 // Sets all active input devices' gain level to |gain_percent|, whose range is
147 virtual void SetInputGainPercent(int gain_percent
);
149 // Adjusts all active output devices' volume up (positive percentage) or down
150 // (negative percentage).
151 virtual void AdjustOutputVolumeByPercent(int adjust_by_percent
);
153 // Adjusts all active output devices' volume to a minimum audible level if it
155 virtual void AdjustOutputVolumeToAudibleLevel();
157 // Mutes or unmutes audio output device.
158 virtual void SetOutputMute(bool mute_on
);
160 // Mutes or unmutes audio input device.
161 virtual void SetInputMute(bool mute_on
);
163 // Switches active audio device to |device|.
164 virtual void SwitchToDevice(const AudioDevice
& device
, bool notify
);
166 // Sets volume/gain level for a device.
167 virtual void SetVolumeGainPercentForDevice(uint64_t device_id
, int value
);
169 // Sets the mute for device.
170 virtual void SetMuteForDevice(uint64_t device_id
, bool mute_on
);
172 // Activates or deactivates keyboard mic if there's one.
173 virtual void SetKeyboardMicActive(bool active
);
175 // Changes the active nodes to the nodes specified by |new_active_ids|.
176 // The caller can pass in the "complete" active node list of either input
177 // nodes, or output nodes, or both. If only input nodes are passed in,
178 // it will only change the input nodes' active status, output nodes will NOT
179 // be changed; similarly for the case if only output nodes are passed.
180 // If the nodes specified in |new_active_ids| are already active, they will
181 // remain active. Otherwise, the old active nodes will be de-activated before
182 // we activate the new nodes with the same type(input/output).
183 virtual void ChangeActiveNodes(const NodeIdList
& new_active_ids
);
185 // Swaps the left and right channel of the internal speaker.
186 // Swap the left and right channel if |swap| is true; otherwise, swap the left
187 // and right channel back to the normal mode.
188 // If the feature is not supported on the device, nothing happens.
189 virtual void SwapInternalSpeakerLeftRightChannel(bool swap
);
191 // Enables error logging.
192 virtual void LogErrors();
194 // If necessary, sets the starting point for re-discovering the active HDMI
195 // output device caused by device entering/exiting docking mode, HDMI display
196 // changing resolution, or chromeos device suspend/resume. If
197 // |force_rediscovering| is true, it will force to set the starting point for
198 // re-discovering the active HDMI output device again if it has been in the
199 // middle of rediscovering the HDMI active output device.
200 virtual void SetActiveHDMIOutoutRediscoveringIfNecessary(
201 bool force_rediscovering
);
204 explicit CrasAudioHandler(
205 scoped_refptr
<AudioDevicesPrefHandler
> audio_pref_handler
);
206 ~CrasAudioHandler() override
;
209 friend class CrasAudioHandlerTest
;
211 // CrasAudioClient::Observer overrides.
212 void AudioClientRestarted() override
;
213 void NodesChanged() override
;
214 void ActiveOutputNodeChanged(uint64_t node_id
) override
;
215 void ActiveInputNodeChanged(uint64_t node_id
) override
;
217 // AudioPrefObserver overrides.
218 void OnAudioPolicyPrefChanged() override
;
220 // SessionManagerClient::Observer overrides.
221 void EmitLoginPromptVisibleCalled() override
;
223 // Sets the active audio output/input node to the node with |node_id|.
224 // If |notify|, notifies Active*NodeChange.
225 void SetActiveOutputNode(uint64_t node_id
, bool notify
);
226 void SetActiveInputNode(uint64_t node_id
, bool notify
);
228 // Sets up the audio device state based on audio policy and audio settings
230 void SetupAudioInputState();
231 void SetupAudioOutputState();
233 // Sets up the additional active audio node's state.
234 void SetupAdditionalActiveAudioNodeState(uint64_t node_id
);
236 const AudioDevice
* GetDeviceFromId(uint64_t device_id
) const;
237 const AudioDevice
* GetKeyboardMic() const;
239 // Initializes audio state, which should only be called when CrasAudioHandler
240 // is created or cras audio client is restarted.
241 void InitializeAudioState();
243 // Applies the audio muting policies whenever the user logs in or policy
244 // change notification is received.
245 void ApplyAudioPolicy();
247 // Sets output volume of |node_id| to |volume|.
248 void SetOutputNodeVolume(uint64_t node_id
, int volume
);
250 void SetOutputNodeVolumePercent(uint64_t node_id
, int volume_percent
);
252 // Sets output mute state to |mute_on| internally, returns true if output mute
254 bool SetOutputMuteInternal(bool mute_on
);
256 // Sets input gain of |node_id| to |gain|.
257 void SetInputNodeGain(uint64_t node_id
, int gain
);
259 void SetInputNodeGainPercent(uint64_t node_id
, int gain_percent
);
261 // Sets input mute state to |mute_on| internally.
262 void SetInputMuteInternal(bool mute_on
);
264 // Calling dbus to get nodes data.
267 // Updates the current audio nodes list and switches the active device
269 void UpdateDevicesAndSwitchActive(const AudioNodeList
& nodes
);
271 // Returns true if *|current_active_node_id| device is changed to
272 // |new_active_device|.
273 bool ChangeActiveDevice(const AudioDevice
& new_active_device
,
274 uint64_t* current_active_node_id
);
276 // Returns true if the audio nodes change is caused by some non-active
277 // audio nodes unplugged.
278 bool NonActiveDeviceUnplugged(size_t old_devices_size
,
279 size_t new_device_size
,
280 uint64_t current_active_node
);
282 // Returns true if there is any device change for for input or output,
283 // specified by |is_input|.
284 // The new discovered nodes are returned in |new_discovered|.
285 bool HasDeviceChange(const AudioNodeList
& new_nodes
,
287 AudioNodeList
* new_discovered
);
289 // Handles dbus callback for GetNodes.
290 void HandleGetNodes(const chromeos::AudioNodeList
& node_list
, bool success
);
292 // Handles the dbus error callback.
293 void HandleGetNodesError(const std::string
& error_name
,
294 const std::string
& error_msg
);
296 // Adds an active node.
297 // If there is no active node, |node_id| will be switched to become the
298 // primary active node. Otherwise, it will be added as an additional active
300 void AddActiveNode(uint64_t node_id
, bool notify
);
302 // Adds |node_id| into additional active nodes.
303 void AddAdditionalActiveNode(uint64_t node_id
, bool notify
);
305 // Removes |node_id| from additional active nodes.
306 void RemoveActiveNodeInternal(uint64_t node_id
, bool notify
);
308 void UpdateAudioAfterHDMIRediscoverGracePeriod();
310 bool IsHDMIPrimaryOutputDevice() const;
312 void StartHDMIRediscoverGracePeriod();
314 bool hdmi_rediscovering() const { return hdmi_rediscovering_
; }
316 void SetHDMIRediscoverGracePeriodForTesting(int duration_in_ms
);
324 // Checks if |device| is a newly discovered, changed, or existing device for
325 // the nodes sent from NodesChanged signal.
326 DeviceStatus
CheckDeviceStatus(const AudioDevice
& device
);
328 void NotifyActiveNodeChanged(bool is_input
);
330 scoped_refptr
<AudioDevicesPrefHandler
> audio_pref_handler_
;
331 base::ObserverList
<AudioObserver
> observers_
;
333 // Audio data and state.
334 AudioDeviceMap audio_devices_
;
336 AudioDevicePriorityQueue input_devices_pq_
;
337 AudioDevicePriorityQueue output_devices_pq_
;
339 bool output_mute_on_
;
343 uint64_t active_output_node_id_
;
344 uint64_t active_input_node_id_
;
345 bool has_alternative_input_
;
346 bool has_alternative_output_
;
348 bool output_mute_locked_
;
350 // Failures are not logged at startup, since CRAS may not be running yet.
353 // Timer for HDMI re-discovering grace period.
354 base::OneShotTimer
<CrasAudioHandler
> hdmi_rediscover_timer_
;
355 int hdmi_rediscover_grace_period_duration_in_ms_
;
356 bool hdmi_rediscovering_
;
358 base::WeakPtrFactory
<CrasAudioHandler
> weak_ptr_factory_
;
360 DISALLOW_COPY_AND_ASSIGN(CrasAudioHandler
);
363 } // namespace chromeos
365 #endif // CHROMEOS_AUDIO_CRAS_AUDIO_HANDLER_H_