1 // Copyright 2016 The Android Open Source Project
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 // Implementation of audio_volume_handler.h
17 
18 #include "audio_volume_handler.h"
19 
20 #include <base/files/file.h>
21 #include <base/files/file_util.h>
22 #include <base/logging.h>
23 #include <brillo/map_utils.h>
24 #include <brillo/message_loops/message_loop.h>
25 #include <brillo/strings/string_utils.h>
26 
27 #include "audio_device_handler.h"
28 
29 namespace brillo {
30 
31 static const char kVolumeStateFilePath[] =
32     "/data/misc/brilloaudioservice/volume.dat";
33 
AudioVolumeHandler()34 AudioVolumeHandler::AudioVolumeHandler() {
35   for (auto stream : kSupportedStreams_) {
36     step_sizes_.emplace(stream, kDefaultStepSize_);
37   }
38   selected_stream_ = AUDIO_STREAM_DEFAULT;
39   volume_state_file_ = base::FilePath(kVolumeStateFilePath);
40 }
41 
~AudioVolumeHandler()42 AudioVolumeHandler::~AudioVolumeHandler() {}
43 
APSDisconnect()44 void AudioVolumeHandler::APSDisconnect() { aps_.clear(); }
45 
APSConnect(android::sp<android::IAudioPolicyService> aps)46 void AudioVolumeHandler::APSConnect(
47     android::sp<android::IAudioPolicyService> aps) {
48   aps_ = aps;
49   InitAPSAllStreams();
50 }
51 
RegisterCallback(base::Callback<void (audio_stream_type_t,int,int)> & callback)52 void AudioVolumeHandler::RegisterCallback(
53     base::Callback<void(audio_stream_type_t, int, int)>& callback) {
54   callback_ = callback;
55 }
56 
ConvertToUserDefinedIndex(audio_stream_type_t stream,int index)57 int AudioVolumeHandler::ConvertToUserDefinedIndex(audio_stream_type_t stream,
58                                                   int index) {
59   return index / step_sizes_[stream];
60 }
61 
ConvertToInternalIndex(audio_stream_type_t stream,int index)62 int AudioVolumeHandler::ConvertToInternalIndex(audio_stream_type_t stream,
63                                                int index) {
64   return index * step_sizes_[stream];
65 }
66 
TriggerCallback(audio_stream_type_t stream,int previous_index,int current_index)67 void AudioVolumeHandler::TriggerCallback(audio_stream_type_t stream,
68                                          int previous_index,
69                                          int current_index) {
70   int user_defined_previous_index =
71       ConvertToUserDefinedIndex(stream, previous_index);
72   int user_defined_current_index =
73       ConvertToUserDefinedIndex(stream, current_index);
74   MessageLoop::current()->PostTask(base::Bind(callback_,
75                                               stream,
76                                               user_defined_previous_index,
77                                               user_defined_current_index));
78 }
79 
GenerateVolumeFile()80 void AudioVolumeHandler::GenerateVolumeFile() {
81   for (auto stream : kSupportedStreams_) {
82     for (auto device : AudioDeviceHandler::kSupportedOutputDevices_) {
83       PersistVolumeConfiguration(stream, device, kDefaultCurrentIndex_);
84     }
85   }
86   if (!kv_store_->Save(volume_state_file_)) {
87     LOG(ERROR) << "Could not save volume data file!";
88   }
89 }
90 
GetVolumeMaxSteps(audio_stream_type_t stream)91 int AudioVolumeHandler::GetVolumeMaxSteps(audio_stream_type_t stream) {
92   return ConvertToUserDefinedIndex(stream, kMaxIndex_);
93 }
94 
SetVolumeMaxSteps(audio_stream_type_t stream,int max_steps)95 int AudioVolumeHandler::SetVolumeMaxSteps(audio_stream_type_t stream,
96                                           int max_steps) {
97   if (max_steps <= kMinIndex_ || max_steps > kMaxIndex_)
98     return EINVAL;
99   step_sizes_[stream] = kMaxIndex_ / max_steps;
100   return 0;
101 }
102 
GetVolumeCurrentIndex(audio_stream_type_t stream,audio_devices_t device)103 int AudioVolumeHandler::GetVolumeCurrentIndex(audio_stream_type_t stream,
104                                               audio_devices_t device) {
105   auto key = kCurrentIndexKey_ + "." + string_utils::ToString(stream) + "." +
106              string_utils::ToString(device);
107   std::string value;
108   kv_store_->GetString(key, &value);
109   return std::stoi(value);
110 }
111 
GetVolumeIndex(audio_stream_type_t stream,audio_devices_t device)112 int AudioVolumeHandler::GetVolumeIndex(audio_stream_type_t stream,
113                                        audio_devices_t device) {
114   return ConvertToUserDefinedIndex(stream,
115                                    GetVolumeCurrentIndex(stream, device));
116 }
117 
SetVolumeIndex(audio_stream_type_t stream,audio_devices_t device,int index)118 int AudioVolumeHandler::SetVolumeIndex(audio_stream_type_t stream,
119                                        audio_devices_t device,
120                                        int index) {
121   if (index < kMinIndex_ ||
122       index > ConvertToUserDefinedIndex(stream, kMaxIndex_))
123     return EINVAL;
124   int previous_index = GetVolumeCurrentIndex(stream, device);
125   int current_absolute_index = ConvertToInternalIndex(stream, index);
126   PersistVolumeConfiguration(stream, device, current_absolute_index);
127   TriggerCallback(stream, previous_index, current_absolute_index);
128   return 0;
129 }
130 
PersistVolumeConfiguration(audio_stream_type_t stream,audio_devices_t device,int index)131 void AudioVolumeHandler::PersistVolumeConfiguration(audio_stream_type_t stream,
132                                                     audio_devices_t device,
133                                                     int index) {
134   auto key = kCurrentIndexKey_ + "." + string_utils::ToString(stream) + "." +
135              string_utils::ToString(device);
136   kv_store_->SetString(key, string_utils::ToString(index));
137   kv_store_->Save(volume_state_file_);
138 }
139 
InitAPSAllStreams()140 void AudioVolumeHandler::InitAPSAllStreams() {
141   for (auto stream : kSupportedStreams_) {
142     aps_->initStreamVolume(stream, kMinIndex_, kMaxIndex_);
143     for (auto device : AudioDeviceHandler::kSupportedOutputDevices_) {
144       int current_index = GetVolumeCurrentIndex(stream, device);
145       aps_->setStreamVolumeIndex(stream, current_index, device);
146     }
147   }
148 }
149 
SetVolumeFilePathForTesting(const base::FilePath & path)150 void AudioVolumeHandler::SetVolumeFilePathForTesting(
151     const base::FilePath& path) {
152   volume_state_file_ = path;
153 }
154 
Init(android::sp<android::IAudioPolicyService> aps)155 void AudioVolumeHandler::Init(android::sp<android::IAudioPolicyService> aps) {
156   aps_ = aps;
157   kv_store_ = std::unique_ptr<KeyValueStore>(new KeyValueStore());
158   if (!base::PathExists(volume_state_file_)) {
159     // Generate key-value store and save it to a file.
160     GenerateVolumeFile();
161   } else {
162     // Load the file. If loading fails, generate the file.
163     if (!kv_store_->Load(volume_state_file_)) {
164       LOG(ERROR) << "Could not load volume data file!";
165       GenerateVolumeFile();
166     }
167   }
168   // Inform APS.
169   InitAPSAllStreams();
170 }
171 
GetVolumeControlStream()172 audio_stream_type_t AudioVolumeHandler::GetVolumeControlStream() {
173   return selected_stream_;
174 }
175 
SetVolumeControlStream(audio_stream_type_t stream)176 void AudioVolumeHandler::SetVolumeControlStream(audio_stream_type_t stream) {
177   selected_stream_ = stream;
178 }
179 
GetNewVolumeIndex(int previous_index,int direction,audio_stream_type_t stream)180 int AudioVolumeHandler::GetNewVolumeIndex(int previous_index, int direction,
181                                           audio_stream_type_t stream) {
182   int current_index =
183       previous_index + ConvertToInternalIndex(stream, direction);
184   if (current_index < kMinIndex_) {
185     return kMinIndex_;
186   } else if (current_index > kMaxIndex_) {
187     return kMaxIndex_;
188   } else
189     return current_index;
190 }
191 
AdjustStreamVolume(audio_stream_type_t stream,int direction)192 void AudioVolumeHandler::AdjustStreamVolume(audio_stream_type_t stream,
193                                             int direction) {
194   VLOG(1) << "Adjusting volume of stream " << selected_stream_
195           << " in direction " << direction;
196   auto device = aps_->getDevicesForStream(stream);
197   int previous_index = GetVolumeCurrentIndex(stream, device);
198   int current_index = GetNewVolumeIndex(previous_index, direction, stream);
199   VLOG(1) << "Current index is " << current_index << " for stream " << stream
200           << " and device " << device;
201   aps_->setStreamVolumeIndex(stream, current_index, device);
202   PersistVolumeConfiguration(selected_stream_, device, current_index);
203   TriggerCallback(stream, previous_index, current_index);
204 }
205 
AdjustVolumeActiveStreams(int direction)206 void AudioVolumeHandler::AdjustVolumeActiveStreams(int direction) {
207   if (selected_stream_ != AUDIO_STREAM_DEFAULT) {
208     AdjustStreamVolume(selected_stream_, direction);
209     return;
210   }
211   for (auto stream : kSupportedStreams_) {
212     if (aps_->isStreamActive(stream)) {
213       AdjustStreamVolume(stream, direction);
214       return;
215     }
216   }
217 }
218 
ProcessEvent(const struct input_event & event)219 void AudioVolumeHandler::ProcessEvent(const struct input_event& event) {
220   VLOG(1) << event.type << " " << event.code << " " << event.value;
221   if (event.type == EV_KEY) {
222     switch (event.code) {
223       case KEY_VOLUMEDOWN:
224         AdjustVolumeActiveStreams(-1);
225         break;
226       case KEY_VOLUMEUP:
227         AdjustVolumeActiveStreams(1);
228         break;
229       default:
230         // This event code is not supported by this handler.
231         break;
232     }
233   }
234 }
235 
236 }  // namespace brillo
237