You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
8.1 KiB
236 lines
8.1 KiB
// Copyright 2016 The Android Open Source Project |
|
// |
|
// 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. |
|
// |
|
|
|
// Implementation of audio_volume_handler.h |
|
|
|
#include "audio_volume_handler.h" |
|
|
|
#include <base/files/file.h> |
|
#include <base/files/file_util.h> |
|
#include <base/logging.h> |
|
#include <brillo/map_utils.h> |
|
#include <brillo/message_loops/message_loop.h> |
|
#include <brillo/strings/string_utils.h> |
|
|
|
#include "audio_device_handler.h" |
|
|
|
namespace brillo { |
|
|
|
static const char kVolumeStateFilePath[] = |
|
"/data/misc/brilloaudioservice/volume.dat"; |
|
|
|
AudioVolumeHandler::AudioVolumeHandler() { |
|
for (auto stream : kSupportedStreams_) { |
|
step_sizes_.emplace(stream, kDefaultStepSize_); |
|
} |
|
selected_stream_ = AUDIO_STREAM_DEFAULT; |
|
volume_state_file_ = base::FilePath(kVolumeStateFilePath); |
|
} |
|
|
|
AudioVolumeHandler::~AudioVolumeHandler() {} |
|
|
|
void AudioVolumeHandler::APSDisconnect() { aps_.clear(); } |
|
|
|
void AudioVolumeHandler::APSConnect( |
|
android::sp<android::IAudioPolicyService> aps) { |
|
aps_ = aps; |
|
InitAPSAllStreams(); |
|
} |
|
|
|
void AudioVolumeHandler::RegisterCallback( |
|
base::Callback<void(audio_stream_type_t, int, int)>& callback) { |
|
callback_ = callback; |
|
} |
|
|
|
int AudioVolumeHandler::ConvertToUserDefinedIndex(audio_stream_type_t stream, |
|
int index) { |
|
return index / step_sizes_[stream]; |
|
} |
|
|
|
int AudioVolumeHandler::ConvertToInternalIndex(audio_stream_type_t stream, |
|
int index) { |
|
return index * step_sizes_[stream]; |
|
} |
|
|
|
void AudioVolumeHandler::TriggerCallback(audio_stream_type_t stream, |
|
int previous_index, |
|
int current_index) { |
|
int user_defined_previous_index = |
|
ConvertToUserDefinedIndex(stream, previous_index); |
|
int user_defined_current_index = |
|
ConvertToUserDefinedIndex(stream, current_index); |
|
MessageLoop::current()->PostTask(base::Bind(callback_, |
|
stream, |
|
user_defined_previous_index, |
|
user_defined_current_index)); |
|
} |
|
|
|
void AudioVolumeHandler::GenerateVolumeFile() { |
|
for (auto stream : kSupportedStreams_) { |
|
for (auto device : AudioDeviceHandler::kSupportedOutputDevices_) { |
|
PersistVolumeConfiguration(stream, device, kDefaultCurrentIndex_); |
|
} |
|
} |
|
if (!kv_store_->Save(volume_state_file_)) { |
|
LOG(ERROR) << "Could not save volume data file!"; |
|
} |
|
} |
|
|
|
int AudioVolumeHandler::GetVolumeMaxSteps(audio_stream_type_t stream) { |
|
return ConvertToUserDefinedIndex(stream, kMaxIndex_); |
|
} |
|
|
|
int AudioVolumeHandler::SetVolumeMaxSteps(audio_stream_type_t stream, |
|
int max_steps) { |
|
if (max_steps <= kMinIndex_ || max_steps > kMaxIndex_) |
|
return EINVAL; |
|
step_sizes_[stream] = kMaxIndex_ / max_steps; |
|
return 0; |
|
} |
|
|
|
int AudioVolumeHandler::GetVolumeCurrentIndex(audio_stream_type_t stream, |
|
audio_devices_t device) { |
|
auto key = kCurrentIndexKey_ + "." + string_utils::ToString(stream) + "." + |
|
string_utils::ToString(device); |
|
std::string value; |
|
kv_store_->GetString(key, &value); |
|
return std::stoi(value); |
|
} |
|
|
|
int AudioVolumeHandler::GetVolumeIndex(audio_stream_type_t stream, |
|
audio_devices_t device) { |
|
return ConvertToUserDefinedIndex(stream, |
|
GetVolumeCurrentIndex(stream, device)); |
|
} |
|
|
|
int AudioVolumeHandler::SetVolumeIndex(audio_stream_type_t stream, |
|
audio_devices_t device, |
|
int index) { |
|
if (index < kMinIndex_ || |
|
index > ConvertToUserDefinedIndex(stream, kMaxIndex_)) |
|
return EINVAL; |
|
int previous_index = GetVolumeCurrentIndex(stream, device); |
|
int current_absolute_index = ConvertToInternalIndex(stream, index); |
|
PersistVolumeConfiguration(stream, device, current_absolute_index); |
|
TriggerCallback(stream, previous_index, current_absolute_index); |
|
return 0; |
|
} |
|
|
|
void AudioVolumeHandler::PersistVolumeConfiguration(audio_stream_type_t stream, |
|
audio_devices_t device, |
|
int index) { |
|
auto key = kCurrentIndexKey_ + "." + string_utils::ToString(stream) + "." + |
|
string_utils::ToString(device); |
|
kv_store_->SetString(key, string_utils::ToString(index)); |
|
kv_store_->Save(volume_state_file_); |
|
} |
|
|
|
void AudioVolumeHandler::InitAPSAllStreams() { |
|
for (auto stream : kSupportedStreams_) { |
|
aps_->initStreamVolume(stream, kMinIndex_, kMaxIndex_); |
|
for (auto device : AudioDeviceHandler::kSupportedOutputDevices_) { |
|
int current_index = GetVolumeCurrentIndex(stream, device); |
|
aps_->setStreamVolumeIndex(stream, current_index, device); |
|
} |
|
} |
|
} |
|
|
|
void AudioVolumeHandler::SetVolumeFilePathForTesting( |
|
const base::FilePath& path) { |
|
volume_state_file_ = path; |
|
} |
|
|
|
void AudioVolumeHandler::Init(android::sp<android::IAudioPolicyService> aps) { |
|
aps_ = aps; |
|
kv_store_ = std::unique_ptr<KeyValueStore>(new KeyValueStore()); |
|
if (!base::PathExists(volume_state_file_)) { |
|
// Generate key-value store and save it to a file. |
|
GenerateVolumeFile(); |
|
} else { |
|
// Load the file. If loading fails, generate the file. |
|
if (!kv_store_->Load(volume_state_file_)) { |
|
LOG(ERROR) << "Could not load volume data file!"; |
|
GenerateVolumeFile(); |
|
} |
|
} |
|
// Inform APS. |
|
InitAPSAllStreams(); |
|
} |
|
|
|
audio_stream_type_t AudioVolumeHandler::GetVolumeControlStream() { |
|
return selected_stream_; |
|
} |
|
|
|
void AudioVolumeHandler::SetVolumeControlStream(audio_stream_type_t stream) { |
|
selected_stream_ = stream; |
|
} |
|
|
|
int AudioVolumeHandler::GetNewVolumeIndex(int previous_index, int direction, |
|
audio_stream_type_t stream) { |
|
int current_index = |
|
previous_index + ConvertToInternalIndex(stream, direction); |
|
if (current_index < kMinIndex_) { |
|
return kMinIndex_; |
|
} else if (current_index > kMaxIndex_) { |
|
return kMaxIndex_; |
|
} else |
|
return current_index; |
|
} |
|
|
|
void AudioVolumeHandler::AdjustStreamVolume(audio_stream_type_t stream, |
|
int direction) { |
|
VLOG(1) << "Adjusting volume of stream " << selected_stream_ |
|
<< " in direction " << direction; |
|
auto device = aps_->getDevicesForStream(stream); |
|
int previous_index = GetVolumeCurrentIndex(stream, device); |
|
int current_index = GetNewVolumeIndex(previous_index, direction, stream); |
|
VLOG(1) << "Current index is " << current_index << " for stream " << stream |
|
<< " and device " << device; |
|
aps_->setStreamVolumeIndex(stream, current_index, device); |
|
PersistVolumeConfiguration(selected_stream_, device, current_index); |
|
TriggerCallback(stream, previous_index, current_index); |
|
} |
|
|
|
void AudioVolumeHandler::AdjustVolumeActiveStreams(int direction) { |
|
if (selected_stream_ != AUDIO_STREAM_DEFAULT) { |
|
AdjustStreamVolume(selected_stream_, direction); |
|
return; |
|
} |
|
for (auto stream : kSupportedStreams_) { |
|
if (aps_->isStreamActive(stream)) { |
|
AdjustStreamVolume(stream, direction); |
|
return; |
|
} |
|
} |
|
} |
|
|
|
void AudioVolumeHandler::ProcessEvent(const struct input_event& event) { |
|
VLOG(1) << event.type << " " << event.code << " " << event.value; |
|
if (event.type == EV_KEY) { |
|
switch (event.code) { |
|
case KEY_VOLUMEDOWN: |
|
AdjustVolumeActiveStreams(-1); |
|
break; |
|
case KEY_VOLUMEUP: |
|
AdjustVolumeActiveStreams(1); |
|
break; |
|
default: |
|
// This event code is not supported by this handler. |
|
break; |
|
} |
|
} |
|
} |
|
|
|
} // namespace brillo
|
|
|