Merge \"Camera: document expected timestamp source\" into nyc-dev
am: 8a22c41bf5
Change-Id: Iebce5b3330a010356892b68ed22b82e100fe9012
diff --git a/audio_utils/Android.mk b/audio_utils/Android.mk
index e3b63f5..32c94e2 100644
--- a/audio_utils/Android.mk
+++ b/audio_utils/Android.mk
@@ -18,6 +18,7 @@
roundup.c \
echo_reference.c
+LOCAL_CFLAGS := -Wno-unused-parameter
LOCAL_C_INCLUDES += $(call include-path-for, speex)
LOCAL_C_INCLUDES += \
$(call include-path-for, speex) \
@@ -91,6 +92,7 @@
primitives.c \
roundup.c
+LOCAL_CFLAGS := -Wno-unused-parameter
LOCAL_C_INCLUDES += \
$(call include-path-for, audio-utils)
diff --git a/audio_utils/channels.c b/audio_utils/channels.c
index 0a80ede..fa005d3 100644
--- a/audio_utils/channels.c
+++ b/audio_utils/channels.c
@@ -67,23 +67,23 @@
*/
#define EXPAND_CHANNELS(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes, zero) \
{ \
- size_t num_in_samples = num_in_bytes / sizeof(*in_buff); \
- size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
- typeof(out_buff) dst_ptr = out_buff + num_out_samples - 1; \
+ size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
+ size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
+ typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \
size_t src_index; \
- typeof(in_buff) src_ptr = in_buff + num_in_samples - 1; \
- size_t num_zero_chans = out_buff_chans - in_buff_chans; \
- for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \
+ typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \
+ size_t num_zero_chans = (out_buff_chans) - (in_buff_chans); \
+ for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
size_t dst_offset; \
for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) { \
*dst_ptr-- = zero; \
} \
- for (; dst_offset < out_buff_chans; dst_offset++) { \
+ for (; dst_offset < (out_buff_chans); dst_offset++) { \
*dst_ptr-- = *src_ptr--; \
} \
} \
/* return number of *bytes* generated */ \
- return num_out_samples * sizeof(*out_buff); \
+ return num_out_samples * sizeof(*(out_buff)); \
}
/* Channel expands from a MONO input buffer to a MULTICHANNEL output buffer by duplicating the
@@ -98,24 +98,24 @@
*/
#define EXPAND_MONO_TO_MULTI(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes, zero) \
{ \
- size_t num_in_samples = num_in_bytes / sizeof(*in_buff); \
- size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
- typeof(out_buff) dst_ptr = out_buff + num_out_samples - 1; \
+ size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
+ size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
+ typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \
size_t src_index; \
- typeof(in_buff) src_ptr = in_buff + num_in_samples - 1; \
- size_t num_zero_chans = out_buff_chans - in_buff_chans - 1; \
- for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \
+ typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \
+ size_t num_zero_chans = (out_buff_chans) - (in_buff_chans) - 1; \
+ for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
size_t dst_offset; \
for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) { \
*dst_ptr-- = zero; \
} \
- for (; dst_offset < out_buff_chans; dst_offset++) { \
+ for (; dst_offset < (out_buff_chans); dst_offset++) { \
*dst_ptr-- = *src_ptr; \
} \
src_ptr--; \
} \
/* return number of *bytes* generated */ \
- return num_out_samples * sizeof(*out_buff); \
+ return num_out_samples * sizeof(*(out_buff)); \
}
/* Channel contracts (removes from audio frame end) from an input buffer to an output buffer.
@@ -127,21 +127,21 @@
*/
#define CONTRACT_CHANNELS(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes) \
{ \
- size_t num_in_samples = num_in_bytes / sizeof(*in_buff); \
- size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
- size_t num_skip_samples = in_buff_chans - out_buff_chans; \
+ size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
+ size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
+ size_t num_skip_samples = (in_buff_chans) - (out_buff_chans); \
typeof(out_buff) dst_ptr = out_buff; \
typeof(in_buff) src_ptr = in_buff; \
size_t src_index; \
- for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \
+ for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
size_t dst_offset; \
- for (dst_offset = 0; dst_offset < out_buff_chans; dst_offset++) { \
+ for (dst_offset = 0; dst_offset < (out_buff_chans); dst_offset++) { \
*dst_ptr++ = *src_ptr++; \
} \
src_ptr += num_skip_samples; \
} \
/* return number of *bytes* generated */ \
- return num_out_samples * sizeof(*out_buff); \
+ return num_out_samples * sizeof(*(out_buff)); \
}
/* Channel contracts from a MULTICHANNEL input buffer to a MONO output buffer by mixing the
@@ -158,7 +158,7 @@
*/
#define CONTRACT_TO_MONO(in_buff, out_buff, num_in_bytes) \
{ \
- size_t num_in_samples = num_in_bytes / sizeof(*in_buff); \
+ size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
size_t num_skip_samples = in_buff_chans - 2; \
typeof(out_buff) dst_ptr = out_buff; \
@@ -176,7 +176,7 @@
src_ptr += num_skip_samples; \
} \
/* return number of *bytes* generated */ \
- return num_out_samples * sizeof(*out_buff); \
+ return num_out_samples * sizeof(*(out_buff)); \
}
/* Channel contracts from a MULTICHANNEL uint8x3_t input buffer to a MONO uint8x3_t output buffer
@@ -191,7 +191,7 @@
*/
#define CONTRACT_TO_MONO_24(in_buff, out_buff, num_in_bytes) \
{ \
- size_t num_in_samples = num_in_bytes / sizeof(*in_buff); \
+ size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
size_t num_skip_samples = in_buff_chans - 2; \
typeof(out_buff) dst_ptr = out_buff; \
@@ -205,7 +205,7 @@
src_ptr += num_skip_samples; \
} \
/* return number of *bytes* generated */ \
- return num_out_samples * sizeof(*out_buff); \
+ return num_out_samples * sizeof(*(out_buff)); \
}
/*
diff --git a/audio_utils/echo_reference.c b/audio_utils/echo_reference.c
index 178b306..a822519 100644
--- a/audio_utils/echo_reference.c
+++ b/audio_utils/echo_reference.c
@@ -332,9 +332,7 @@
uint32_t timeoutMs = (uint32_t)((1000 * buffer->frame_count) / er->rd_sampling_rate / 2);
struct timespec ts = {0, 0};
-#ifndef HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
clock_gettime(CLOCK_REALTIME, &ts);
-#endif
ts.tv_sec += timeoutMs/1000;
ts.tv_nsec += (timeoutMs%1000) * 1000000;
@@ -343,11 +341,7 @@
ts.tv_sec += 1;
}
-#ifdef HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
- pthread_cond_timedwait_relative_np(&er->cond, &er->lock, &ts);
-#else
pthread_cond_timedwait(&er->cond, &er->lock, &ts);
-#endif
ALOGV_IF((er->frames_in < buffer->frame_count),
"echo_reference_read() waited %d ms but still not enough frames"\
diff --git a/audio_utils/fixedfft.cpp b/audio_utils/fixedfft.cpp
index eba84e7..3fcc247 100644
--- a/audio_utils/fixedfft.cpp
+++ b/audio_utils/fixedfft.cpp
@@ -26,9 +26,6 @@
#include <stdio.h>
#include <stdint.h>
-#ifdef __arm__
-#include <machine/cpu-features.h>
-#endif
#include <audio_utils/fixedfft.h>
@@ -86,7 +83,7 @@
/* Returns the multiplication of \conj{a} and {b}. */
static inline int32_t mult(int32_t a, int32_t b)
{
-#if __ARM_ARCH__ >= 6
+#if defined(__arm__)
int32_t t = b;
__asm__("smuad %0, %0, %1" : "+r" (t) : "r" (a));
__asm__("smusdx %0, %0, %1" : "+r" (b) : "r" (a));
@@ -100,7 +97,7 @@
static inline int32_t half(int32_t a)
{
-#if __ARM_ARCH__ >= 6
+#if defined(__arm__)
__asm__("shadd16 %0, %0, %1" : "+r" (a) : "r" (0));
return a;
#else
diff --git a/audio_utils/primitives.c b/audio_utils/primitives.c
index 254f3af..d44c29e 100644
--- a/audio_utils/primitives.c
+++ b/audio_utils/primitives.c
@@ -345,15 +345,15 @@
#define copy_frame_by_mask(dst, dmask, src, smask, count, zero) \
{ \
uint32_t bit, ormask; \
- while (count--) { \
- ormask = dmask | smask; \
+ while ((count)--) { \
+ ormask = (dmask) | (smask); \
while (ormask) { \
bit = ormask & -ormask; /* get lowest bit */ \
ormask ^= bit; /* remove lowest bit */ \
- if (dmask & bit) { \
- *dst++ = smask & bit ? *src++ : zero; \
+ if ((dmask) & bit) { \
+ *(dst)++ = (smask) & bit ? *(src)++ : (zero); \
} else { /* source channel only */ \
- ++src; \
+ ++(src); \
} \
} \
} \
@@ -417,12 +417,12 @@
{ \
unsigned i; \
int index; \
- while (count--) { \
- for (i = 0; i < dst_channels; ++i) { \
- index = idxary[i]; \
- *dst++ = index < 0 ? zero : src[index]; \
+ while ((count)--) { \
+ for (i = 0; i < (dst_channels); ++i) { \
+ index = (idxary)[i]; \
+ *(dst)++ = index < 0 ? (zero) : (src)[index]; \
} \
- src += src_channels; \
+ (src) += (src_channels); \
} \
}
diff --git a/audio_utils/spdif/AC3FrameScanner.cpp b/audio_utils/spdif/AC3FrameScanner.cpp
index ab47274..4055bb0 100644
--- a/audio_utils/spdif/AC3FrameScanner.cpp
+++ b/audio_utils/spdif/AC3FrameScanner.cpp
@@ -92,12 +92,13 @@
// -----------------------------------------------------------------------------
// Scanner for AC3 byte streams.
-AC3FrameScanner::AC3FrameScanner()
+AC3FrameScanner::AC3FrameScanner(audio_format_t format)
: FrameScanner(SPDIF_DATA_TYPE_AC3,
AC3FrameScanner::kSyncBytes,
sizeof(AC3FrameScanner::kSyncBytes), 6)
, mStreamType(0)
, mSubstreamID(0)
+ , mFormat(format)
{
mAudioBlocksPerSyncFrame = 6;
memset(mSubstreamBlockCounts, 0, sizeof(mSubstreamBlockCounts));
@@ -240,6 +241,14 @@
* kAC3FrameSizeTable[frmsizcod][fscod];
}
mAudioBlocksPerSyncFrame = 6;
+ if (mFormat == AUDIO_FORMAT_E_AC3) {
+ ALOGV("Its a Ac3 substream in EAC3 stream");
+ mStreamType = 2;
+ mSubstreamID = 0;
+ mSubstreamBlockCounts[0] += mAudioBlocksPerSyncFrame;
+ mDataType = SPDIF_DATA_TYPE_E_AC3;
+ mRateMultiplier = EAC3_RATE_MULTIPLIER;
+ }
}
ALOGI_IF((mFormatDumpCount == 0),
"AC3 frame rate = %d * %d, size = %zu, audioBlocksPerSyncFrame = %d",
diff --git a/audio_utils/spdif/AC3FrameScanner.h b/audio_utils/spdif/AC3FrameScanner.h
index 1ef5610..7cdba84 100644
--- a/audio_utils/spdif/AC3FrameScanner.h
+++ b/audio_utils/spdif/AC3FrameScanner.h
@@ -18,6 +18,7 @@
#define ANDROID_AUDIO_AC3_FRAME_SCANNER_H
#include <stdint.h>
+#include <hardware/audio.h>
#include <audio_utils/spdif/FrameScanner.h>
namespace android {
@@ -34,7 +35,7 @@
class AC3FrameScanner : public FrameScanner
{
public:
- AC3FrameScanner();
+ AC3FrameScanner(audio_format_t format);
virtual ~AC3FrameScanner();
virtual int getMaxChannels() const { return 5 + 1; } // 5.1 surround
@@ -58,6 +59,7 @@
uint32_t mStreamType;
// substream index
uint32_t mSubstreamID;
+ audio_format_t mFormat;
// used to recognize the start of an AC3 sync frame
static const uint8_t kSyncBytes[];
diff --git a/audio_utils/spdif/SPDIFEncoder.cpp b/audio_utils/spdif/SPDIFEncoder.cpp
index 8e7e6cd..efcd556 100644
--- a/audio_utils/spdif/SPDIFEncoder.cpp
+++ b/audio_utils/spdif/SPDIFEncoder.cpp
@@ -48,7 +48,7 @@
switch(format) {
case AUDIO_FORMAT_AC3:
case AUDIO_FORMAT_E_AC3:
- mFramer = new AC3FrameScanner();
+ mFramer = new AC3FrameScanner(format);
break;
case AUDIO_FORMAT_DTS:
case AUDIO_FORMAT_DTS_HD:
diff --git a/brillo/audio/audioservice/Android.mk b/brillo/audio/audioservice/Android.mk
index 8d4fb15..cdfbb49 100644
--- a/brillo/audio/audioservice/Android.mk
+++ b/brillo/audio/audioservice/Android.mk
@@ -15,6 +15,7 @@
LOCAL_PATH := $(call my-dir)
audio_service_shared_libraries := \
+ libbinder \
libbinderwrapper \
libbrillo \
libbrillo-binder \
@@ -23,28 +24,62 @@
libmedia \
libutils
+audio_client_sources := \
+ aidl/android/brillo/brilloaudioservice/IAudioServiceCallback.aidl \
+ aidl/android/brillo/brilloaudioservice/IBrilloAudioService.aidl \
+ audio_service_callback.cpp \
+ brillo_audio_client.cpp \
+ brillo_audio_client_helpers.cpp \
+ brillo_audio_device_info.cpp \
+ brillo_audio_device_info_internal.cpp \
+ brillo_audio_manager.cpp
+
+audio_service_sources := \
+ aidl/android/brillo/brilloaudioservice/IAudioServiceCallback.aidl \
+ aidl/android/brillo/brilloaudioservice/IBrilloAudioService.aidl \
+ audio_daemon.cpp \
+ audio_device_handler.cpp \
+ audio_volume_handler.cpp \
+ brillo_audio_service_impl.cpp
+
# Audio service.
# =============================================================================
include $(CLEAR_VARS)
LOCAL_MODULE := brilloaudioservice
LOCAL_SRC_FILES := \
- audio_daemon.cpp \
- audio_device_handler.cpp \
+ $(audio_service_sources) \
main_audio_service.cpp
+LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl
LOCAL_SHARED_LIBRARIES := $(audio_service_shared_libraries)
LOCAL_CFLAGS := -Werror -Wall
LOCAL_INIT_RC := brilloaudioserv.rc
include $(BUILD_EXECUTABLE)
-# Unit tests for audio device handler.
+# Audio client library.
+# =============================================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbrilloaudio
+LOCAL_SRC_FILES := \
+ $(audio_client_sources)
+LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl
+LOCAL_SHARED_LIBRARIES := $(audio_service_shared_libraries)
+LOCAL_CFLAGS := -Wall -std=c++14
+include $(BUILD_SHARED_LIBRARY)
+
+# Unit tests for the Brillo audio service.
# =============================================================================
include $(CLEAR_VARS)
LOCAL_MODULE := brilloaudioservice_test
LOCAL_SRC_FILES := \
- audio_device_handler.cpp \
- test/audio_device_handler_test.cpp
+ $(audio_service_sources) \
+ test/audio_daemon_test.cpp \
+ test/audio_device_handler_test.cpp \
+ test/audio_volume_handler_test.cpp
+LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl
LOCAL_C_INCLUDES := external/gtest/include
-LOCAL_SHARED_LIBRARIES := $(audio_service_shared_libraries)
+LOCAL_SHARED_LIBRARIES := \
+ $(audio_service_shared_libraries) \
+ libbinderwrapper_test_support
LOCAL_STATIC_LIBRARIES := \
libBionicGtestMain \
libchrome_test_helpers \
@@ -52,3 +87,24 @@
LOCAL_CFLAGS := -Werror -Wall
LOCAL_CFLAGS += -Wno-sign-compare
include $(BUILD_NATIVE_TEST)
+
+# Unit tests for the Brillo audio client.
+# =============================================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := brilloaudioclient_test
+LOCAL_SRC_FILES := \
+ $(audio_client_sources) \
+ test/audio_service_callback_test.cpp \
+ test/brillo_audio_client_test.cpp \
+ test/brillo_audio_device_info_internal_test.cpp \
+ test/brillo_audio_manager_test.cpp
+LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl
+LOCAL_SHARED_LIBRARIES := \
+ $(audio_service_shared_libraries) \
+ libbinderwrapper_test_support
+LOCAL_STATIC_LIBRARIES := \
+ libBionicGtestMain \
+ libchrome_test_helpers \
+ libgmock
+LOCAL_CFLAGS := -Wno-sign-compare -Wall
+include $(BUILD_NATIVE_TEST)
diff --git a/brillo/audio/audioservice/aidl/android/brillo/brilloaudioservice/IAudioServiceCallback.aidl b/brillo/audio/audioservice/aidl/android/brillo/brilloaudioservice/IAudioServiceCallback.aidl
new file mode 100644
index 0000000..841c4ae
--- /dev/null
+++ b/brillo/audio/audioservice/aidl/android/brillo/brilloaudioservice/IAudioServiceCallback.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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.
+ */
+
+
+package android.brillo.brilloaudioservice;
+
+/*
+ * Interface for the callback object registered with IBrilloAudioService. Used
+ * to notify clients about changes to the audio system.
+ */
+interface IAudioServiceCallback {
+ // Oneway call triggered when audio devices are connected to the system.
+ oneway void OnAudioDevicesConnected(in int[] added_devices);
+
+ // Oneway call triggered when audio devices are disconnected from the system.
+ oneway void OnAudioDevicesDisconnected(in int[] removed_devices);
+
+ // Oneway call triggered when the volume is changed. If there are
+ // multiple active streams, this call will be called multiple times.
+ oneway void OnVolumeChanged(
+ int stream_type, int old_volume_index, int new_volume_index);
+}
diff --git a/brillo/audio/audioservice/aidl/android/brillo/brilloaudioservice/IBrilloAudioService.aidl b/brillo/audio/audioservice/aidl/android/brillo/brilloaudioservice/IBrilloAudioService.aidl
new file mode 100644
index 0000000..209b651
--- /dev/null
+++ b/brillo/audio/audioservice/aidl/android/brillo/brilloaudioservice/IBrilloAudioService.aidl
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 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.
+ */
+
+
+package android.brillo.brilloaudioservice;
+
+import android.brillo.brilloaudioservice.IAudioServiceCallback;
+
+/*
+ * Interface for BrilloAudioService that clients can use to get the list of
+ * devices currently connected to the system as well as to control volume.
+ * Clients can also register callbacks to be notified about changes.
+ */
+interface IBrilloAudioService {
+ // Constants for device enumeration.
+ const int GET_DEVICES_INPUTS = 1;
+ const int GET_DEVICES_OUTPUTS = 2;
+
+ // Constants for volume control.
+ const int VOLUME_BUTTON_PRESS_DOWN = 1;
+ const int VOLUME_BUTTON_PRESS_UP = 2;
+
+ // Get the list of devices connected. If flag is GET_DEVICES_INPUTS, then
+ // return input devices. Otherwise, return output devices.
+ int[] GetDevices(int flag);
+
+ // Set device for a given usage.
+ // usage is an int of type audio_policy_force_use_t.
+ // config is an int of type audio_policy_forced_cfg_t.
+ void SetDevice(int usage, int config);
+
+ // Get the maximum number of steps used for a given stream.
+ int GetMaxVolumeSteps(int stream);
+
+ // Set the maximum number of steps to use for a given stream.
+ void SetMaxVolumeSteps(int stream, int max_steps);
+
+ // Set the volume for a given (stream, device) tuple.
+ void SetVolumeIndex(int stream, int device, int index);
+
+ // Get the current volume for a given (stream, device) tuple.
+ int GetVolumeIndex(int stream, int device);
+
+ // Get stream used when volume buttons are pressed.
+ int GetVolumeControlStream();
+
+ // Set default stream to use when volume buttons are pressed.
+ void SetVolumeControlStream(int stream);
+
+ // Increment volume.
+ void IncrementVolume();
+
+ // Decrement volume.
+ void DecrementVolume();
+
+ // Register a callback object with the service.
+ void RegisterServiceCallback(IAudioServiceCallback callback);
+
+ // Unregister a callback object.
+ void UnregisterServiceCallback(IAudioServiceCallback callback);
+}
diff --git a/brillo/audio/audioservice/audio_daemon.cpp b/brillo/audio/audioservice/audio_daemon.cpp
index f764f1a..08ff548 100644
--- a/brillo/audio/audioservice/audio_daemon.cpp
+++ b/brillo/audio/audioservice/audio_daemon.cpp
@@ -26,16 +26,37 @@
#include <binderwrapper/binder_wrapper.h>
#include <linux/input.h>
+#include "brillo_audio_service_impl.h"
+
namespace brillo {
static const char kAPSServiceName[] = "media.audio_policy";
static const char kInputDeviceDir[] = "/dev/input";
+static const char kServiceName[] =
+ "android.brillo.brilloaudioservice.BrilloAudioService";
-void AudioDaemon::InitializeHandler() {
- // Start and initialize the audio device handler.
+AudioDaemon::~AudioDaemon() {}
+
+void AudioDaemon::InitializeHandlers() {
+ // Start and initialize the audio daemon handlers.
audio_device_handler_ =
- std::unique_ptr<AudioDeviceHandler>(new AudioDeviceHandler());
+ std::shared_ptr<AudioDeviceHandler>(new AudioDeviceHandler());
+ audio_volume_handler_ =
+ std::unique_ptr<AudioVolumeHandler>(new AudioVolumeHandler());
+
+ // Register a callback with the audio device handler to call when device state
+ // changes.
+ auto device_callback =
+ base::Bind(&AudioDaemon::DeviceCallback, weak_ptr_factory_.GetWeakPtr());
+ audio_device_handler_->RegisterDeviceCallback(device_callback);
+
+ // Register a callback with the audio volume handler.
+ auto volume_callback =
+ base::Bind(&AudioDaemon::VolumeCallback, weak_ptr_factory_.GetWeakPtr());
+ audio_volume_handler_->RegisterCallback(volume_callback);
+
audio_device_handler_->Init(aps_);
+ audio_volume_handler_->Init(aps_);
// Poll on all files in kInputDeviceDir.
base::FileEnumerator fenum(base::FilePath(kInputDeviceDir),
@@ -48,17 +69,31 @@
// Move file to files_ and ensure that when binding we get a pointer from
// the object in files_.
files_.emplace(std::move(file));
- base::Closure callback =
- base::Bind(&AudioDaemon::Callback, weak_ptr_factory_.GetWeakPtr(),
+ base::Closure file_callback =
+ base::Bind(&AudioDaemon::EventCallback, weak_ptr_factory_.GetWeakPtr(),
&files_.top());
message_loop->WatchFileDescriptor(fd, MessageLoop::kWatchRead,
- true /*persistent*/, callback);
+ true /*persistent*/, file_callback);
} else {
LOG(WARNING) << "Could not open " << name.value() << " for reading. ("
<< base::File::ErrorToString(file.error_details()) << ")";
}
}
- handler_initialized_ = true;
+
+ handlers_initialized_ = true;
+ // Once the handlers have been initialized, we can register with service
+ // manager.
+ InitializeBrilloAudioService();
+}
+
+void AudioDaemon::InitializeBrilloAudioService() {
+ brillo_audio_service_ = new BrilloAudioServiceImpl();
+ brillo_audio_service_->RegisterHandlers(
+ std::weak_ptr<AudioDeviceHandler>(audio_device_handler_),
+ std::weak_ptr<AudioVolumeHandler>(audio_volume_handler_));
+ android::BinderWrapper::Get()->RegisterService(kServiceName,
+ brillo_audio_service_);
+ VLOG(1) << "Registered brilloaudioservice with the service manager.";
}
void AudioDaemon::ConnectToAPS() {
@@ -79,22 +114,25 @@
weak_ptr_factory_.GetWeakPtr()));
VLOG(1) << "Registered death notification.";
aps_ = android::interface_cast<android::IAudioPolicyService>(binder);
- if (!handler_initialized_)
- InitializeHandler();
- else
+ if (!handlers_initialized_) {
+ InitializeHandlers();
+ } else {
audio_device_handler_->APSConnect(aps_);
+ audio_volume_handler_->APSConnect(aps_);
+ }
}
void AudioDaemon::OnAPSDisconnected() {
LOG(INFO) << "Audio policy service died. Will try to reconnect.";
audio_device_handler_->APSDisconnect();
+ audio_volume_handler_->APSDisconnect();
aps_ = nullptr;
ConnectToAPS();
}
// OnInit, we want to do the following:
// - Get a binder to the audio policy service.
-// - Initialize the audio device handler.
+// - Initialize the audio device and volume handlers.
// - Set up polling on files in /dev/input.
int AudioDaemon::OnInit() {
int exit_code = Daemon::OnInit();
@@ -107,7 +145,7 @@
return EX_OK;
}
-void AudioDaemon::Callback(base::File* file) {
+void AudioDaemon::EventCallback(base::File* file) {
input_event event;
int bytes_read =
file->ReadAtCurrentPos(reinterpret_cast<char*>(&event), sizeof(event));
@@ -116,6 +154,38 @@
return;
}
audio_device_handler_->ProcessEvent(event);
+ audio_volume_handler_->ProcessEvent(event);
+}
+
+void AudioDaemon::DeviceCallback(
+ AudioDeviceHandler::DeviceConnectionState state,
+ const std::vector<int>& devices) {
+ VLOG(1) << "Triggering device callback.";
+ if (!brillo_audio_service_.get()) {
+ LOG(ERROR) << "The Brillo audio service object is unavailble. Will try to "
+ << "call the clients again once the service is up.";
+ InitializeBrilloAudioService();
+ DeviceCallback(state, devices);
+ return;
+ }
+ if (state == AudioDeviceHandler::DeviceConnectionState::kDevicesConnected)
+ brillo_audio_service_->OnDevicesConnected(devices);
+ else
+ brillo_audio_service_->OnDevicesDisconnected(devices);
+}
+
+void AudioDaemon::VolumeCallback(audio_stream_type_t stream,
+ int previous_index,
+ int current_index) {
+ VLOG(1) << "Triggering volume button press callback.";
+ if (!brillo_audio_service_.get()) {
+ LOG(ERROR) << "The Brillo audio service object is unavailble. Will try to "
+ << "call the clients again once the service is up.";
+ InitializeBrilloAudioService();
+ VolumeCallback(stream, previous_index, current_index);
+ return;
+ }
+ brillo_audio_service_->OnVolumeChanged(stream, previous_index, current_index);
}
} // namespace brillo
diff --git a/brillo/audio/audioservice/audio_daemon.h b/brillo/audio/audioservice/audio_daemon.h
index 48aa35f..5fc01fd 100644
--- a/brillo/audio/audioservice/audio_daemon.h
+++ b/brillo/audio/audioservice/audio_daemon.h
@@ -20,6 +20,7 @@
#include <memory>
#include <stack>
+#include <vector>
#include <base/files/file.h>
#include <base/memory/weak_ptr.h>
@@ -28,22 +29,47 @@
#include <media/IAudioPolicyService.h>
#include "audio_device_handler.h"
+#include "audio_volume_handler.h"
+#include "brillo_audio_service.h"
namespace brillo {
class AudioDaemon : public Daemon {
public:
AudioDaemon() {}
+ virtual ~AudioDaemon();
protected:
- // Initialize the audio device handler and start pollig the files in
+ // Initialize the audio daemon handlers and start pollig the files in
// /dev/input.
int OnInit() override;
private:
+ friend class AudioDaemonTest;
+ FRIEND_TEST(AudioDaemonTest, RegisterService);
+ FRIEND_TEST(AudioDaemonTest, TestAPSConnectInitializesHandlersOnlyOnce);
+ FRIEND_TEST(AudioDaemonTest, TestDeviceCallbackInitializesBASIfNULL);
+
// Callback function for input events. Events are handled by the audio device
// handler.
- void Callback(base::File* file);
+ void EventCallback(base::File* file);
+
+ // Callback function for device state changes. Events are handler by the
+ // audio service.
+ //
+ // |mode| is kDevicesConnected when |devices| are connected.
+ // |devices| is a vector of integers representing audio_devices_t.
+ void DeviceCallback(AudioDeviceHandler::DeviceConnectionState,
+ const std::vector<int>& devices);
+
+ // Callback function when volume changes.
+ //
+ // |stream| is an audio_stream_type_t representing the stream.
+ // |previous_index| is the volume index before the key press.
+ // |current_index| is the volume index after the key press.
+ void VolumeCallback(audio_stream_type_t stream,
+ int previous_index,
+ int current_index);
// Callback function for audio policy service death notification.
void OnAPSDisconnected();
@@ -52,26 +78,33 @@
// if the audio policy service dies.
void ConnectToAPS();
- // Initialize the audio_device_handler_.
+ // Register the brillo audio service with the service manager.
+ void InitializeBrilloAudioService();
+
+ // Initialize all audio daemon handlers.
//
// Note: This can only occur after we have connected to the audio policy
// service.
- void InitializeHandler();
+ virtual void InitializeHandlers();
// Store the file objects that are created during initialization for the files
// being polled. This is done so these objects can be freed when the
// AudioDaemon object is destroyed.
std::stack<base::File> files_;
// Handler for audio device input events.
- std::unique_ptr<AudioDeviceHandler> audio_device_handler_;
+ std::shared_ptr<AudioDeviceHandler> audio_device_handler_;
+ // Handler for volume key press input events.
+ std::shared_ptr<AudioVolumeHandler> audio_volume_handler_;
// Used to generate weak_ptr to AudioDaemon for use in base::Bind.
base::WeakPtrFactory<AudioDaemon> weak_ptr_factory_{this};
// Pointer to the audio policy service.
android::sp<android::IAudioPolicyService> aps_;
- // Flag to indicate whether the handler has been initialized.
- bool handler_initialized_ = false;
+ // Flag to indicate whether the handlers have been initialized.
+ bool handlers_initialized_ = false;
// Binder watcher to watch for binder messages.
- brillo::BinderWatcher binder_watcher_;
+ BinderWatcher binder_watcher_;
+ // Brillo audio service. Used for scheduling callbacks to clients.
+ android::sp<BrilloAudioService> brillo_audio_service_;
};
} // namespace brillo
diff --git a/brillo/audio/audioservice/audio_daemon_handler.h b/brillo/audio/audioservice/audio_daemon_handler.h
new file mode 100644
index 0000000..ea147c2
--- /dev/null
+++ b/brillo/audio/audioservice/audio_daemon_handler.h
@@ -0,0 +1,58 @@
+// 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.
+//
+
+// Handler for input events in /dev/input. AudioDaemonHandler is the base class
+// that other handlers inherit.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DAEMON_HANDLER_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DAEMON_HANDLER_H_
+
+#include <linux/input.h>
+#include <media/IAudioPolicyService.h>
+
+namespace brillo {
+
+class AudioDaemonHandler {
+ public:
+ virtual ~AudioDaemonHandler(){};
+
+ // Initialize the handler.
+ //
+ // |aps| is a pointer to the binder object.
+ virtual void Init(android::sp<android::IAudioPolicyService> aps) = 0;
+
+ // Process input events from the kernel.
+ //
+ // |event| is a pointer to an input_event. This function should be able to
+ // gracefully handle input events that are not relevant to the functionality
+ // provided by this class.
+ virtual void ProcessEvent(const struct input_event& event) = 0;
+
+ // Inform the handler that the audio policy service has been disconnected.
+ virtual void APSDisconnect() = 0;
+
+ // Inform the handler that the audio policy service is reconnected.
+ //
+ // |aps| is a pointer to the binder object.
+ virtual void APSConnect(android::sp<android::IAudioPolicyService> aps) = 0;
+
+ protected:
+ // Pointer to the audio policy service.
+ android::sp<android::IAudioPolicyService> aps_;
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DAEMON_HANDLER_H_
diff --git a/brillo/audio/audioservice/audio_device_handler.cpp b/brillo/audio/audioservice/audio_device_handler.cpp
index af12c96..dc7e454 100644
--- a/brillo/audio/audioservice/audio_device_handler.cpp
+++ b/brillo/audio/audioservice/audio_device_handler.cpp
@@ -19,10 +19,19 @@
#include <base/files/file.h>
#include <base/logging.h>
+#include <brillo/message_loops/message_loop.h>
#include <media/AudioSystem.h>
namespace brillo {
+// All input devices currently supported by AudioDeviceHandler.
+const std::vector<audio_devices_t> AudioDeviceHandler::kSupportedInputDevices_ =
+ {AUDIO_DEVICE_IN_WIRED_HEADSET};
+
+const std::vector<audio_devices_t>
+ AudioDeviceHandler::kSupportedOutputDevices_ = {
+ AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADPHONE};
+
static const char kH2WStateFile[] = "/sys/class/switch/h2w/state";
AudioDeviceHandler::AudioDeviceHandler() {
@@ -32,6 +41,35 @@
AudioDeviceHandler::~AudioDeviceHandler() {}
+void AudioDeviceHandler::GetInputDevices(std::vector<int>* devices_list) {
+ std::copy(connected_input_devices_.begin(),
+ connected_input_devices_.end(),
+ std::back_inserter(*devices_list));
+}
+
+void AudioDeviceHandler::GetOutputDevices(std::vector<int>* devices_list) {
+ std::copy(connected_output_devices_.begin(),
+ connected_output_devices_.end(),
+ std::back_inserter(*devices_list));
+}
+
+void AudioDeviceHandler::RegisterDeviceCallback(
+ base::Callback<void(DeviceConnectionState,
+ const std::vector<int>& )>& callback) {
+ callback_ = callback;
+}
+
+void AudioDeviceHandler::TriggerCallback(DeviceConnectionState state) {
+ // If no devices have changed, don't bother triggering a callback.
+ if (changed_devices_.size() == 0)
+ return;
+ base::Closure closure = base::Bind(callback_, state, changed_devices_);
+ MessageLoop::current()->PostTask(closure);
+ // We can clear changed_devices_ here since base::Bind makes a copy of
+ // changed_devices_.
+ changed_devices_.clear();
+}
+
void AudioDeviceHandler::APSDisconnect() {
aps_.clear();
}
@@ -54,6 +92,7 @@
// was previously told.
VLOG(1) << "Calling DisconnectAllSupportedDevices.";
DisconnectAllSupportedDevices();
+ TriggerCallback(kDevicesDisconnected);
// Get headphone jack state and update audio policy service with new state.
VLOG(1) << "Calling ReadInitialAudioDeviceState.";
@@ -65,8 +104,8 @@
base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!file.IsValid()) {
LOG(WARNING) << "Kernel does not have wired headset support. Could not "
- << "open " << path.value() << "( "
- << base::File::ErrorToString(file.error_details()) << " ).";
+ << "open " << path.value() << " ("
+ << base::File::ErrorToString(file.error_details()) << ").";
return;
}
int state = 0;
@@ -97,6 +136,17 @@
aps_->setDeviceConnectionState(device, state, "", "");
}
+int AudioDeviceHandler::SetDevice(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config) {
+ if (aps_ == nullptr) {
+ LOG(WARNING) << "Audio policy service cannot be reached. Please try again.";
+ return EAGAIN;
+ }
+ VLOG(1) << "Calling audio policy service to set " << usage << " to "
+ << config;
+ return aps_->setForceUse(usage, config);
+}
+
void AudioDeviceHandler::ConnectAudioDevice(audio_devices_t device) {
audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
NotifyAudioPolicyService(device, state);
@@ -104,6 +154,7 @@
connected_input_devices_.insert(device);
else
connected_output_devices_.insert(device);
+ changed_devices_.push_back(device);
}
void AudioDeviceHandler::DisconnectAudioDevice(audio_devices_t device) {
@@ -113,6 +164,7 @@
connected_input_devices_.erase(device);
else
connected_output_devices_.erase(device);
+ changed_devices_.push_back(device);
}
void AudioDeviceHandler::DisconnectAllSupportedDevices() {
@@ -147,7 +199,11 @@
// No devices are connected. Inform the audio policy service that all
// connected devices have been disconnected.
DisconnectAllConnectedDevices();
+ TriggerCallback(kDevicesDisconnected);
+ return;
}
+ TriggerCallback(kDevicesConnected);
+ return;
}
void AudioDeviceHandler::ProcessEvent(const struct input_event& event) {
diff --git a/brillo/audio/audioservice/audio_device_handler.h b/brillo/audio/audioservice/audio_device_handler.h
index 335ae98..af20420 100644
--- a/brillo/audio/audioservice/audio_device_handler.h
+++ b/brillo/audio/audioservice/audio_device_handler.h
@@ -23,6 +23,7 @@
#include <set>
#include <vector>
+#include <base/bind.h>
#include <base/files/file_path.h>
#include <gtest/gtest_prod.h>
#include <linux/input.h>
@@ -30,9 +31,11 @@
#include <system/audio.h>
#include <system/audio_policy.h>
+#include "audio_daemon_handler.h"
+
namespace brillo {
-class AudioDeviceHandler {
+class AudioDeviceHandler : public AudioDaemonHandler {
public:
AudioDeviceHandler();
virtual ~AudioDeviceHandler();
@@ -41,7 +44,7 @@
// the initial state.
//
// |aps| is a pointer to the binder object.
- void Init(android::sp<android::IAudioPolicyService> aps);
+ virtual void Init(android::sp<android::IAudioPolicyService> aps) override;
// Process input events from the kernel. Connecting/disconnecting an audio
// device will result in multiple calls to this method.
@@ -49,7 +52,7 @@
// |event| is a pointer to an input_event. This function should be able to
// gracefully handle input events that are not relevant to the functionality
// provided by this class.
- void ProcessEvent(const struct input_event& event);
+ virtual void ProcessEvent(const struct input_event& event) override;
// Inform the handler that the audio policy service has been disconnected.
void APSDisconnect();
@@ -57,10 +60,49 @@
// Inform the handler that the audio policy service is reconnected.
//
// |aps| is a pointer to the binder object.
- void APSConnect(android::sp<android::IAudioPolicyService> aps);
+ virtual void APSConnect(
+ android::sp<android::IAudioPolicyService> aps) override;
+
+ // Get the list of connected devices.
+ //
+ // |devices_list| is the vector to copy list of connected input devices to.
+ void GetInputDevices(std::vector<int>* devices_list);
+
+ // Get the list of connected output devices.
+ //
+ // |devices_list| is the vector to copy the list of connected output devices
+ // to.
+ void GetOutputDevices(std::vector<int>* devices_list);
+
+ // Set device.
+ //
+ // |usage| is an int of type audio_policy_force_use_t
+ // |config| is an int of type audio_policy_forced_cfg_t.
+ //
+ // Returns 0 on sucess and errno on failure.
+ int SetDevice(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config);
+
+ // Enum used to represent whether devices are being connected or not. This is
+ // used when triggering callbacks.
+ enum DeviceConnectionState {
+ kDevicesConnected,
+ kDevicesDisconnected
+ };
+
+ // Register a callback function to call when device state changes.
+ //
+ // |callback| is an object of type base::Callback that accepts a
+ // DeviceConnectionState and a vector of ints. See DeviceCallback() in
+ // audio_daemon.h.
+ void RegisterDeviceCallback(
+ base::Callback<void(DeviceConnectionState,
+ const std::vector<int>& )>& callback);
private:
friend class AudioDeviceHandlerTest;
+ friend class AudioVolumeHandler;
+ friend class AudioVolumeHandlerTest;
FRIEND_TEST(AudioDeviceHandlerTest,
DisconnectAllSupportedDevicesCallsDisconnect);
FRIEND_TEST(AudioDeviceHandlerTest, InitCallsDisconnectAllSupportedDevices);
@@ -86,6 +128,7 @@
FRIEND_TEST(AudioDeviceHandlerTest, ConnectAudioDeviceOutput);
FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceInput);
FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceOutput);
+ FRIEND_TEST(AudioVolumeHandlerTest, FileGeneration);
// Read the initial state of audio devices in /sys/class/* and update
// the audio policy service.
@@ -125,26 +168,32 @@
// Disconnect all supported audio devices.
void DisconnectAllSupportedDevices();
+ // Trigger a callback when a device is either connected or disconnected.
+ //
+ // |state| is kDevicesConnected when |devices| are being connected.
+ virtual void TriggerCallback(DeviceConnectionState state);
+
// All input devices currently supported by AudioDeviceHandler.
- std::vector<audio_devices_t> kSupportedInputDevices_{
- AUDIO_DEVICE_IN_WIRED_HEADSET};
+ static const std::vector<audio_devices_t> kSupportedInputDevices_;
// All output devices currently supported by AudioDeviceHandler.
- std::vector<audio_devices_t> kSupportedOutputDevices_{
- AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADPHONE};
- // Pointer to the audio policy service.
- android::sp<android::IAudioPolicyService> aps_;
+ static const std::vector<audio_devices_t> kSupportedOutputDevices_;
protected:
// Set of connected input devices.
std::set<audio_devices_t> connected_input_devices_;
// Set of connected output devices.
std::set<audio_devices_t> connected_output_devices_;
+ // Vector of devices changed (used for callbacks to clients).
+ std::vector<int> changed_devices_;
// Keeps track of whether a headphone has been connected. Used by ProcessEvent
// and UpdateAudioSystem.
bool headphone_;
// Keeps track of whether a microphone has been connected. Used by
// ProcessEvent and UpdateAudioSystem.
bool microphone_;
+ // Callback object to call when device state changes.
+ base::Callback<void(DeviceConnectionState,
+ const std::vector<int>& )> callback_;
};
} // namespace brillo
diff --git a/brillo/audio/audioservice/audio_service_callback.cpp b/brillo/audio/audioservice/audio_service_callback.cpp
new file mode 100644
index 0000000..eecc1ce
--- /dev/null
+++ b/brillo/audio/audioservice/audio_service_callback.cpp
@@ -0,0 +1,78 @@
+// 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_service_callback.
+
+#include "audio_service_callback.h"
+
+#include <base/bind.h>
+#include <base/logging.h>
+
+#include "brillo_audio_client_helpers.h"
+#include "brillo_audio_device_info_def.h"
+
+using android::binder::Status;
+
+namespace brillo {
+
+AudioServiceCallback::AudioServiceCallback(const BAudioCallback* callback,
+ void* user_data) {
+ connected_callback_ = base::Bind(callback->OnAudioDeviceAdded);
+ disconnected_callback_ = base::Bind(callback->OnAudioDeviceRemoved);
+ volume_callback_ = base::Bind(callback->OnVolumeChanged);
+ user_data_ = user_data;
+}
+
+Status AudioServiceCallback::OnAudioDevicesConnected(
+ const std::vector<int>& devices) {
+ for (auto device : devices) {
+ BAudioDeviceInfo device_info;
+ device_info.internal_ = std::unique_ptr<BAudioDeviceInfoInternal>(
+ BAudioDeviceInfoInternal::CreateFromAudioDevicesT(device));
+ connected_callback_.Run(&device_info, user_data_);
+ }
+ return Status::ok();
+}
+
+Status AudioServiceCallback::OnAudioDevicesDisconnected(
+ const std::vector<int>& devices) {
+ for (auto device : devices) {
+ BAudioDeviceInfo device_info;
+ device_info.internal_ = std::unique_ptr<BAudioDeviceInfoInternal>(
+ BAudioDeviceInfoInternal::CreateFromAudioDevicesT(device));
+ disconnected_callback_.Run(&device_info, user_data_);
+ }
+ return Status::ok();
+}
+
+Status AudioServiceCallback::OnVolumeChanged(int stream,
+ int previous_index,
+ int current_index) {
+ auto usage = BrilloAudioClientHelpers::GetBAudioUsage(
+ static_cast<audio_stream_type_t>(stream));
+ volume_callback_.Run(usage, previous_index, current_index, user_data_);
+ return Status::ok();
+}
+
+bool AudioServiceCallback::Equals(android::sp<AudioServiceCallback> callback) {
+ if (callback->connected_callback_.Equals(connected_callback_) &&
+ callback->disconnected_callback_.Equals(disconnected_callback_) &&
+ callback->volume_callback_.Equals(volume_callback_) &&
+ callback->user_data_ == user_data_)
+ return true;
+ return false;
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/audio_service_callback.h b/brillo/audio/audioservice/audio_service_callback.h
new file mode 100644
index 0000000..5c72924
--- /dev/null
+++ b/brillo/audio/audioservice/audio_service_callback.h
@@ -0,0 +1,80 @@
+// 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.
+//
+
+// Callback object to be passed to brilloaudioservice.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_AUDIO_SERVICE_CALLBACK_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_AUDIO_SERVICE_CALLBACK_H_
+
+#include <vector>
+
+#include <base/callback.h>
+#include <binder/Status.h>
+
+#include "android/brillo/brilloaudioservice/BnAudioServiceCallback.h"
+#include "include/brillo_audio_manager.h"
+
+using android::binder::Status;
+using android::brillo::brilloaudioservice::BnAudioServiceCallback;
+
+namespace brillo {
+
+class AudioServiceCallback : public BnAudioServiceCallback {
+ public:
+ // Constructor for AudioServiceCallback.
+ //
+ // |callback| is an object of type BAudioCallback.
+ // |user_data| is an object to be passed to the callbacks.
+ AudioServiceCallback(const BAudioCallback* callback, void* user_data);
+
+ // Callback function triggered when a device is connected.
+ //
+ // |devices| is a vector of audio_devices_t.
+ Status OnAudioDevicesConnected(const std::vector<int>& devices);
+
+ // Callback function triggered when a device is disconnected.
+ //
+ // |devices| is a vector of audio_devices_t.
+ Status OnAudioDevicesDisconnected(const std::vector<int>& devices);
+
+ // Callback function triggered when volume is changed.
+ //
+ // |stream| is an int representing the stream.
+ // |previous_index| is the volume index before the key press.
+ // |current_index| is the volume index after the key press.
+ Status OnVolumeChanged(int stream, int previous_index, int current_index);
+
+ // Method to compare two AudioServiceCallback objects.
+ //
+ // |callback| is a ref counted pointer to a AudioServiceCallback object to be
+ // compared with this.
+ //
+ // Returns true if |callback| equals this.
+ bool Equals(android::sp<AudioServiceCallback> callback);
+
+ private:
+ // Callback when devices are connected.
+ base::Callback<void(const BAudioDeviceInfo*, void*)> connected_callback_;
+ // Callback when devices are disconnected.
+ base::Callback<void(const BAudioDeviceInfo*, void*)> disconnected_callback_;
+ // Callback when the volume button is pressed.
+ base::Callback<void(BAudioUsage, int, int, void*)> volume_callback_;
+ // User data passed to the callbacks.
+ void* user_data_;
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_AUDIO_SERVICE_CALLBACK_H_
diff --git a/brillo/audio/audioservice/audio_volume_handler.cpp b/brillo/audio/audioservice/audio_volume_handler.cpp
new file mode 100644
index 0000000..d95b2c2
--- /dev/null
+++ b/brillo/audio/audioservice/audio_volume_handler.cpp
@@ -0,0 +1,236 @@
+// 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
diff --git a/brillo/audio/audioservice/audio_volume_handler.h b/brillo/audio/audioservice/audio_volume_handler.h
new file mode 100644
index 0000000..fb95c2f
--- /dev/null
+++ b/brillo/audio/audioservice/audio_volume_handler.h
@@ -0,0 +1,248 @@
+// 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.
+//
+
+// Handler for input events in /dev/input. AudioVolumeHandler handles events
+// only for volume key presses.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_AUDIO_VOLUME_HANDLER_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_AUDIO_VOLUME_HANDLER_H_
+
+#include <base/bind.h>
+#include <base/files/file_path.h>
+#include <brillo/key_value_store.h>
+#include <gtest/gtest_prod.h>
+#include <linux/input.h>
+#include <media/IAudioPolicyService.h>
+#include <system/audio.h>
+
+#include "audio_daemon_handler.h"
+
+namespace brillo {
+
+class AudioVolumeHandler : public AudioDaemonHandler {
+ public:
+ AudioVolumeHandler();
+ virtual ~AudioVolumeHandler();
+
+ // Get the current state of the headset jack and update AudioSystem based on
+ // the initial state.
+ //
+ // |aps| is a pointer to the binder object.
+ virtual void Init(android::sp<android::IAudioPolicyService> aps) override;
+
+ // Process input events from the kernel. Connecting/disconnecting an audio
+ // device will result in multiple calls to this method.
+ //
+ // |event| is a pointer to an input_event. This function should be able to
+ // gracefully handle input events that are not relevant to the functionality
+ // provided by this class.
+ virtual void ProcessEvent(const struct input_event& event) override;
+
+ // Inform the handler that the audio policy service has been disconnected.
+ virtual void APSDisconnect() override;
+
+ // Inform the handler that the audio policy service is reconnected.
+ //
+ // |aps| is a pointer to the binder object.
+ virtual void APSConnect(
+ android::sp<android::IAudioPolicyService> aps) override;
+
+ // Get the stream used when volume buttons are pressed.
+ //
+ // Returns an audio_stream_t representing the stream. If
+ // SetVolumeControlStream isn't called before calling this method,
+ // STREAM_DEFAULT is returned.
+ audio_stream_type_t GetVolumeControlStream();
+
+ // Set the stream to use when volume buttons are pressed.
+ //
+ // |stream| is an int representing the stream. Passing STREAM_DEFAULT to this
+ // method can be used to reset selected_stream_.
+ void SetVolumeControlStream(audio_stream_type_t stream);
+
+ // Register a callback to be triggered when keys are pressed.
+ //
+ // |callback| is an object of type base::Callback.
+ void RegisterCallback(
+ base::Callback<void(audio_stream_type_t, int, int)>& callback);
+
+ // Set the max steps for an audio stream.
+ //
+ // |stream| is an int representing the stream.
+ // |max_index| is an int representing the maximum index to set for |stream|.
+ //
+ // Returns 0 on success and errno on failure.
+ int SetVolumeMaxSteps(audio_stream_type_t stream, int max_steps);
+
+ // Get the max steps for an audio stream.
+ //
+ // |stream| is an int representing the stream.
+ //
+ // Returns the maximum possible index for |stream|.
+ int GetVolumeMaxSteps(audio_stream_type_t stream);
+
+ // Get the volume of a given key.
+ //
+ // |stream| is an int representing the stream.
+ // |device| is an int representing the device.
+ //
+ // Returns an int which corresponds to the current index.
+ int GetVolumeCurrentIndex(audio_stream_type_t stream, audio_devices_t device);
+
+ // Set the volume for a given (stream, device) tuple.
+ //
+ // |stream| is an int representing the stream.
+ // |device| is an int representing the device.
+ // |index| is an int representing the volume.
+ //
+ // Returns 0 on success and errno on failure.
+ int SetVolumeIndex(audio_stream_type_t stream,
+ audio_devices_t device,
+ int index);
+
+ // Get the volume for a given (stream, device) tuple.
+ //
+ // |stream| is an int representing the stream.
+ // |device| is an int representing the device.
+ //
+ // Returns the index for the (stream, device) tuple. This index is between 0
+ // and the user defined maximum value.
+ int GetVolumeIndex(audio_stream_type_t stream, audio_devices_t device);
+
+ // Update the volume index for a given stream.
+ //
+ // |previous_index| is the current index of the stream/device tuple before the
+ // volume button is pressed.
+ // |direction| is an int which is multiplied to step_. +1 for volume up and -1
+ // for volume down.
+ // |stream| is an int representing the stream.
+ //
+ // Returns the new volume index.
+ int GetNewVolumeIndex(int previous_index, int direction,
+ audio_stream_type_t stream);
+
+ // Adjust the volume of the active streams in the direction indicated. If
+ // SetDefaultStream() is called, then only the volume for that stream will be
+ // changed. Calling this method always triggers a callback.
+ //
+ // |direction| is an int which is multiplied to step_. +1 for volume up and -1
+ // for volume down.
+ virtual void AdjustVolumeActiveStreams(int direction);
+
+ private:
+ friend class AudioVolumeHandlerTest;
+ FRIEND_TEST(AudioVolumeHandlerTest, FileGeneration);
+ FRIEND_TEST(AudioVolumeHandlerTest, GetVolumeForStreamDeviceTuple);
+ FRIEND_TEST(AudioVolumeHandlerTest, SetVolumeForStreamDeviceTuple);
+ FRIEND_TEST(AudioVolumeHandlerTest, InitNoFile);
+ FRIEND_TEST(AudioVolumeHandlerTest, InitFilePresent);
+ FRIEND_TEST(AudioVolumeHandlerTest, ProcessEventEmpty);
+ FRIEND_TEST(AudioVolumeHandlerTest, ProcessEventKeyUp);
+ FRIEND_TEST(AudioVolumeHandlerTest, ProcessEventKeyDown);
+ FRIEND_TEST(AudioVolumeHandlerTest, SelectStream);
+ FRIEND_TEST(AudioVolumeHandlerTest, ComputeNewVolume);
+ FRIEND_TEST(AudioVolumeHandlerTest, GetSetVolumeIndex);
+
+ // Save the volume for a given (stream, device) tuple.
+ //
+ // |stream| is an int representing the stream.
+ // |device| is an int representing the device.
+ // |index| is an int representing the volume.
+ void PersistVolumeConfiguration(audio_stream_type_t stream,
+ audio_devices_t device,
+ int index);
+
+ // Read the initial volume of audio streams.
+ //
+ // |path| is the file that contains the initial volume state.
+ void GetInitialVolumeState(const base::FilePath& path);
+
+ // Adjust the volume of a given stream in the direction specified.
+ //
+ // |stream| is an int representing the stream.
+ // |direction| is an int which is multiplied to step_. +1 for volume up and -1
+ // for volume down.
+ void AdjustStreamVolume(audio_stream_type_t stream, int direction);
+
+ // Set the file path for testing.
+ //
+ // |path| to use while running tests.
+ void SetVolumeFilePathForTesting(const base::FilePath& path);
+
+ // Initialize all the streams in the audio policy service.
+ virtual void InitAPSAllStreams();
+
+ // Generate the volume config file.
+ void GenerateVolumeFile();
+
+ // Trigger a callback when a volume button is pressed.
+ //
+ // |stream| is an audio_stream_t representing the stream.
+ // |previous_index| is the volume index before the key press. This is an
+ // absolute index from 0 - 100.
+ // |current_index| is the volume index after the key press. This is an
+ // absolute index from 0 - 100.
+ virtual void TriggerCallback(audio_stream_type_t stream,
+ int previous_index,
+ int current_index);
+
+ // Convert internal index to user defined index scale.
+ //
+ // |stream| is an audio_stream_t representing the stream.
+ // |index| is the volume index before the key press. This is an absolute
+ // index from 0 - 100.
+ //
+ // Returns an int between 0 and the user defined max.
+ int ConvertToUserDefinedIndex(audio_stream_type_t stream, int index);
+
+ // Convert user defined index to internal index scale.
+ //
+ // |stream| is an audio_stream_t representing the stream.
+ // |index| is the volume index before the key press. This is an index from 0
+ // and the user defined max.
+ //
+ // Returns an int between 0 and 100.
+ int ConvertToInternalIndex(audio_stream_type_t stream, int index);
+
+ // Stream to use for volume control.
+ audio_stream_type_t selected_stream_;
+ // File backed key-value store of the current index (as seen by the audio
+ // policy service).
+ std::unique_ptr<KeyValueStore> kv_store_;
+ // Supported stream names. The order of this vector defines the priority from
+ // high to low.
+ std::vector<audio_stream_type_t> kSupportedStreams_{
+ AUDIO_STREAM_ALARM, AUDIO_STREAM_NOTIFICATION, AUDIO_STREAM_SYSTEM,
+ AUDIO_STREAM_MUSIC};
+ // Step size for each stream. This is used to translate between user defined
+ // stream ranges and the range as seen by audio policy service. This value is
+ // not file-backed and is intended to be re-applied by the user on reboots and
+ // brilloaudioservice crashes.
+ std::map<audio_stream_type_t, double> step_sizes_;
+ // Callback to call when volume buttons are pressed.
+ base::Callback<void(audio_stream_type_t, int, int)> callback_;
+ // Key indicies.
+ const std::string kCurrentIndexKey_ = "current_index";
+ // Default values.
+ const int kMinIndex_ = 0;
+ const int kDefaultCurrentIndex_ = 30;
+ const int kMaxIndex_ = 100;
+ const int kDefaultStepSize_ = 1;
+ base::FilePath volume_state_file_;
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_AUDIO_VOLUME_HANDLER_H_
diff --git a/brillo/audio/audioservice/brillo_audio_client.cpp b/brillo/audio/audioservice/brillo_audio_client.cpp
new file mode 100644
index 0000000..4f162be
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_client.cpp
@@ -0,0 +1,224 @@
+// 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 brillo_audio_client.h
+
+#include "brillo_audio_client.h"
+
+#include <base/logging.h>
+#include <binder/Status.h>
+#include <binderwrapper/binder_wrapper.h>
+
+#include "brillo_audio_client_helpers.h"
+#include "brillo_audio_device_info_def.h"
+#include "brillo_audio_device_info_internal.h"
+
+using android::binder::Status;
+
+namespace brillo {
+
+static const char kBrilloAudioServiceName[] =
+ "android.brillo.brilloaudioservice.BrilloAudioService";
+
+std::shared_ptr<BrilloAudioClient> BrilloAudioClient::instance_ = nullptr;
+
+int BrilloAudioClient::callback_id_counter_ = 1;
+
+BrilloAudioClient::~BrilloAudioClient() {}
+
+std::weak_ptr<BrilloAudioClient> BrilloAudioClient::GetClientInstance() {
+ if (!instance_) {
+ instance_ = std::shared_ptr<BrilloAudioClient>(new BrilloAudioClient());
+ if (!instance_->Initialize()) {
+ LOG(ERROR) << "Could not Initialize the brillo audio client.";
+ instance_.reset();
+ return instance_;
+ }
+ }
+ return instance_;
+}
+
+android::sp<android::IBinder> BrilloAudioClient::ConnectToService(
+ std::string service_name, const base::Closure& callback) {
+ android::BinderWrapper* binder_wrapper =
+ android::BinderWrapper::GetOrCreateInstance();
+ auto service = binder_wrapper->GetService(service_name);
+ if (!service.get()) {
+ return service;
+ }
+ binder_wrapper->RegisterForDeathNotifications(service, callback);
+ return service;
+}
+
+void BrilloAudioClient::OnBASDisconnect() {
+ LOG(WARNING) << "The brillo audio service died! Please reset the "
+ << "BAudioManager.";
+ instance_.reset();
+}
+
+bool BrilloAudioClient::Initialize() {
+ auto service = ConnectToService(
+ kBrilloAudioServiceName, base::Bind(&BrilloAudioClient::OnBASDisconnect,
+ weak_ptr_factory_.GetWeakPtr()));
+ if (!service.get()) {
+ LOG(ERROR) << "Could not connect to brillo audio service.";
+ return false;
+ }
+ brillo_audio_service_ = android::interface_cast<IBrilloAudioService>(service);
+ return true;
+}
+
+int BrilloAudioClient::GetDevices(int flag, std::vector<int>& devices) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto status = brillo_audio_service_->GetDevices(flag, &devices);
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::SetDevice(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto status = brillo_audio_service_->SetDevice(usage, config);
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::GetMaxVolumeSteps(BAudioUsage usage, int* max_steps) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto status = brillo_audio_service_->GetMaxVolumeSteps(
+ BrilloAudioClientHelpers::GetStreamType(usage), max_steps);
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::SetMaxVolumeSteps(BAudioUsage usage, int max_steps) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto status = brillo_audio_service_->SetMaxVolumeSteps(
+ BrilloAudioClientHelpers::GetStreamType(usage), max_steps);
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::SetVolumeIndex(BAudioUsage usage,
+ audio_devices_t device,
+ int index) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto status = brillo_audio_service_->SetVolumeIndex(
+ BrilloAudioClientHelpers::GetStreamType(usage), device, index);
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::GetVolumeIndex(BAudioUsage usage,
+ audio_devices_t device,
+ int* index) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto status = brillo_audio_service_->GetVolumeIndex(
+ BrilloAudioClientHelpers::GetStreamType(usage), device, index);
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::GetVolumeControlStream(BAudioUsage* usage) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ int stream;
+ auto status = brillo_audio_service_->GetVolumeControlStream(&stream);
+ *usage = BrilloAudioClientHelpers::GetBAudioUsage(
+ static_cast<audio_stream_type_t>(stream));
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::SetVolumeControlStream(BAudioUsage usage) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto status = brillo_audio_service_->SetVolumeControlStream(
+ BrilloAudioClientHelpers::GetStreamType(usage));
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::IncrementVolume() {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto status = brillo_audio_service_->IncrementVolume();
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::DecrementVolume() {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto status = brillo_audio_service_->DecrementVolume();
+ return status.serviceSpecificErrorCode();
+}
+
+int BrilloAudioClient::RegisterAudioCallback(
+ android::sp<AudioServiceCallback> callback, int* callback_id) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ if (!brillo_audio_service_->RegisterServiceCallback(callback).isOk()) {
+ *callback_id = 0;
+ return ECONNABORTED;
+ }
+ for (auto& entry : callback_map_) {
+ if (entry.second->Equals(callback)) {
+ LOG(ERROR) << "Callback has already been registered.";
+ *callback_id = 0;
+ return EINVAL;
+ }
+ }
+ *callback_id = callback_id_counter_++;
+ callback_map_.emplace(*callback_id, callback);
+ return 0;
+}
+
+int BrilloAudioClient::UnregisterAudioCallback(int callback_id) {
+ if (!brillo_audio_service_.get()) {
+ OnBASDisconnect();
+ return ECONNABORTED;
+ }
+ auto callback_elem = callback_map_.find(callback_id);
+ if (callback_elem == callback_map_.end()) {
+ // If we were passed an invalid callback_id, do nothing.
+ LOG(ERROR) << "Unregister called with invalid callback ID.";
+ return EINVAL;
+ }
+ brillo_audio_service_->UnregisterServiceCallback(callback_elem->second.get());
+ callback_map_.erase(callback_elem);
+ return 0;
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/brillo_audio_client.h b/brillo/audio/audioservice/brillo_audio_client.h
new file mode 100644
index 0000000..d7e31f1
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_client.h
@@ -0,0 +1,183 @@
+// 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.
+//
+
+// Client for the brilloaudioservice.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_CLIENT_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_CLIENT_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <base/bind.h>
+#include <base/memory/weak_ptr.h>
+#include <gtest/gtest_prod.h>
+#include <media/IAudioPolicyService.h>
+
+#include "android/brillo/brilloaudioservice/IBrilloAudioService.h"
+#include "audio_service_callback.h"
+
+using android::brillo::brilloaudioservice::IBrilloAudioService;
+
+namespace brillo {
+
+class BrilloAudioClient {
+ public:
+ virtual ~BrilloAudioClient();
+
+ // Get or create a pointer to the client instance.
+ //
+ // Returns a weak_ptr to a BrilloAudioClient object.
+ static std::weak_ptr<BrilloAudioClient> GetClientInstance();
+
+ // Query brillo audio service to get list of connected audio devices.
+ //
+ // |flag| is an int which is either GET_DEVICES_INPUTS or GET_DEVICES_OUTPUTS.
+ // |devices| is a reference to a vector of audio_devices_t.
+ //
+ // Returns 0 on success and errno on failure.
+ int GetDevices(int flag, std::vector<int>& devices);
+
+ // Register a callback object with the service.
+ //
+ // |callback| is a ref pointer to a callback object to be register with the
+ // brillo audio service.
+ // |callback_id| is a pointer to an int that represents a callback id token on
+ // success and 0 on failure.
+ //
+ // Returns 0 on success and errno on failure.
+ int RegisterAudioCallback(android::sp<AudioServiceCallback> callback,
+ int* callback_id);
+
+ // Unregister a callback object with the service.
+ //
+ // |callback_id| is an int referring to the callback object.
+ //
+ // Returns 0 on success and errno on failure.
+ int UnregisterAudioCallback(int callback_id);
+
+ // Set a device to be the default. This does not communicate with the brillo
+ // audio service but instead communicates directly with the audio policy
+ // service.
+ //
+ // Please see system/audio_policy.h for details on these arguments.
+ //
+ // Returns 0 on success and errno on failure.
+ int SetDevice(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config);
+
+ // Get the maximum number of steps for a given BAudioUsage.
+ //
+ // |usage| is an enum of type BAudioUsage.
+ // |max_steps| is a pointer to the maximum number of steps.
+ //
+ // Returns 0 on success and errno on failure.
+ int GetMaxVolumeSteps(BAudioUsage usage, int* max_steps);
+
+ // Set the maximum number of steps to use for a given BAudioUsage.
+ //
+ // |usage| is an enum of type BAudioUsage.
+ // |max_steps| is an int between 0 and 100.
+ //
+ // Returns 0 on success and errno on failure.
+ int SetMaxVolumeSteps(BAudioUsage usage, int max_steps);
+
+ // Set the volume index for a given BAudioUsage and device.
+ //
+ // |usage| is an enum of type BAudioUsage.
+ // |device| is of type audio_devices_t.
+ // |index| is an int representing the current index.
+ //
+ // Returns 0 on success and errno on failure.
+ int SetVolumeIndex(BAudioUsage usage, audio_devices_t device, int index);
+
+ // Get the volume index for a given BAudioUsage and device.
+ //
+ // |usage| is an enum of type BAudioUsage.
+ // |device| is of type audio_devices_t.
+ // |index| is a pointer to an int representing the current index.
+ //
+ // Returns 0 on success and errno on failure.
+ int GetVolumeIndex(BAudioUsage usage, audio_devices_t device, int* index);
+
+ // Get default stream to use for volume buttons.
+ //
+ // |usage| is a pointer to a BAudioUsage.
+ //
+ // Returns 0 on success and errno on failure.
+ int GetVolumeControlStream(BAudioUsage* usage);
+
+ // Set default stream to use for volume buttons.
+ //
+ // |usage| is an enum of type BAudioUsage.
+ //
+ // Returns 0 on success and errno on failure.
+ int SetVolumeControlStream(BAudioUsage usage);
+
+ // Increment the volume.
+ //
+ // Returns 0 on success and errno on failure.
+ int IncrementVolume();
+
+ // Decrement the volume.
+ //
+ // Returns 0 on success and errno on failure.
+ int DecrementVolume();
+
+ protected:
+ BrilloAudioClient() = default;
+
+ private:
+ friend class BrilloAudioClientTest;
+ FRIEND_TEST(BrilloAudioClientTest, InitializeNoService);
+ FRIEND_TEST(BrilloAudioClientTest,
+ CheckInitializeRegistersForDeathNotifications);
+
+ // Initialize the BrilloAudioClient object and connects to the brillo audio
+ // service and the audio policy service. It also registers for death
+ // notifications.
+ bool Initialize();
+
+ // Callback to be triggered when the brillo audio service dies. It attempts to
+ // reconnect to the service.
+ virtual void OnBASDisconnect();
+
+ // Helper method to connect to a service and register a callback to receive
+ // death notifications.
+ //
+ // |service_name| is a string representing the name of the service.
+ // |callback| is a base::Closure which will be called if the service dies.
+ android::sp<android::IBinder> ConnectToService(std::string service_name,
+ const base::Closure& callback);
+
+ // Pointer to the BrilloAudioClient object.
+ static std::shared_ptr<BrilloAudioClient> instance_;
+
+ // Used to generate weak_ptr to BrilloAudioClient for use in base::Bind.
+ base::WeakPtrFactory<BrilloAudioClient> weak_ptr_factory_{this};
+ // Pointer to the brillo audio service.
+ android::sp<IBrilloAudioService> brillo_audio_service_;
+ // Counter for callback IDs.
+ static int callback_id_counter_;
+ // Map of callback ids to callback objects.
+ std::map<int, android::sp<AudioServiceCallback> > callback_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrilloAudioClient);
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_CLIENT_H_
diff --git a/brillo/audio/audioservice/brillo_audio_client_helpers.cpp b/brillo/audio/audioservice/brillo_audio_client_helpers.cpp
new file mode 100644
index 0000000..871c7a9
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_client_helpers.cpp
@@ -0,0 +1,59 @@
+// 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.
+//
+
+#include "brillo_audio_client_helpers.h"
+
+namespace brillo {
+
+audio_policy_force_use_t BrilloAudioClientHelpers::GetForceUse(
+ BAudioUsage usage) {
+ if (usage == kUsageMedia)
+ return AUDIO_POLICY_FORCE_FOR_MEDIA;
+ else
+ return AUDIO_POLICY_FORCE_FOR_SYSTEM;
+}
+
+audio_stream_type_t BrilloAudioClientHelpers::GetStreamType(BAudioUsage usage) {
+ switch (usage) {
+ case kUsageAlarm:
+ return AUDIO_STREAM_ALARM;
+ case kUsageMedia:
+ return AUDIO_STREAM_MUSIC;
+ case kUsageNotifications:
+ return AUDIO_STREAM_NOTIFICATION;
+ case kUsageSystem:
+ return AUDIO_STREAM_SYSTEM;
+ default:
+ return AUDIO_STREAM_DEFAULT;
+ }
+}
+
+BAudioUsage BrilloAudioClientHelpers::GetBAudioUsage(
+ audio_stream_type_t stream) {
+ switch (stream) {
+ case AUDIO_STREAM_ALARM:
+ return kUsageAlarm;
+ case AUDIO_STREAM_MUSIC:
+ return kUsageMedia;
+ case AUDIO_STREAM_NOTIFICATION:
+ return kUsageNotifications;
+ case AUDIO_STREAM_SYSTEM:
+ return kUsageSystem;
+ default:
+ return kUsageInvalid;
+ }
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/brillo_audio_client_helpers.h b/brillo/audio/audioservice/brillo_audio_client_helpers.h
new file mode 100644
index 0000000..a5bb7ba
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_client_helpers.h
@@ -0,0 +1,38 @@
+// 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.
+//
+
+// Helpers for the brillo audio client.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_CLIENT_HELPERS_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_CLIENT_HELPERS_H_
+
+#include <gtest/gtest_prod.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+
+#include "include/brillo_audio_manager.h"
+
+namespace brillo {
+
+class BrilloAudioClientHelpers {
+ public:
+ static audio_policy_force_use_t GetForceUse(BAudioUsage usage);
+ static audio_stream_type_t GetStreamType(BAudioUsage usage);
+ static BAudioUsage GetBAudioUsage(audio_stream_type_t stream);
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_CLIENT_HELPERS_H_
diff --git a/brillo/audio/audioservice/brillo_audio_device_info.cpp b/brillo/audio/audioservice/brillo_audio_device_info.cpp
new file mode 100644
index 0000000..611bcc5
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_device_info.cpp
@@ -0,0 +1,38 @@
+// 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 brillo_audio_device_info.h.
+
+#include "include/brillo_audio_device_info.h"
+
+#include "brillo_audio_device_info_def.h"
+#include "brillo_audio_device_info_internal.h"
+
+using brillo::BAudioDeviceInfoInternal;
+
+BAudioDeviceInfo* BAudioDeviceInfo_new(int device) {
+ BAudioDeviceInfo* audio_device_info = new BAudioDeviceInfo;
+ audio_device_info->internal_ =
+ std::make_unique<BAudioDeviceInfoInternal>(device);
+ return audio_device_info;
+}
+
+int BAudioDeviceInfo_getType(BAudioDeviceInfo* device) {
+ return device->internal_->GetDeviceId();
+}
+
+void BAudioDeviceInfo_delete(BAudioDeviceInfo* device) {
+ delete device;
+}
diff --git a/brillo/audio/audioservice/brillo_audio_device_info_def.h b/brillo/audio/audioservice/brillo_audio_device_info_def.h
new file mode 100644
index 0000000..3bf1f66
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_device_info_def.h
@@ -0,0 +1,33 @@
+// 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.
+//
+
+// Definition of BAudioDeviceInfo.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_DEVICE_INFO_DEF_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_DEVICE_INFO_DEF_H_
+
+
+#include <memory>
+
+#include "brillo_audio_device_info_internal.h"
+#include "include/brillo_audio_device_info.h"
+
+using brillo::BAudioDeviceInfoInternal;
+
+struct BAudioDeviceInfo {
+ std::unique_ptr<BAudioDeviceInfoInternal> internal_;
+};
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_DEVICE_INFO_DEF_H_
diff --git a/brillo/audio/audioservice/brillo_audio_device_info_internal.cpp b/brillo/audio/audioservice/brillo_audio_device_info_internal.cpp
new file mode 100644
index 0000000..215da21
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_device_info_internal.cpp
@@ -0,0 +1,89 @@
+// 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.
+//
+
+// Internal helpers for BAudioDeviceInfo.
+
+#include "brillo_audio_device_info_internal.h"
+
+#include <base/logging.h>
+
+#include "brillo_audio_device_info_def.h"
+
+namespace brillo {
+
+BAudioDeviceInfoInternal::BAudioDeviceInfoInternal(int device_id) {
+ device_id_ = device_id;
+}
+
+int BAudioDeviceInfoInternal::GetDeviceId() {
+ return device_id_;
+}
+
+audio_policy_forced_cfg_t BAudioDeviceInfoInternal::GetConfig() {
+ switch (device_id_) {
+ case TYPE_BUILTIN_SPEAKER:
+ return AUDIO_POLICY_FORCE_SPEAKER;
+ case TYPE_WIRED_HEADSET:
+ return AUDIO_POLICY_FORCE_HEADPHONES;
+ case TYPE_WIRED_HEADSET_MIC:
+ return AUDIO_POLICY_FORCE_HEADPHONES;
+ case TYPE_WIRED_HEADPHONES:
+ return AUDIO_POLICY_FORCE_HEADPHONES;
+ case TYPE_BUILTIN_MIC:
+ return AUDIO_POLICY_FORCE_NONE;
+ default:
+ return AUDIO_POLICY_FORCE_NONE;
+ }
+}
+
+audio_devices_t BAudioDeviceInfoInternal::GetAudioDevicesT() {
+ switch (device_id_) {
+ case TYPE_BUILTIN_SPEAKER:
+ return AUDIO_DEVICE_OUT_SPEAKER;
+ case TYPE_WIRED_HEADSET:
+ return AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ case TYPE_WIRED_HEADSET_MIC:
+ return AUDIO_DEVICE_IN_WIRED_HEADSET;
+ case TYPE_WIRED_HEADPHONES:
+ return AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ case TYPE_BUILTIN_MIC:
+ return AUDIO_DEVICE_IN_BUILTIN_MIC;
+ default:
+ return AUDIO_DEVICE_NONE;
+ }
+}
+
+BAudioDeviceInfoInternal* BAudioDeviceInfoInternal::CreateFromAudioDevicesT(
+ unsigned int device) {
+ int device_id = TYPE_UNKNOWN;
+ switch (device) {
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ device_id = TYPE_WIRED_HEADSET;
+ break;
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ device_id = TYPE_WIRED_HEADPHONES;
+ break;
+ case AUDIO_DEVICE_IN_WIRED_HEADSET:
+ device_id = TYPE_WIRED_HEADSET_MIC;
+ break;
+ }
+ if (device_id == TYPE_UNKNOWN) {
+ LOG(ERROR) << "Unsupported device.";
+ return nullptr;
+ }
+ return new BAudioDeviceInfoInternal(device_id);
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/brillo_audio_device_info_internal.h b/brillo/audio/audioservice/brillo_audio_device_info_internal.h
new file mode 100644
index 0000000..0eaaab4
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_device_info_internal.h
@@ -0,0 +1,74 @@
+// 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.
+//
+
+// Internal class to represent BAudioDeviceInfo.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_DEVICE_INFO_INTERNAL_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_DEVICE_INFO_INTERNAL_H_
+
+#include <vector>
+
+#include <gtest/gtest_prod.h>
+#include <hardware/audio_policy.h>
+
+#include "include/brillo_audio_device_info.h"
+
+namespace brillo {
+
+class BAudioDeviceInfoInternal {
+ public:
+ // Constructor for BAudioDeviceInfoInternal.
+ //
+ // |device_id| is an integer representing an audio device type as defined in
+ // brillo_audio_device_info.h.
+ BAudioDeviceInfoInternal(int device_id);
+
+ // Get audio policy config.
+ //
+ // Returns an audio_policy_forced_cfg_t.
+ audio_policy_forced_cfg_t GetConfig();
+
+ // Create a BAudioDeviceInfoInternal object from a audio_devices_t device
+ // type.
+ //
+ // |devices_t| is an audio device of type audio_devices_t which is represented
+ // using an int.
+ //
+ // Returns a pointer to a BAudioDeviceInfoInternal that has been created.
+ static BAudioDeviceInfoInternal* CreateFromAudioDevicesT(unsigned int device);
+
+ // Get the device id.
+ //
+ // Returns an int which is the device_id.
+ int GetDeviceId();
+
+ // Get audio_devices_t that corresponds to device_id;
+ //
+ // Returns an audio_devices_t.
+ audio_devices_t GetAudioDevicesT();
+
+ private:
+ FRIEND_TEST(BrilloAudioDeviceInfoInternalTest, InWiredHeadset);
+ FRIEND_TEST(BrilloAudioDeviceInfoInternalTest, OutWiredHeadset);
+ FRIEND_TEST(BrilloAudioDeviceInfoInternalTest, OutWiredHeadphone);
+
+ // An int representing the underlying audio device. The int is one of the
+ // constants defined in brillo_audio_device_info.h.
+ int device_id_;
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_DEVICE_INFO_INTERNAL_H_
diff --git a/brillo/audio/audioservice/brillo_audio_manager.cpp b/brillo/audio/audioservice/brillo_audio_manager.cpp
new file mode 100644
index 0000000..4c09824
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_manager.cpp
@@ -0,0 +1,227 @@
+ // 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 brillo_audio_manager.h.
+
+#include "include/brillo_audio_manager.h"
+
+#include <memory>
+#include <stdlib.h>
+
+#include "audio_service_callback.h"
+#include "brillo_audio_client.h"
+#include "brillo_audio_client_helpers.h"
+#include "brillo_audio_device_info_def.h"
+#include "brillo_audio_device_info_internal.h"
+
+using brillo::AudioServiceCallback;
+using brillo::BrilloAudioClient;
+using brillo::BrilloAudioClientHelpers;
+
+struct BAudioManager {
+ std::weak_ptr<BrilloAudioClient> client_;
+};
+
+BAudioManager* BAudioManager_new() {
+ auto client = BrilloAudioClient::GetClientInstance();
+ if (!client.lock())
+ return nullptr;
+ BAudioManager* bam = new BAudioManager;
+ bam->client_ = client;
+ return bam;
+}
+
+int BAudioManager_getDevices(
+ const BAudioManager* brillo_audio_manager, int flag,
+ BAudioDeviceInfo* device_array[], unsigned int size,
+ unsigned int* num_devices) {
+ if (!brillo_audio_manager || !num_devices ||
+ (flag != GET_DEVICES_INPUTS && flag != GET_DEVICES_OUTPUTS))
+ return EINVAL;
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client) {
+ *num_devices = 0;
+ return ECONNABORTED;
+ }
+ std::vector<int> devices;
+ auto rc = client->GetDevices(flag, devices);
+ if (rc) {
+ *num_devices = 0;
+ return rc;
+ }
+ unsigned int num_elems = (devices.size() < size) ? devices.size() : size;
+ for (size_t i = 0; i < num_elems; i++) {
+ device_array[i] = new BAudioDeviceInfo;
+ device_array[i]->internal_ = std::unique_ptr<BAudioDeviceInfoInternal>(
+ BAudioDeviceInfoInternal::CreateFromAudioDevicesT(devices[i]));
+ }
+ *num_devices = devices.size();
+ return 0;
+}
+
+int BAudioManager_setInputDevice(const BAudioManager* brillo_audio_manager,
+ const BAudioDeviceInfo* device) {
+ if (!brillo_audio_manager || !device)
+ return EINVAL;
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client) {
+ return ECONNABORTED;
+ }
+ return client->SetDevice(AUDIO_POLICY_FORCE_FOR_RECORD,
+ device->internal_->GetConfig());
+}
+
+int BAudioManager_setOutputDevice(
+ const BAudioManager* brillo_audio_manager, const BAudioDeviceInfo* device,
+ BAudioUsage usage) {
+ if (!brillo_audio_manager || !device)
+ return EINVAL;
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client)
+ return ECONNABORTED;
+ return client->SetDevice(BrilloAudioClientHelpers::GetForceUse(usage),
+ device->internal_->GetConfig());
+}
+
+int BAudioManager_getMaxVolumeSteps(const BAudioManager* brillo_audio_manager,
+ BAudioUsage usage,
+ int* max_steps) {
+ if (!brillo_audio_manager || !max_steps)
+ return EINVAL;
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client)
+ return ECONNABORTED;
+ return client->GetMaxVolumeSteps(usage, max_steps);
+}
+
+int BAudioManager_setMaxVolumeSteps(const BAudioManager* brillo_audio_manager,
+ BAudioUsage usage,
+ int max_steps) {
+ if (!brillo_audio_manager || max_steps < 0 || max_steps > 100)
+ return EINVAL;
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client)
+ return ECONNABORTED;
+ return client->SetMaxVolumeSteps(usage, max_steps);
+}
+
+int BAudioManager_setVolumeIndex(const BAudioManager* brillo_audio_manager,
+ BAudioUsage usage,
+ const BAudioDeviceInfo* device,
+ int index) {
+ if (!brillo_audio_manager || !device) {
+ return EINVAL;
+ }
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client) {
+ return ECONNABORTED;
+ }
+ return client->SetVolumeIndex(
+ usage, device->internal_->GetAudioDevicesT(), index);
+}
+
+int BAudioManager_getVolumeIndex(const BAudioManager* brillo_audio_manager,
+ BAudioUsage usage,
+ const BAudioDeviceInfo* device,
+ int* index) {
+ if (!brillo_audio_manager || !device || !index) {
+ return EINVAL;
+ }
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client) {
+ return ECONNABORTED;
+ }
+ return client->GetVolumeIndex(
+ usage, device->internal_->GetAudioDevicesT(), index);
+}
+
+int BAudioManager_getVolumeControlUsage(
+ const BAudioManager* brillo_audio_manager, BAudioUsage* usage) {
+ if (!brillo_audio_manager || !usage) {
+ return EINVAL;
+ }
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client) {
+ return ECONNABORTED;
+ }
+ return client->GetVolumeControlStream(usage);
+}
+
+int BAudioManager_setVolumeControlUsage(
+ const BAudioManager* brillo_audio_manager, BAudioUsage usage) {
+ if (!brillo_audio_manager) {
+ return EINVAL;
+ }
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client) {
+ return ECONNABORTED;
+ }
+ return client->SetVolumeControlStream(usage);
+}
+
+int BAudioManager_incrementVolume(const BAudioManager* brillo_audio_manager) {
+ if (!brillo_audio_manager) {
+ return EINVAL;
+ }
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client) {
+ return ECONNABORTED;
+ }
+ return client->IncrementVolume();
+}
+
+int BAudioManager_decrementVolume(const BAudioManager* brillo_audio_manager) {
+ if (!brillo_audio_manager) {
+ return EINVAL;
+ }
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client) {
+ return ECONNABORTED;
+ }
+ return client->DecrementVolume();
+}
+
+int BAudioManager_registerAudioCallback(
+ const BAudioManager* brillo_audio_manager, const BAudioCallback* callback,
+ void* user_data, int* callback_id) {
+ if (!brillo_audio_manager || !callback || !callback_id)
+ return EINVAL;
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client) {
+ *callback_id = 0;
+ return ECONNABORTED;
+ }
+ // This copies the BAudioCallback into AudioServiceCallback so the
+ // BAudioCallback can be safely deleted.
+ return client->RegisterAudioCallback(
+ new AudioServiceCallback(callback, user_data), callback_id);
+}
+
+int BAudioManager_unregisterAudioCallback(
+ const BAudioManager* brillo_audio_manager, int callback_id) {
+ if (!brillo_audio_manager)
+ return EINVAL;
+ auto client = brillo_audio_manager->client_.lock();
+ if (!client)
+ return ECONNABORTED;
+ return client->UnregisterAudioCallback(callback_id);
+}
+
+int BAudioManager_delete(BAudioManager* brillo_audio_manager) {
+ if (!brillo_audio_manager)
+ return EINVAL;
+ delete brillo_audio_manager;
+ return 0;
+}
diff --git a/brillo/audio/audioservice/brillo_audio_service.h b/brillo/audio/audioservice/brillo_audio_service.h
new file mode 100644
index 0000000..87ca0d7
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_service.h
@@ -0,0 +1,87 @@
+// 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.
+//
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_SERVICE_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_SERVICE_H_
+
+#include "android/brillo/brilloaudioservice/BnBrilloAudioService.h"
+
+#include <memory>
+#include <set>
+#include <vector>
+
+#include <binder/Status.h>
+
+#include "android/brillo/brilloaudioservice/IAudioServiceCallback.h"
+#include "audio_device_handler.h"
+#include "audio_volume_handler.h"
+
+using android::binder::Status;
+using android::brillo::brilloaudioservice::BnBrilloAudioService;
+using android::brillo::brilloaudioservice::IAudioServiceCallback;
+
+namespace brillo {
+
+class BrilloAudioService : public BnBrilloAudioService {
+ public:
+ virtual ~BrilloAudioService() {}
+
+ // From AIDL.
+ virtual Status GetDevices(int flag, std::vector<int>* _aidl_return) = 0;
+ virtual Status SetDevice(int usage, int config) = 0;
+ virtual Status GetMaxVolumeSteps(int stream, int* _aidl_return) = 0;
+ virtual Status SetMaxVolumeSteps(int stream, int max_steps) = 0;
+ virtual Status SetVolumeIndex(int stream, int device, int index) = 0;
+ virtual Status GetVolumeIndex(int stream, int device, int* _aidl_return) = 0;
+ virtual Status GetVolumeControlStream(int* _aidl_return) = 0;
+ virtual Status SetVolumeControlStream(int stream) = 0;
+ virtual Status IncrementVolume() = 0;
+ virtual Status DecrementVolume() = 0;
+ virtual Status RegisterServiceCallback(
+ const android::sp<IAudioServiceCallback>& callback) = 0;
+ virtual Status UnregisterServiceCallback(
+ const android::sp<IAudioServiceCallback>& callback) = 0;
+
+ // Register daemon handlers.
+ //
+ // |audio_device_handler| is a weak pointer to an audio device handler object.
+ // |audio_volume_handler| is a weak pointer to an audio volume handler object.
+ virtual void RegisterHandlers(
+ std::weak_ptr<AudioDeviceHandler> audio_device_handler,
+ std::weak_ptr<AudioVolumeHandler> audio_volume_handler) = 0;
+
+ // Callback to be called when a device is connected.
+ //
+ // |devices| is a vector of ints representing the audio_devices_t.
+ virtual void OnDevicesConnected(const std::vector<int>& device) = 0;
+
+ // Callback to be called when a device is disconnected.
+ //
+ // |devices| is a vector of ints representing the audio_devices_t.
+ virtual void OnDevicesDisconnected(const std::vector<int>& device) = 0;
+
+ // Callback to be called when the volume is changed.
+ //
+ // |stream| is an audio_stream_type_t representing the stream.
+ // |previous_index| is the volume index before the key press.
+ // |current_index| is the volume index after the key press.
+ virtual void OnVolumeChanged(audio_stream_type_t stream,
+ int previous_index,
+ int current_index) = 0;
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_SERVICE_H_
diff --git a/brillo/audio/audioservice/brillo_audio_service_impl.cpp b/brillo/audio/audioservice/brillo_audio_service_impl.cpp
new file mode 100644
index 0000000..d108a4a
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_service_impl.cpp
@@ -0,0 +1,193 @@
+// 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 brillo_audio_service_impl.h
+
+#include "brillo_audio_service_impl.h"
+
+using android::binder::Status;
+
+namespace brillo {
+
+Status BrilloAudioServiceImpl::GetDevices(int flag,
+ std::vector<int>* _aidl_return) {
+ auto device_handler = audio_device_handler_.lock();
+ if (!device_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio device handler died."));
+ }
+ if (flag == BrilloAudioService::GET_DEVICES_INPUTS) {
+ device_handler->GetInputDevices(_aidl_return);
+ } else if (flag == BrilloAudioService::GET_DEVICES_OUTPUTS) {
+ device_handler->GetOutputDevices(_aidl_return);
+ } else {
+ return Status::fromServiceSpecificError(EINVAL,
+ android::String8("Invalid flag."));
+ }
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::SetDevice(int usage, int config) {
+ auto device_handler = audio_device_handler_.lock();
+ if (!device_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio device handler died."));
+ }
+ int rc =
+ device_handler->SetDevice(static_cast<audio_policy_force_use_t>(usage),
+ static_cast<audio_policy_forced_cfg_t>(config));
+ if (rc) return Status::fromServiceSpecificError(rc);
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::RegisterServiceCallback(
+ const android::sp<IAudioServiceCallback>& callback) {
+ callbacks_set_.insert(callback);
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::UnregisterServiceCallback(
+ const android::sp<IAudioServiceCallback>& callback) {
+ callbacks_set_.erase(callback);
+ return Status::ok();
+}
+
+void BrilloAudioServiceImpl::RegisterHandlers(
+ std::weak_ptr<AudioDeviceHandler> audio_device_handler,
+ std::weak_ptr<AudioVolumeHandler> audio_volume_handler) {
+ audio_device_handler_ = audio_device_handler;
+ audio_volume_handler_ = audio_volume_handler;
+}
+
+Status BrilloAudioServiceImpl::GetMaxVolumeSteps(int stream,
+ int* _aidl_return) {
+ auto volume_handler = audio_volume_handler_.lock();
+ if (!volume_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio volume handler died."));
+ }
+ *_aidl_return = volume_handler->GetVolumeMaxSteps(
+ static_cast<audio_stream_type_t>(stream));
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::SetMaxVolumeSteps(int stream, int max_steps) {
+ auto volume_handler = audio_volume_handler_.lock();
+ if (!volume_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio volume handler died."));
+ }
+ int rc = volume_handler->SetVolumeMaxSteps(
+ static_cast<audio_stream_type_t>(stream), max_steps);
+ if (rc)
+ return Status::fromServiceSpecificError(rc);
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::SetVolumeIndex(int stream,
+ int device,
+ int index) {
+ auto volume_handler = audio_volume_handler_.lock();
+ if (!volume_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio volume handler died."));
+ }
+ int rc =
+ volume_handler->SetVolumeIndex(static_cast<audio_stream_type_t>(stream),
+ static_cast<audio_devices_t>(device),
+ index);
+ if (rc)
+ return Status::fromServiceSpecificError(rc);
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::GetVolumeIndex(int stream,
+ int device,
+ int* _aidl_return) {
+ auto volume_handler = audio_volume_handler_.lock();
+ if (!volume_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio volume handler died."));
+ }
+ *_aidl_return =
+ volume_handler->GetVolumeIndex(static_cast<audio_stream_type_t>(stream),
+ static_cast<audio_devices_t>(device));
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::IncrementVolume() {
+ auto volume_handler = audio_volume_handler_.lock();
+ if (!volume_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio volume handler died."));
+ }
+ volume_handler->AdjustVolumeActiveStreams(1);
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::GetVolumeControlStream(int* _aidl_return) {
+ auto volume_handler = audio_volume_handler_.lock();
+ if (!volume_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio volume handler died."));
+ }
+ *_aidl_return = volume_handler->GetVolumeControlStream();
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::SetVolumeControlStream(int stream) {
+ auto volume_handler = audio_volume_handler_.lock();
+ if (!volume_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio volume handler died."));
+ }
+ volume_handler->SetVolumeControlStream(
+ static_cast<audio_stream_type_t>(stream));
+ return Status::ok();
+}
+
+Status BrilloAudioServiceImpl::DecrementVolume() {
+ auto volume_handler = audio_volume_handler_.lock();
+ if (!volume_handler) {
+ return Status::fromServiceSpecificError(
+ EREMOTEIO, android::String8("The audio volume handler died."));
+ }
+ volume_handler->AdjustVolumeActiveStreams(-1);
+ return Status::ok();
+}
+
+void BrilloAudioServiceImpl::OnDevicesConnected(
+ const std::vector<int>& devices) {
+ for (auto callback : callbacks_set_) {
+ callback->OnAudioDevicesConnected(devices);
+ }
+}
+
+void BrilloAudioServiceImpl::OnDevicesDisconnected(
+ const std::vector<int>& devices) {
+ for (auto callback : callbacks_set_) {
+ callback->OnAudioDevicesDisconnected(devices);
+ }
+}
+
+void BrilloAudioServiceImpl::OnVolumeChanged(audio_stream_type_t stream,
+ int previous_index,
+ int current_index) {
+ for (auto callback : callbacks_set_) {
+ callback->OnVolumeChanged(stream, previous_index, current_index);
+ }
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/brillo_audio_service_impl.h b/brillo/audio/audioservice/brillo_audio_service_impl.h
new file mode 100644
index 0000000..af53b66
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_service_impl.h
@@ -0,0 +1,83 @@
+// 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.
+//
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_SERVICE_IMPL_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_SERVICE_IMPL_H_
+
+// Server side implementation of brillo audio service.
+
+#include "brillo_audio_service.h"
+
+namespace brillo {
+
+class BrilloAudioServiceImpl : public BrilloAudioService {
+ public:
+ ~BrilloAudioServiceImpl() = default;
+
+ // From AIDL.
+ Status GetDevices(int flag, std::vector<int>* _aidl_return) override;
+ Status SetDevice(int usage, int config) override;
+ Status GetMaxVolumeSteps(int stream, int* _aidl_return) override;
+ Status SetMaxVolumeSteps(int stream, int max_steps) override;
+ Status SetVolumeIndex(int stream, int device, int index) override;
+ Status GetVolumeIndex(int stream, int device, int* _aidl_return) override;
+ Status GetVolumeControlStream(int* _aidl_return) override;
+ Status SetVolumeControlStream(int stream) override;
+ Status IncrementVolume() override;
+ Status DecrementVolume() override;
+ Status RegisterServiceCallback(
+ const android::sp<IAudioServiceCallback>& callback) override;
+ Status UnregisterServiceCallback(
+ const android::sp<IAudioServiceCallback>& callback) override;
+
+ // Register daemon handlers.
+ //
+ // |audio_device_handler| is a weak pointer to an audio device handler object.
+ // |audio_volume_handler| is a weak pointer to an audio volume handler object.
+ void RegisterHandlers(
+ std::weak_ptr<AudioDeviceHandler> audio_device_handler,
+ std::weak_ptr<AudioVolumeHandler> audio_volume_handler) override;
+
+ // Callback to be called when a device is connected.
+ //
+ // |devices| is a vector of ints representing the audio_devices_t.
+ void OnDevicesConnected(const std::vector<int>& device) override;
+
+ // Callback to be called when a device is disconnected.
+ //
+ // |devices| is a vector of ints representing the audio_devices_t.
+ void OnDevicesDisconnected(const std::vector<int>& device) override;
+
+ // Callback to be called when volume is changed.
+ //
+ // |stream| is an int representing the stream.
+ // |previous_index| is the volume index before the key press.
+ // |current_index| is the volume index after the key press.
+ void OnVolumeChanged(audio_stream_type_t stream,
+ int previous_index,
+ int current_index) override;
+
+ private:
+ // A weak pointer to the audio device handler.
+ std::weak_ptr<AudioDeviceHandler> audio_device_handler_;
+ // A weak pointer to the audio volume handler.
+ std::weak_ptr<AudioVolumeHandler> audio_volume_handler_;
+ // List of all callbacks objects registered with the service.
+ std::set<android::sp<IAudioServiceCallback> > callbacks_set_;
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_SERVICE_IMPL_H_
diff --git a/brillo/audio/audioservice/brilloaudioserv.rc b/brillo/audio/audioservice/brilloaudioserv.rc
index a9b3898..0595c33 100644
--- a/brillo/audio/audioservice/brilloaudioserv.rc
+++ b/brillo/audio/audioservice/brilloaudioserv.rc
@@ -1,4 +1,4 @@
service brilloaudioserv /system/bin/brilloaudioservice
class late_start
- user system
+ user audioserver
group input
diff --git a/brillo/audio/audioservice/include/brillo_audio_device_info.h b/brillo/audio/audioservice/include/brillo_audio_device_info.h
new file mode 100644
index 0000000..5c386b4
--- /dev/null
+++ b/brillo/audio/audioservice/include/brillo_audio_device_info.h
@@ -0,0 +1,74 @@
+// 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.
+//
+
+// Type to represent audio devices in a brillo system.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_DEVICE_INFO_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_DEVICE_INFO_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+struct BAudioDeviceInfo;
+
+typedef struct BAudioDeviceInfo BAudioDeviceInfo;
+
+// A device type associated with an unknown or uninitialized device.
+static const int TYPE_UNKNOWN = 0;
+
+// A device type describing the speaker system (i.e. a mono speaker or stereo
+// speakers) built in a device.
+static const int TYPE_BUILTIN_SPEAKER = 1;
+
+// A device type describing a headset, which is the combination of a headphones
+// and microphone. This type represents just the transducer in the headset.
+static const int TYPE_WIRED_HEADSET = 2;
+
+// A device type describing a headset, which is the combination of a headphones
+// and microphone. This type represents the microphone in the headset.
+static const int TYPE_WIRED_HEADSET_MIC = 3;
+
+// A device type describing a pair of wired headphones.
+static const int TYPE_WIRED_HEADPHONES = 4;
+
+// A device type describing the microphone(s) built in a device.
+static const int TYPE_BUILTIN_MIC = 5;
+
+// Create a BAudioDeviceInfo based on a type described above.
+//
+// Arg:
+// device: An int representing an audio type as defined above.
+//
+// Returns a pointer to a BAudioDeviceInfo object.
+BAudioDeviceInfo* BAudioDeviceInfo_new(int device);
+
+// Get the type of the device.
+//
+// Arg:
+// device: A pointer to a BAudioDeviceInfo object to be freed.
+//
+// Returns an int representing the type of the device.
+int BAudioDeviceInfo_getType(BAudioDeviceInfo* device);
+
+// Free a BAudioDeviceInfo.
+//
+// Arg:
+// device: A pointer to a BAudioDeviceInfo object to be freed.
+void BAudioDeviceInfo_delete(BAudioDeviceInfo* device);
+
+__END_DECLS
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_DEVICE_INFO_H_
diff --git a/brillo/audio/audioservice/include/brillo_audio_manager.h b/brillo/audio/audioservice/include/brillo_audio_manager.h
new file mode 100644
index 0000000..ff80daa
--- /dev/null
+++ b/brillo/audio/audioservice/include/brillo_audio_manager.h
@@ -0,0 +1,258 @@
+// 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.
+//
+
+// Class to manage audio devices in Brillo.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_MANAGER_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_MANAGER_H_
+
+#include <sys/cdefs.h>
+
+#include "brillo_audio_device_info.h"
+
+__BEGIN_DECLS
+
+struct BAudioManager;
+
+typedef struct BAudioManager BAudioManager;
+
+// Get a pointer to a BAudioManager. This object will refer to the same
+// underlying client object no matter how many times it is called.
+//
+// Returns a pointer to a BAudioManager. Returns NULL on failure.
+BAudioManager* BAudioManager_new();
+
+// Flag to get input devices.
+static const int GET_DEVICES_INPUTS = 1;
+// Flag to get output devices.
+static const int GET_DEVICES_OUTPUTS = 2;
+
+// Returns the list of input/output devices connected to the system.
+//
+// Arg:
+// brillo_audio_manager: A pointer to a BAudioManager.
+// flag: Either GET_DEVICES_INPUTS or GET_DEVICES_OUTPUTS.
+// device_array: An array of BAudioDeviceInfo pointers. The caller has to
+// allocate this array.
+// size: The size of device_array.
+// num_devices: A pointer to an unsigned int which will represent the number
+// of audio devices connected to the device.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_getDevices(
+ const BAudioManager* brillo_audio_manager, int flag,
+ BAudioDeviceInfo* device_array[], unsigned int size,
+ unsigned int* num_devices);
+
+// Select the input device to be used for recording.
+//
+// Arg:
+// brillo_audio_manager: A pointer to a BAudioManager.
+// device: Device to set as the input device. Note that the device has to be
+// an input device.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_setInputDevice(const BAudioManager* brillo_audio_manager,
+ const BAudioDeviceInfo* device);
+
+// Usage types.
+enum BAudioUsage {
+ kUsageAlarm,
+ kUsageMedia,
+ kUsageNotifications,
+ kUsageSystem,
+ kUsageInvalid
+};
+
+// Select the output device to be used for playback.
+//
+// Arg:
+// brillo_audio_manager: A pointer to a BAudioManager.
+// device: Device to set as the output device. Note that the device has to
+// be an output device.
+// usage: A BAudioUsage type representing a usage to route to |device|.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_setOutputDevice(
+ const BAudioManager* brillo_audio_manager, const BAudioDeviceInfo* device,
+ BAudioUsage usage);
+
+// Get the number of steps for a given stream type.
+//
+// Args:
+// brillo_audio_manager: A pointer to a BAudioManager object.
+// usage: A BAudioUsage representing the audio stream.
+// max_steps: A pointer to an int representing the number of steps for a given
+// usage.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_getMaxVolumeSteps(const BAudioManager* brillo_audio_manager,
+ BAudioUsage usage,
+ int* max_steps);
+
+// Set the number of steps for a given stream type.
+//
+// Args:
+// brillo_audio_manager: A pointer to a BAudioManager object.
+// usage: A BAudioUsage representing the audio stream.
+// max_steps: An int representing the number of steps to use for a given
+// usage.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_setMaxVolumeSteps(const BAudioManager* brillo_audio_manager,
+ BAudioUsage usage,
+ int max_steps);
+
+// Set the volume for a given stream type.
+//
+// Args:
+// brillo_audio_manager: A pointer to a BAudioManager object.
+// usage: A BAudioUsage representing the audio stream.
+// device: A pointer to a BAudioDeviceInfo object.
+// value: An int representing the index to set the volume to. The index must
+// be less than max_steps if BAudioManager_setMaxVolumeSteps was
+// called or 100 otherwise.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_setVolumeIndex(const BAudioManager* brillo_audio_manager,
+ BAudioUsage usage,
+ const BAudioDeviceInfo* device,
+ int index);
+
+// Get the volume for a given stream type.
+//
+// Args:
+// brillo_audio_manager: A pointer to a BAudioManager object.
+// usage: A BAudioUsage representing the audio stream.
+// device: A pointer to a BAudioDeviceInfo object.
+// value: A pointer to int. This will be set to an int representing the volume
+// index for |usage|.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_getVolumeIndex(const BAudioManager* brillo_audio_manager,
+ BAudioUsage usage,
+ const BAudioDeviceInfo* device,
+ int* index);
+
+// Get the default stream for volume buttons. If
+// BAudioManager_setVolumeControlUsage has not been called, this will return
+// kInvalidUsage.
+//
+// Args:
+// brillo_audio_manager: A pointer to a BAudioManager object.
+// usage: A pointer to a BAudioUsage representing the audio stream.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_getVolumeControlUsage(
+ const BAudioManager* brillo_audio_manager, BAudioUsage* usage);
+
+// Set the default stream to use for volume buttons. By default, streams will be
+// ordered by priority:
+// 1. kUsageAlarm
+// 2. kUsageNotifications
+// 3. kUsageSystem
+// 4. kUsageMedia
+//
+// Calling BAudioMananager_setVolumeControlUsage with kInvalidUsage will reset
+// the volume control stream to its default priorities and undo the effects of
+// previous calls to BAudioManager_setVolumeControlUsage.
+//
+// Args:
+// brillo_audio_manager: A pointer to a BAudioManager object.
+// usage: A BAudioUsage representing the audio stream.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_setVolumeControlUsage(
+ const BAudioManager* brillo_audio_manager, BAudioUsage usage);
+
+// Increment the volume of active streams or stream selected using
+// BAudioManager_setVolumeControlUsage.
+//
+// Args:
+// brillo_audio_manager: A pointer to a BAudioManager object.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_incrementVolume(const BAudioManager* brillo_audio_manager);
+
+// Decrement the volume of active streams or stream selected using
+// BAudioManager_setVolumeControlUsage.
+//
+// Args:
+// brillo_audio_manager: A pointer to a BAudioManager object.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_decrementVolume(const BAudioManager* brillo_audio_manager);
+
+// Object used for callbacks.
+struct BAudioCallback {
+ // Function to be called when an audio device is added. If multiple audio
+ // devices are added, then this function will be called multiple times. The
+ // user is not responsible for freeing added_device.
+ void (*OnAudioDeviceAdded)(const BAudioDeviceInfo* added_device,
+ void* user_data);
+
+ // Function to be called when an audio device is removed. If multiple audio
+ // devices are removed, then this function will be called multiple times. The
+ // user is not responsible for freeing removed_device.
+ void (*OnAudioDeviceRemoved)(const BAudioDeviceInfo* removed_device,
+ void* user_data);
+
+ // Function to be called when the volume button is pressed.
+ void (*OnVolumeChanged)(BAudioUsage usage,
+ int old_volume_index,
+ int new_volume_index,
+ void* user_data);
+};
+
+typedef struct BAudioCallback BAudioCallback;
+
+// Registers a callback object that lets clients know when audio devices have
+// been added/removed from the system.
+//
+// Arg:
+// brillo_audio_manager: A pointer to a BAudioManager.
+// callback: An object of type BAudioCallback. The BAudioManager
+// maintains ownership of this object.
+// user_data : A pointer to user data. This is not used by BAudioManager and
+// is passed as an arg to callbacks.
+// callback_id: A pointer to an int. The int represents a token that can be
+// used to de-register this callback. Contains 0 on failure.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_registerAudioCallback(
+ const BAudioManager* brillo_audio_manager, const BAudioCallback* callback,
+ void* user_data, int* callback_id);
+
+// Unregisters a callback object.
+//
+// Arg:
+// brillo_audio_manager: A pointer to a BAudioManager.
+// callback_id: A token correspoding to the callback object.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_unregisterAudioCallback(
+ const BAudioManager* brillo_audio_manager, int callback_id);
+
+// Free a Brillo audio manager object.
+//
+// Arg:
+// brillo_audio_manager: A pointer to a BAudioManager to be freed.
+//
+// Returns 0 on success and errno on failure.
+int BAudioManager_delete(BAudioManager* brillo_audio_manager);
+
+__END_DECLS
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_MANAGER_H_
diff --git a/brillo/audio/audioservice/test/audio_daemon_mock.h b/brillo/audio/audioservice/test/audio_daemon_mock.h
new file mode 100644
index 0000000..c5ed43e
--- /dev/null
+++ b/brillo/audio/audioservice/test/audio_daemon_mock.h
@@ -0,0 +1,44 @@
+// 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.
+//
+
+// Mock of audio daemon.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_DAEMON_MOCK_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_DAEMON_MOCK_H_
+
+#include <gmock/gmock.h>
+#include <gtest/gtest_prod.h>
+
+#include "audio_daemon.h"
+
+namespace brillo {
+
+class AudioDaemonMock : public AudioDaemon {
+ public:
+ AudioDaemonMock() = default;
+ ~AudioDaemonMock() {}
+
+ private:
+ friend class AudioDaemonTest;
+ FRIEND_TEST(AudioDaemonTest, RegisterService);
+ FRIEND_TEST(AudioDaemonTest, TestAPSConnectInitializesHandlersOnlyOnce);
+ FRIEND_TEST(AudioDaemonTest, TestDeviceCallbackInitializesBASIfNULL);
+
+ MOCK_METHOD0(InitializeHandlers, void());
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_DAEMON_MOCK_H_
diff --git a/brillo/audio/audioservice/test/audio_daemon_test.cpp b/brillo/audio/audioservice/test/audio_daemon_test.cpp
new file mode 100644
index 0000000..3ff5482
--- /dev/null
+++ b/brillo/audio/audioservice/test/audio_daemon_test.cpp
@@ -0,0 +1,68 @@
+// 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.
+//
+
+// Tests for audio daemon.
+
+#include "audio_daemon_mock.h"
+
+#include <memory>
+#include <vector>
+
+#include <binder/Binder.h>
+#include <binderwrapper/binder_test_base.h>
+#include <binderwrapper/stub_binder_wrapper.h>
+#include <gmock/gmock.h>
+
+#include "audio_device_handler_mock.h"
+
+using android::BinderTestBase;
+using android::IInterface;
+using std::make_shared;
+using testing::_;
+using testing::AnyNumber;
+
+namespace brillo {
+
+class AudioDaemonTest : public BinderTestBase {
+ public:
+ AudioDaemonMock daemon_;
+ AudioDeviceHandlerMock device_handler_;
+};
+
+TEST_F(AudioDaemonTest, RegisterService) {
+ daemon_.InitializeBrilloAudioService();
+ EXPECT_EQ(daemon_.brillo_audio_service_,
+ binder_wrapper()->GetRegisteredService(
+ "android.brillo.brilloaudioservice.BrilloAudioService"));
+}
+
+TEST_F(AudioDaemonTest, TestAPSConnectInitializesHandlersOnlyOnce) {
+ binder_wrapper()->SetBinderForService("media.audio_policy",
+ binder_wrapper()->CreateLocalBinder());
+ daemon_.handlers_initialized_ = false;
+ EXPECT_CALL(daemon_, InitializeHandlers()).Times(1);
+ daemon_.ConnectToAPS();
+}
+
+TEST_F(AudioDaemonTest, TestDeviceCallbackInitializesBASIfNULL) {
+ daemon_.DeviceCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesConnected,
+ std::vector<int>());
+ EXPECT_EQ(daemon_.brillo_audio_service_,
+ binder_wrapper()->GetRegisteredService(
+ "android.brillo.brilloaudioservice.BrilloAudioService"));
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/test/audio_device_handler_mock.h b/brillo/audio/audioservice/test/audio_device_handler_mock.h
index ce6dfd3..fcc711f 100644
--- a/brillo/audio/audioservice/test/audio_device_handler_mock.h
+++ b/brillo/audio/audioservice/test/audio_device_handler_mock.h
@@ -72,6 +72,7 @@
MOCK_METHOD2(NotifyAudioPolicyService,
void(audio_devices_t device, audio_policy_dev_state_t state));
+ MOCK_METHOD1(TriggerCallback, void(DeviceConnectionState));
};
} // namespace brillo
diff --git a/brillo/audio/audioservice/test/audio_device_handler_test.cpp b/brillo/audio/audioservice/test/audio_device_handler_test.cpp
index 5487469..d14faa0 100644
--- a/brillo/audio/audioservice/test/audio_device_handler_test.cpp
+++ b/brillo/audio/audioservice/test/audio_device_handler_test.cpp
@@ -33,6 +33,7 @@
using brillo::AudioDeviceHandlerMock;
using testing::_;
using testing::AnyNumber;
+using testing::AtLeast;
namespace brillo {
@@ -67,6 +68,7 @@
NotifyAudioPolicyService(
_, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)).Times(3);
handler_.DisconnectAllSupportedDevices();
+ EXPECT_EQ(handler_.changed_devices_.size(), 3);
}
// Test that Init() calls DisconnectAllSupportedDevices().
@@ -74,9 +76,15 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(
_, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)).Times(3);
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesDisconnected))
+ .Times(AtLeast(1));
EXPECT_CALL(handler_,
NotifyAudioPolicyService(
_, AUDIO_POLICY_DEVICE_STATE_AVAILABLE)).Times(AnyNumber());
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesConnected))
+ .Times(AnyNumber());
handler_.Init(nullptr);
}
@@ -86,11 +94,15 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesConnected));
handler_.GetInitialAudioDeviceState(h2w_file_path_);
EXPECT_NE(
handler_.connected_input_devices_.find(AUDIO_DEVICE_IN_WIRED_HEADSET),
handler_.connected_input_devices_.end());
EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], AUDIO_DEVICE_IN_WIRED_HEADSET);
}
// Test GetInitialAudioDeviceState() with a headphone.
@@ -99,16 +111,22 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesConnected));
handler_.GetInitialAudioDeviceState(h2w_file_path_);
EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
EXPECT_NE(
handler_.connected_output_devices_.find(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
handler_.connected_output_devices_.end());
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
}
// Test GetInitialAudioDeviceState() with a headset.
TEST_F(AudioDeviceHandlerTest, InitialAudioStateHeadset) {
WriteToH2WFile(3);
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesConnected));
EXPECT_CALL(handler_,
NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
@@ -122,6 +140,7 @@
EXPECT_NE(
handler_.connected_output_devices_.find(AUDIO_DEVICE_OUT_WIRED_HEADSET),
handler_.connected_output_devices_.end());
+ EXPECT_EQ(handler_.changed_devices_.size(), 2);
}
// Test GetInitialAudioDeviceState() without any devices connected to the audio
@@ -129,9 +148,11 @@
// by Init().
TEST_F(AudioDeviceHandlerTest, InitialAudioStateNone) {
WriteToH2WFile(0);
+ EXPECT_CALL(handler_, TriggerCallback(_));
handler_.GetInitialAudioDeviceState(h2w_file_path_);
EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+ EXPECT_EQ(handler_.changed_devices_.size(), 0);
}
// Test GetInitialAudioDeviceState() with an invalid file. The audio handler
@@ -150,6 +171,7 @@
event.type = 0;
event.code = 0;
event.value = 0;
+ EXPECT_CALL(handler_, TriggerCallback(_));
handler_.ProcessEvent(event);
EXPECT_FALSE(handler_.headphone_);
EXPECT_FALSE(handler_.microphone_);
@@ -215,7 +237,10 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(
_, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)).Times(0);
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesDisconnected));
handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+ EXPECT_EQ(handler_.changed_devices_.size(), 0);
}
// Test UpdateAudioSystem() when disconnecting a microphone.
@@ -225,9 +250,13 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(device,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesDisconnected));
handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], device);
}
// Test UpdateAudioSystem() when disconnecting a headphone.
@@ -237,9 +266,13 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(device,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesDisconnected));
handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], device);
}
// Test UpdateAudioSystem() when disconnecting a headset & headphones.
@@ -256,9 +289,12 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesDisconnected));
handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+ EXPECT_EQ(handler_.changed_devices_.size(), 3);
}
// Test UpdateAudioSystem() when connecting a microphone.
@@ -267,9 +303,13 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesConnected));
handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
EXPECT_EQ(handler_.connected_input_devices_.size(), 1);
EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], AUDIO_DEVICE_IN_WIRED_HEADSET);
}
// Test UpdateAudioSystem() when connecting a headphone.
@@ -278,9 +318,13 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesConnected));
handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
EXPECT_EQ(handler_.connected_output_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
}
// Test UpdateAudioSystem() when connecting a headset.
@@ -293,9 +337,12 @@
EXPECT_CALL(handler_,
NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADSET,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ EXPECT_CALL(handler_, TriggerCallback(
+ AudioDeviceHandlerMock::DeviceConnectionState::kDevicesConnected));
handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
EXPECT_EQ(handler_.connected_input_devices_.size(), 1);
EXPECT_EQ(handler_.connected_output_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_.size(), 2);
}
// Test ConnectAudioDevice() with an input device.
@@ -309,6 +356,8 @@
EXPECT_NE(
handler_.connected_input_devices_.find(device),
handler_.connected_input_devices_.end());
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], device);
}
// Test ConnectAudioDevice() with an output device.
@@ -322,6 +371,8 @@
EXPECT_NE(
handler_.connected_output_devices_.find(device),
handler_.connected_output_devices_.end());
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], device);
}
// Test DisconnectAudioDevice() with an input device.
@@ -335,6 +386,8 @@
handler_.DisconnectAudioDevice(device);
EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
EXPECT_EQ(handler_.connected_output_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], device);
}
// Test DisconnectAudioDevice() with an output device.
@@ -348,6 +401,8 @@
handler_.DisconnectAudioDevice(device);
EXPECT_EQ(handler_.connected_input_devices_.size(), 1);
EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+ EXPECT_EQ(handler_.changed_devices_.size(), 1);
+ EXPECT_EQ(handler_.changed_devices_[0], device);
}
} // namespace brillo
diff --git a/brillo/audio/audioservice/test/audio_service_callback_test.cpp b/brillo/audio/audioservice/test/audio_service_callback_test.cpp
new file mode 100644
index 0000000..38ced10
--- /dev/null
+++ b/brillo/audio/audioservice/test/audio_service_callback_test.cpp
@@ -0,0 +1,62 @@
+// 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.
+//
+
+// Tests for the audio service callback object.
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <hardware/audio.h>
+
+#include "audio_service_callback.h"
+
+namespace brillo {
+
+class AudioServiceCallbackTest : public testing::Test {
+ public:
+ void SetUp() override {
+ connected_call_count_ = 0;
+ disconnected_call_count_ = 0;
+ callback_.OnAudioDeviceAdded = OnDeviceConnectedMock;
+ callback_.OnAudioDeviceRemoved = OnDeviceDisconnectedMock;
+ user_data_ = static_cast<void*>(this);
+ }
+
+ static void OnDeviceConnectedMock(const BAudioDeviceInfo*, void* user_data) {
+ static_cast<AudioServiceCallbackTest*>(user_data)->connected_call_count_++;
+ }
+
+ static void OnDeviceDisconnectedMock(const BAudioDeviceInfo*, void* user_data) {
+ static_cast<AudioServiceCallbackTest*>(
+ user_data)->disconnected_call_count_++;
+ }
+
+ BAudioCallback callback_;
+ void* user_data_;
+ int connected_call_count_;
+ int disconnected_call_count_;
+};
+
+TEST_F(AudioServiceCallbackTest, CallbackCallCount) {
+ std::vector<int> devices = {AUDIO_DEVICE_OUT_WIRED_HEADSET,
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE};
+ AudioServiceCallback service_callback(&callback_, user_data_);
+ service_callback.OnAudioDevicesConnected(devices);
+ EXPECT_EQ(connected_call_count_, devices.size());
+ service_callback.OnAudioDevicesDisconnected(devices);
+ EXPECT_EQ(disconnected_call_count_, devices.size());
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/test/audio_volume_handler_mock.h b/brillo/audio/audioservice/test/audio_volume_handler_mock.h
new file mode 100644
index 0000000..32028ca
--- /dev/null
+++ b/brillo/audio/audioservice/test/audio_volume_handler_mock.h
@@ -0,0 +1,55 @@
+// 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.
+//
+
+// Mock of AudioVolumeHandler.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_VOLUME_HANDLER_MOCK_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_VOLUME_HANDLER_MOCK_H_
+
+#include <gmock/gmock.h>
+#include <gtest/gtest_prod.h>
+
+#include "audio_volume_handler.h"
+
+namespace brillo {
+
+class AudioVolumeHandlerMock : public AudioVolumeHandler {
+ public:
+ AudioVolumeHandlerMock() = default;
+ ~AudioVolumeHandlerMock() {}
+
+ private:
+ friend class AudioVolumeHandlerTest;
+ FRIEND_TEST(AudioVolumeHandlerTest, FileGeneration);
+ FRIEND_TEST(AudioVolumeHandlerTest, GetVolumeForKey);
+ FRIEND_TEST(AudioVolumeHandlerTest, GetVolumeForStreamDeviceTuple);
+ FRIEND_TEST(AudioVolumeHandlerTest, SetVolumeForStreamDeviceTuple);
+ FRIEND_TEST(AudioVolumeHandlerTest, InitNoFile);
+ FRIEND_TEST(AudioVolumeHandlerTest, InitFilePresent);
+ FRIEND_TEST(AudioVolumeHandlerTest, ProcessEventEmpty);
+ FRIEND_TEST(AudioVolumeHandlerTest, ProcessEventKeyUp);
+ FRIEND_TEST(AudioVolumeHandlerTest, ProcessEventKeyDown);
+ FRIEND_TEST(AudioVolumeHandlerTest, SelectStream);
+ FRIEND_TEST(AudioVolumeHandlerTest, ComputeNewVolume);
+ FRIEND_TEST(AudioVolumeHandlerTest, GetSetVolumeIndex);
+
+ MOCK_METHOD3(TriggerCallback, void(audio_stream_type_t, int, int));
+ MOCK_METHOD0(InitAPSAllStreams, void());
+ MOCK_METHOD1(AdjustVolumeActiveStreams, void(int));
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_VOLUME_HANDLER_MOCK_H_
diff --git a/brillo/audio/audioservice/test/audio_volume_handler_test.cpp b/brillo/audio/audioservice/test/audio_volume_handler_test.cpp
new file mode 100644
index 0000000..47ef236
--- /dev/null
+++ b/brillo/audio/audioservice/test/audio_volume_handler_test.cpp
@@ -0,0 +1,212 @@
+// 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.
+//
+
+// Tests for audio volume handler.
+
+#include "audio_volume_handler_mock.h"
+
+#include <memory>
+#include <string>
+
+#include <base/files/file_path.h>
+#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <brillo/key_value_store.h>
+#include <brillo/strings/string_utils.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "audio_device_handler.h"
+
+using base::FilePath;
+using base::PathExists;
+using base::ScopedTempDir;
+using brillo::string_utils::ToString;
+using std::stoi;
+using testing::_;
+
+namespace brillo {
+
+class AudioVolumeHandlerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+ volume_file_path_ = temp_dir_.path().Append("vol_file");
+ handler_.SetVolumeFilePathForTesting(volume_file_path_);
+ }
+
+ void SetupHandlerVolumeFile() {
+ handler_.kv_store_ = std::unique_ptr<KeyValueStore>(new KeyValueStore);
+ handler_.GenerateVolumeFile();
+ }
+
+ AudioVolumeHandlerMock handler_;
+ FilePath volume_file_path_;
+
+ private:
+ ScopedTempDir temp_dir_;
+};
+
+// Test that the volume file is formatted correctly.
+TEST_F(AudioVolumeHandlerTest, FileGeneration) {
+ SetupHandlerVolumeFile();
+ KeyValueStore kv_store;
+ kv_store.Load(volume_file_path_);
+ for (auto stream : handler_.kSupportedStreams_) {
+ std::string value;
+ ASSERT_EQ(handler_.kMinIndex_, 0);
+ ASSERT_EQ(handler_.kMaxIndex_, 100);
+ for (auto device : AudioDeviceHandler::kSupportedOutputDevices_) {
+ ASSERT_TRUE(kv_store.GetString(handler_.kCurrentIndexKey_ + "." +
+ ToString(stream) + "." +
+ ToString(device),
+ &value));
+ ASSERT_EQ(handler_.kDefaultCurrentIndex_, stoi(value));
+ }
+ }
+}
+
+// Test GetVolumeCurrentIndex.
+TEST_F(AudioVolumeHandlerTest, GetVolumeForStreamDeviceTuple) {
+ handler_.kv_store_ = std::unique_ptr<KeyValueStore>(new KeyValueStore);
+ handler_.kv_store_->SetString(handler_.kCurrentIndexKey_ + ".1.2", "100");
+ ASSERT_EQ(
+ handler_.GetVolumeCurrentIndex(static_cast<audio_stream_type_t>(1), 2),
+ 100);
+}
+
+// Test SetVolumeCurrentIndex.
+TEST_F(AudioVolumeHandlerTest, SetVolumeForStreamDeviceTuple) {
+ handler_.kv_store_ = std::unique_ptr<KeyValueStore>(new KeyValueStore);
+ handler_.PersistVolumeConfiguration(
+ static_cast<audio_stream_type_t>(1), 2, 100);
+ std::string value;
+ auto key = handler_.kCurrentIndexKey_ + ".1.2";
+ handler_.kv_store_->GetString(key, &value);
+ ASSERT_EQ(stoi(value), 100);
+}
+
+// Test that a new volume file is generated if it doesn't exist.
+TEST_F(AudioVolumeHandlerTest, InitNoFile) {
+ EXPECT_CALL(handler_, InitAPSAllStreams());
+ handler_.Init(nullptr);
+ EXPECT_TRUE(PathExists(volume_file_path_));
+}
+
+// Test that a new volume file isn't generated it already exists.
+TEST_F(AudioVolumeHandlerTest, InitFilePresent) {
+ KeyValueStore kv_store;
+ kv_store.SetString("foo", "100");
+ kv_store.Save(volume_file_path_);
+ EXPECT_CALL(handler_, InitAPSAllStreams());
+ handler_.Init(nullptr);
+ EXPECT_TRUE(PathExists(volume_file_path_));
+ std::string value;
+ handler_.kv_store_->GetString("foo", &value);
+ EXPECT_EQ(stoi(value), 100);
+}
+
+TEST_F(AudioVolumeHandlerTest, ProcessEventEmpty) {
+ struct input_event event;
+ event.type = 0;
+ event.code = 0;
+ event.value = 0;
+ EXPECT_CALL(handler_, AdjustVolumeActiveStreams(_)).Times(0);
+ handler_.ProcessEvent(event);
+}
+
+TEST_F(AudioVolumeHandlerTest, ProcessEventKeyUp) {
+ struct input_event event;
+ event.type = EV_KEY;
+ event.code = KEY_VOLUMEUP;
+ event.value = 1;
+ EXPECT_CALL(handler_, AdjustVolumeActiveStreams(1));
+ handler_.ProcessEvent(event);
+}
+
+TEST_F(AudioVolumeHandlerTest, ProcessEventKeyDown) {
+ struct input_event event;
+ event.type = EV_KEY;
+ event.code = KEY_VOLUMEDOWN;
+ event.value = 1;
+ EXPECT_CALL(handler_, AdjustVolumeActiveStreams(-1));
+ handler_.ProcessEvent(event);
+}
+
+TEST_F(AudioVolumeHandlerTest, SelectStream) {
+ EXPECT_EQ(handler_.GetVolumeControlStream(), AUDIO_STREAM_DEFAULT);
+ handler_.SetVolumeControlStream(AUDIO_STREAM_MUSIC);
+ EXPECT_EQ(handler_.GetVolumeControlStream(), AUDIO_STREAM_MUSIC);
+}
+
+TEST_F(AudioVolumeHandlerTest, ComputeNewVolume) {
+ EXPECT_EQ(handler_.GetNewVolumeIndex(50, 1, AUDIO_STREAM_MUSIC), 51);
+ EXPECT_EQ(handler_.GetNewVolumeIndex(50, -1, AUDIO_STREAM_MUSIC), 49);
+ handler_.step_sizes_[AUDIO_STREAM_MUSIC] = 10;
+ EXPECT_EQ(handler_.GetNewVolumeIndex(50, 1, AUDIO_STREAM_MUSIC), 60);
+ EXPECT_EQ(handler_.GetNewVolumeIndex(50, -1, AUDIO_STREAM_MUSIC), 40);
+ SetupHandlerVolumeFile();
+ EXPECT_EQ(handler_.GetNewVolumeIndex(100, 1, AUDIO_STREAM_MUSIC), 100);
+ EXPECT_EQ(handler_.GetNewVolumeIndex(0, -1, AUDIO_STREAM_MUSIC), 0);
+}
+
+TEST_F(AudioVolumeHandlerTest, GetSetMaxSteps) {
+ EXPECT_EQ(handler_.GetVolumeMaxSteps(AUDIO_STREAM_MUSIC), 100);
+ EXPECT_EQ(handler_.SetVolumeMaxSteps(AUDIO_STREAM_MUSIC, 0), EINVAL);
+ EXPECT_EQ(handler_.GetVolumeMaxSteps(AUDIO_STREAM_MUSIC), 100);
+ EXPECT_EQ(handler_.SetVolumeMaxSteps(AUDIO_STREAM_MUSIC, 100), 0);
+ EXPECT_EQ(handler_.GetVolumeMaxSteps(AUDIO_STREAM_MUSIC), 100);
+ EXPECT_EQ(handler_.SetVolumeMaxSteps(AUDIO_STREAM_MUSIC, -1), EINVAL);
+ EXPECT_EQ(handler_.SetVolumeMaxSteps(AUDIO_STREAM_MUSIC, 101), EINVAL);
+}
+
+TEST_F(AudioVolumeHandlerTest, GetSetVolumeIndex) {
+ SetupHandlerVolumeFile();
+ EXPECT_CALL(handler_, TriggerCallback(AUDIO_STREAM_MUSIC, _, 0));
+ EXPECT_EQ(handler_.SetVolumeIndex(
+ AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_WIRED_HEADSET, 0),
+ 0);
+ EXPECT_CALL(handler_, TriggerCallback(AUDIO_STREAM_MUSIC, 0, 50));
+ EXPECT_EQ(handler_.SetVolumeIndex(
+ AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_WIRED_HEADSET, 50),
+ 0);
+ EXPECT_CALL(handler_, TriggerCallback(AUDIO_STREAM_MUSIC, 50, 100));
+ EXPECT_EQ(handler_.SetVolumeIndex(
+ AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_WIRED_HEADSET, 100),
+ 0);
+ EXPECT_EQ(handler_.SetVolumeIndex(
+ AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_WIRED_HEADSET, -1),
+ EINVAL);
+ EXPECT_EQ(handler_.SetVolumeIndex(
+ AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_WIRED_HEADSET, 101),
+ EINVAL);
+ EXPECT_EQ(handler_.SetVolumeMaxSteps(AUDIO_STREAM_MUSIC, 10), 0);
+ EXPECT_EQ(handler_.GetVolumeIndex(AUDIO_STREAM_MUSIC,
+ AUDIO_DEVICE_OUT_WIRED_HEADSET),
+ 10);
+ EXPECT_EQ(handler_.SetVolumeIndex(
+ AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_WIRED_HEADSET, 11),
+ EINVAL);
+ EXPECT_CALL(handler_, TriggerCallback(AUDIO_STREAM_MUSIC, 100, 50));
+ EXPECT_EQ(handler_.SetVolumeIndex(
+ AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_WIRED_HEADSET, 5),
+ 0);
+ EXPECT_EQ(handler_.SetVolumeMaxSteps(AUDIO_STREAM_MUSIC, 20), 0);
+ EXPECT_EQ(handler_.GetVolumeIndex(AUDIO_STREAM_MUSIC,
+ AUDIO_DEVICE_OUT_WIRED_HEADSET),
+ 10);
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/test/brillo_audio_client_mock.h b/brillo/audio/audioservice/test/brillo_audio_client_mock.h
new file mode 100644
index 0000000..047c7c3
--- /dev/null
+++ b/brillo/audio/audioservice/test/brillo_audio_client_mock.h
@@ -0,0 +1,45 @@
+// 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.
+//
+
+// Mock for the brillo audio client.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_CLIENT_MOCK_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_CLIENT_MOCK_H_
+
+#include <gmock/gmock.h>
+#include <gtest/gtest_prod.h>
+
+#include "brillo_audio_client.h"
+
+namespace brillo {
+
+class BrilloAudioClientMock : public BrilloAudioClient {
+ public:
+ virtual ~BrilloAudioClientMock() = default;
+
+ MOCK_METHOD0(OnBASDisconnect, void());
+
+ private:
+ friend class BrilloAudioClientTest;
+ FRIEND_TEST(BrilloAudioClientTest,
+ CheckInitializeRegistersForDeathNotifications);
+ FRIEND_TEST(BrilloAudioClientTest, InitializeNoService);
+
+ BrilloAudioClientMock() = default;
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_CLIENT_MOCK_H_
diff --git a/brillo/audio/audioservice/test/brillo_audio_client_test.cpp b/brillo/audio/audioservice/test/brillo_audio_client_test.cpp
new file mode 100644
index 0000000..3616c7b
--- /dev/null
+++ b/brillo/audio/audioservice/test/brillo_audio_client_test.cpp
@@ -0,0 +1,287 @@
+// 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.
+//
+
+// Tests for the brillo audio client.
+
+#include <binderwrapper/binder_test_base.h>
+#include <binderwrapper/stub_binder_wrapper.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "audio_service_callback.h"
+#include "brillo_audio_client.h"
+#include "include/brillo_audio_manager.h"
+#include "test/brillo_audio_client_mock.h"
+#include "test/brillo_audio_service_mock.h"
+
+using android::sp;
+using android::String8;
+using testing::Return;
+using testing::_;
+
+namespace brillo {
+
+static const char kBrilloAudioServiceName[] =
+ "android.brillo.brilloaudioservice.BrilloAudioService";
+
+class BrilloAudioClientTest : public android::BinderTestBase {
+ public:
+ bool ConnectClientToBAS() {
+ bas_ = new BrilloAudioServiceMock();
+ binder_wrapper()->SetBinderForService(kBrilloAudioServiceName, bas_);
+ return client_.Initialize();
+ }
+
+ BrilloAudioClientMock client_;
+ sp<BrilloAudioServiceMock> bas_;
+};
+
+TEST_F(BrilloAudioClientTest, SetDeviceNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ EXPECT_EQ(
+ client_.SetDevice(AUDIO_POLICY_FORCE_USE_MAX, AUDIO_POLICY_FORCE_NONE),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, GetDevicesNoService) {
+ std::vector<int> foo;
+ EXPECT_CALL(client_, OnBASDisconnect());
+ EXPECT_EQ(client_.GetDevices(0, foo), ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, RegisterCallbackNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ EXPECT_EQ(client_.RegisterAudioCallback(nullptr, nullptr), ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, UnregisterAudioCallbackNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ EXPECT_EQ(client_.UnregisterAudioCallback(0), ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, InitializeNoService) {
+ EXPECT_FALSE(client_.Initialize());
+}
+
+TEST_F(BrilloAudioClientTest, CheckInitializeRegistersForDeathNotifications) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ EXPECT_CALL(client_, OnBASDisconnect());
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+}
+
+TEST_F(BrilloAudioClientTest, GetDevicesWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ std::vector<int> foo;
+ EXPECT_CALL(*bas_.get(), GetDevices(0, &foo)).WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.GetDevices(0, foo), 0);
+}
+
+TEST_F(BrilloAudioClientTest, SetDeviceWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ std::vector<int> foo;
+ EXPECT_CALL(*bas_.get(),
+ SetDevice(AUDIO_POLICY_FORCE_USE_MAX, AUDIO_POLICY_FORCE_NONE))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(
+ client_.SetDevice(AUDIO_POLICY_FORCE_USE_MAX, AUDIO_POLICY_FORCE_NONE),
+ 0);
+}
+
+TEST_F(BrilloAudioClientTest, RegisterCallbackWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ BAudioCallback bcallback;
+ AudioServiceCallback* callback =
+ new AudioServiceCallback(&bcallback, nullptr);
+ int id = 0;
+ EXPECT_CALL(*bas_.get(),
+ RegisterServiceCallback(sp<IAudioServiceCallback>(callback)))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.RegisterAudioCallback(callback, &id), 0);
+ EXPECT_NE(id, 0);
+}
+
+TEST_F(BrilloAudioClientTest, RegisterSameCallbackTwiceWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ BAudioCallback bcallback;
+ AudioServiceCallback* callback =
+ new AudioServiceCallback(&bcallback, nullptr);
+ int id = -1;
+ EXPECT_CALL(*bas_.get(),
+ RegisterServiceCallback(sp<IAudioServiceCallback>(callback)))
+ .Times(2)
+ .WillRepeatedly(Return(Status::ok()));
+ EXPECT_EQ(client_.RegisterAudioCallback(callback, &id), 0);
+ EXPECT_NE(id, 0);
+ id = -1;
+ EXPECT_EQ(client_.RegisterAudioCallback(callback, &id), EINVAL);
+ EXPECT_EQ(id, 0);
+}
+
+TEST_F(BrilloAudioClientTest, UnregisterAudioCallbackValidWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ BAudioCallback bcallback;
+ AudioServiceCallback* callback =
+ new AudioServiceCallback(&bcallback, nullptr);
+ int id = 0;
+ EXPECT_CALL(*bas_.get(),
+ RegisterServiceCallback(sp<IAudioServiceCallback>(callback)))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.RegisterAudioCallback(callback, &id), 0);
+ EXPECT_NE(id, 0);
+ EXPECT_CALL(*bas_.get(),
+ UnregisterServiceCallback(sp<IAudioServiceCallback>(callback)))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.UnregisterAudioCallback(id), 0);
+}
+
+TEST_F(BrilloAudioClientTest, UnregisterInvalidCallbackWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ EXPECT_EQ(client_.UnregisterAudioCallback(1), EINVAL);
+}
+
+TEST_F(BrilloAudioClientTest, RegisterAndUnregisterAudioTwoCallbacks) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ BAudioCallback bcallback1, bcallback2;
+ AudioServiceCallback* callback1 =
+ new AudioServiceCallback(&bcallback1, nullptr);
+ AudioServiceCallback* callback2 =
+ new AudioServiceCallback(&bcallback2, nullptr);
+ int id1 = 0, id2 = 0;
+ EXPECT_CALL(*bas_.get(), RegisterServiceCallback(_))
+ .WillRepeatedly(Return(Status::ok()));
+ EXPECT_EQ(client_.RegisterAudioCallback(callback1, &id1), 0);
+ EXPECT_NE(id1, 0);
+ EXPECT_EQ(client_.RegisterAudioCallback(callback2, &id2), 0);
+ EXPECT_NE(id2, 0);
+ EXPECT_CALL(*bas_.get(), UnregisterServiceCallback(_))
+ .WillRepeatedly(Return(Status::ok()));
+ EXPECT_EQ(client_.UnregisterAudioCallback(id1), 0);
+ EXPECT_EQ(client_.UnregisterAudioCallback(id2), 0);
+}
+
+TEST_F(BrilloAudioClientTest, GetMaxVolStepsNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ int foo;
+ EXPECT_EQ(client_.GetMaxVolumeSteps(BAudioUsage::kUsageInvalid, &foo),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, GetMaxVolStepsWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ int foo;
+ EXPECT_CALL(*bas_.get(), GetMaxVolumeSteps(AUDIO_STREAM_MUSIC, &foo))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.GetMaxVolumeSteps(BAudioUsage::kUsageMedia, &foo), 0);
+}
+
+TEST_F(BrilloAudioClientTest, SetMaxVolStepsNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ EXPECT_EQ(client_.SetMaxVolumeSteps(BAudioUsage::kUsageInvalid, 100),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, SetMaxVolStepsWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ EXPECT_CALL(*bas_.get(), SetMaxVolumeSteps(AUDIO_STREAM_MUSIC, 100))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.SetMaxVolumeSteps(BAudioUsage::kUsageMedia, 100), 0);
+}
+
+TEST_F(BrilloAudioClientTest, SetVolIndexNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ EXPECT_EQ(client_.SetVolumeIndex(
+ BAudioUsage::kUsageInvalid, AUDIO_DEVICE_NONE, 100),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, SetVolIndexWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ EXPECT_CALL(*bas_.get(),
+ SetVolumeIndex(AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_SPEAKER, 100))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.SetVolumeIndex(
+ BAudioUsage::kUsageMedia, AUDIO_DEVICE_OUT_SPEAKER, 100),
+ 0);
+}
+
+TEST_F(BrilloAudioClientTest, GetVolIndexNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ int foo;
+ EXPECT_EQ(client_.GetVolumeIndex(
+ BAudioUsage::kUsageInvalid, AUDIO_DEVICE_NONE, &foo),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, GetVolIndexWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ int foo;
+ EXPECT_CALL(
+ *bas_.get(),
+ GetVolumeIndex(AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_SPEAKER, &foo))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.GetVolumeIndex(
+ BAudioUsage::kUsageMedia, AUDIO_DEVICE_OUT_SPEAKER, &foo),
+ 0);
+}
+
+TEST_F(BrilloAudioClientTest, GetVolumeControlStreamNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ BAudioUsage foo;
+ EXPECT_EQ(client_.GetVolumeControlStream(&foo), ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, GetVolumeControlStreamWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ EXPECT_CALL(*bas_.get(), GetVolumeControlStream(_))
+ .WillOnce(Return(Status::ok()));
+ BAudioUsage foo;
+ EXPECT_EQ(client_.GetVolumeControlStream(&foo), 0);
+}
+
+TEST_F(BrilloAudioClientTest, SetVolumeControlStreamNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ EXPECT_EQ(client_.SetVolumeControlStream(kUsageMedia), ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, SetVolumeControlStreamWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ EXPECT_CALL(*bas_.get(), SetVolumeControlStream(AUDIO_STREAM_MUSIC))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.SetVolumeControlStream(kUsageMedia), 0);
+}
+
+TEST_F(BrilloAudioClientTest, IncrementVolNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ EXPECT_EQ(client_.IncrementVolume(), ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, IncrementVolWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ EXPECT_CALL(*bas_.get(), IncrementVolume()).WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.IncrementVolume(), 0);
+}
+
+TEST_F(BrilloAudioClientTest, DecrementVolNoService) {
+ EXPECT_CALL(client_, OnBASDisconnect());
+ EXPECT_EQ(client_.DecrementVolume(), ECONNABORTED);
+}
+
+TEST_F(BrilloAudioClientTest, DecrementVolWithBAS) {
+ EXPECT_TRUE(ConnectClientToBAS());
+ EXPECT_CALL(*bas_.get(), DecrementVolume()).WillOnce(Return(Status::ok()));
+ EXPECT_EQ(client_.DecrementVolume(), 0);
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/test/brillo_audio_device_info_internal_test.cpp b/brillo/audio/audioservice/test/brillo_audio_device_info_internal_test.cpp
new file mode 100644
index 0000000..d02608c
--- /dev/null
+++ b/brillo/audio/audioservice/test/brillo_audio_device_info_internal_test.cpp
@@ -0,0 +1,51 @@
+// 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.
+//
+
+// Tests for the BrilloAudioDeviceInfoInternal test.
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <hardware/audio.h>
+
+#include "brillo_audio_device_info_internal.h"
+
+namespace brillo {
+
+TEST(BrilloAudioDeviceInfoInternalTest, OutWiredHeadset) {
+ BAudioDeviceInfoInternal* badi =
+ BAudioDeviceInfoInternal::CreateFromAudioDevicesT(
+ AUDIO_DEVICE_OUT_WIRED_HEADSET);
+ EXPECT_EQ(badi->device_id_, TYPE_WIRED_HEADSET);
+ EXPECT_EQ(badi->GetConfig(), AUDIO_POLICY_FORCE_HEADPHONES);
+}
+
+TEST(BrilloAudioDeviceInfoInternalTest, OutWiredHeadphone) {
+ BAudioDeviceInfoInternal* badi =
+ BAudioDeviceInfoInternal::CreateFromAudioDevicesT(
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
+ EXPECT_EQ(badi->device_id_, TYPE_WIRED_HEADPHONES);
+ EXPECT_EQ(badi->GetConfig(), AUDIO_POLICY_FORCE_HEADPHONES);
+}
+
+TEST(BrilloAudioDeviceInfoInternalTest, InWiredHeadset) {
+ BAudioDeviceInfoInternal* badi =
+ BAudioDeviceInfoInternal::CreateFromAudioDevicesT(
+ AUDIO_DEVICE_IN_WIRED_HEADSET);
+ EXPECT_EQ(badi->device_id_, TYPE_WIRED_HEADSET_MIC);
+ EXPECT_EQ(badi->GetConfig(), AUDIO_POLICY_FORCE_HEADPHONES);
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/test/brillo_audio_manager_test.cpp b/brillo/audio/audioservice/test/brillo_audio_manager_test.cpp
new file mode 100644
index 0000000..b4299f7
--- /dev/null
+++ b/brillo/audio/audioservice/test/brillo_audio_manager_test.cpp
@@ -0,0 +1,497 @@
+// 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.
+//
+
+// Tests for the brillo audio manager interface.
+
+#include <binderwrapper/binder_test_base.h>
+#include <binderwrapper/stub_binder_wrapper.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "audio_service_callback.h"
+#include "brillo_audio_client.h"
+#include "include/brillo_audio_manager.h"
+#include "test/brillo_audio_service_mock.h"
+
+using android::sp;
+using testing::Mock;
+using testing::Return;
+using testing::_;
+
+namespace brillo {
+
+static const char kBrilloAudioServiceName[] =
+ "android.brillo.brilloaudioservice.BrilloAudioService";
+
+class BrilloAudioManagerTest : public android::BinderTestBase {
+ public:
+ void ConnectBAS() {
+ bas_ = new BrilloAudioServiceMock();
+ binder_wrapper()->SetBinderForService(kBrilloAudioServiceName, bas_);
+ }
+
+ BAudioManager* GetValidManager() {
+ ConnectBAS();
+ auto bam = BAudioManager_new();
+ EXPECT_NE(bam, nullptr);
+ return bam;
+ }
+
+ void TearDown() {
+ // Stopping the BAS will cause the client to delete itself.
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ bas_.clear();
+ }
+
+ sp<BrilloAudioServiceMock> bas_;
+};
+
+TEST_F(BrilloAudioManagerTest, NewNoService) {
+ EXPECT_EQ(BAudioManager_new(), nullptr);
+}
+
+TEST_F(BrilloAudioManagerTest, NewWithBAS) {
+ ConnectBAS();
+ auto bam = BAudioManager_new();
+ EXPECT_NE(bam, nullptr);
+}
+
+TEST_F(BrilloAudioManagerTest, GetDevicesInvalidParams) {
+ auto bam = GetValidManager();
+ unsigned int num_devices;
+ EXPECT_EQ(BAudioManager_getDevices(nullptr, 1, nullptr, 0, &num_devices),
+ EINVAL);
+ EXPECT_EQ(BAudioManager_getDevices(bam, 1, nullptr, 0, nullptr), EINVAL);
+ EXPECT_EQ(BAudioManager_getDevices(bam, -1, nullptr, 0, &num_devices),
+ EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, GetDevicesNullArrNoDevices) {
+ auto bam = GetValidManager();
+ unsigned int num_devices = -1;
+ EXPECT_CALL(*bas_.get(), GetDevices(1, _)).WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_getDevices(bam, 1, nullptr, 0, &num_devices), 0);
+ EXPECT_EQ(num_devices, 0);
+}
+
+TEST_F(BrilloAudioManagerTest, SetInputDeviceInvalidParams) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_UNKNOWN);
+ EXPECT_EQ(BAudioManager_setInputDevice(nullptr, nullptr), EINVAL);
+ EXPECT_EQ(BAudioManager_setInputDevice(bam, nullptr), EINVAL);
+ EXPECT_EQ(BAudioManager_setInputDevice(nullptr, device), EINVAL);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, SetInputDeviceHeadsetMic) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADSET_MIC);
+ EXPECT_CALL(*bas_.get(), SetDevice(AUDIO_POLICY_FORCE_FOR_RECORD,
+ AUDIO_POLICY_FORCE_HEADPHONES))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_setInputDevice(bam, device), 0);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, SetInputDeviceBuiltinMic) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_BUILTIN_MIC);
+ EXPECT_CALL(*bas_.get(),
+ SetDevice(AUDIO_POLICY_FORCE_FOR_RECORD, AUDIO_POLICY_FORCE_NONE))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_setInputDevice(bam, device), 0);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, SetOutputDeviceInvalidParams) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_UNKNOWN);
+ EXPECT_EQ(BAudioManager_setOutputDevice(nullptr, nullptr, kUsageMedia),
+ EINVAL);
+ EXPECT_EQ(BAudioManager_setOutputDevice(bam, nullptr, kUsageMedia), EINVAL);
+ EXPECT_EQ(BAudioManager_setOutputDevice(nullptr, device, kUsageMedia),
+ EINVAL);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, SetOutputDeviceWiredHeadset) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADSET);
+ EXPECT_CALL(*bas_.get(), SetDevice(AUDIO_POLICY_FORCE_FOR_MEDIA,
+ AUDIO_POLICY_FORCE_HEADPHONES))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_setOutputDevice(bam, device, kUsageMedia), 0);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, SetOutputDeviceBuiltinSpeaker) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_BUILTIN_SPEAKER);
+ EXPECT_CALL(*bas_.get(), SetDevice(AUDIO_POLICY_FORCE_FOR_SYSTEM,
+ AUDIO_POLICY_FORCE_SPEAKER))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_setOutputDevice(bam, device, kUsageSystem), 0);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, SetOutputDeviceWiredHeadphoneNotification) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADPHONES);
+ EXPECT_CALL(*bas_.get(), SetDevice(AUDIO_POLICY_FORCE_FOR_SYSTEM,
+ AUDIO_POLICY_FORCE_HEADPHONES))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_setOutputDevice(bam, device, kUsageNotifications), 0);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, SetOutputDeviceWiredHeadphoneAlarm) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADPHONES);
+ EXPECT_CALL(*bas_.get(), SetDevice(AUDIO_POLICY_FORCE_FOR_SYSTEM,
+ AUDIO_POLICY_FORCE_HEADPHONES))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_setOutputDevice(bam, device, kUsageAlarm), 0);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, RegisterCallbackInvalidParams) {
+ auto bam = GetValidManager();
+ BAudioCallback callback;
+ int callback_id;
+ EXPECT_EQ(
+ BAudioManager_registerAudioCallback(nullptr, nullptr, nullptr, nullptr),
+ EINVAL);
+ EXPECT_EQ(BAudioManager_registerAudioCallback(bam, nullptr, nullptr, nullptr),
+ EINVAL);
+ EXPECT_EQ(
+ BAudioManager_registerAudioCallback(bam, &callback, nullptr, nullptr),
+ EINVAL);
+ EXPECT_EQ(
+ BAudioManager_registerAudioCallback(bam, nullptr, nullptr, &callback_id),
+ EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, RegisterCallbackOnStack) {
+ auto bam = GetValidManager();
+ BAudioCallback callback;
+ callback.OnAudioDeviceAdded = nullptr;
+ callback.OnAudioDeviceRemoved = nullptr;
+ int callback_id = 0;
+ EXPECT_CALL(*bas_.get(), RegisterServiceCallback(_))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_registerAudioCallback(bam, &callback, nullptr,
+ &callback_id),
+ 0);
+ EXPECT_NE(callback_id, 0);
+}
+
+TEST_F(BrilloAudioManagerTest, RegisterCallbackOnHeap) {
+ auto bam = GetValidManager();
+ BAudioCallback* callback = new BAudioCallback;
+ callback->OnAudioDeviceAdded = nullptr;
+ callback->OnAudioDeviceRemoved = nullptr;
+ int callback_id = 0;
+ EXPECT_CALL(*bas_.get(), RegisterServiceCallback(_))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(
+ BAudioManager_registerAudioCallback(bam, callback, nullptr, &callback_id),
+ 0);
+ EXPECT_NE(callback_id, 0);
+ delete callback;
+}
+
+TEST_F(BrilloAudioManagerTest, UnregisterCallbackInvalidParams) {
+ auto bam = GetValidManager();
+ EXPECT_EQ(BAudioManager_unregisterAudioCallback(nullptr, 1), EINVAL);
+ EXPECT_EQ(BAudioManager_unregisterAudioCallback(bam, 1), EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, UnregisterCallback) {
+ auto bam = GetValidManager();
+ BAudioCallback callback;
+ callback.OnAudioDeviceAdded = nullptr;
+ callback.OnAudioDeviceRemoved = nullptr;
+ int callback_id = 0;
+ EXPECT_CALL(*bas_.get(), RegisterServiceCallback(_))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_registerAudioCallback(bam, &callback, nullptr,
+ &callback_id),
+ 0);
+ EXPECT_NE(callback_id, 0);
+ EXPECT_CALL(*bas_.get(), UnregisterServiceCallback(_))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_unregisterAudioCallback(bam, callback_id), 0);
+ // 2nd call shouldn't result in a call to BAS.
+ EXPECT_EQ(BAudioManager_unregisterAudioCallback(bam, callback_id), EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, GetDevicesBASDies) {
+ auto bam = GetValidManager();
+ unsigned int num_devices = -1;
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_getDevices(bam, 1, nullptr, 0, &num_devices),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioManagerTest, SetInputDeviceBASDies) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADSET_MIC);
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_setInputDevice(bam, device), ECONNABORTED);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, SetOutputDeviceBASDies) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADPHONES);
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_setOutputDevice(bam, device, kUsageNotifications),
+ ECONNABORTED);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, RegisterServiceCallbackBASDies) {
+ auto bam = GetValidManager();
+ BAudioCallback callback;
+ callback.OnAudioDeviceAdded = nullptr;
+ callback.OnAudioDeviceRemoved = nullptr;
+ int callback_id = 1;
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_registerAudioCallback(bam, &callback, nullptr,
+ &callback_id),
+ ECONNABORTED);
+ EXPECT_EQ(callback_id, 0);
+}
+
+TEST_F(BrilloAudioManagerTest, UnregisterCallbackBASDies) {
+ auto bam = GetValidManager();
+ BAudioCallback callback;
+ callback.OnAudioDeviceAdded = nullptr;
+ callback.OnAudioDeviceRemoved = nullptr;
+ int callback_id = 0;
+ EXPECT_CALL(*bas_.get(), RegisterServiceCallback(_))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_registerAudioCallback(bam, &callback, nullptr,
+ &callback_id),
+ 0);
+ EXPECT_NE(callback_id, 0);
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_unregisterAudioCallback(bam, callback_id),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioManagerTest, GetMaxVolumeStepsInvalidParams) {
+ auto bam = GetValidManager();
+ int foo;
+ EXPECT_EQ(BAudioManager_getMaxVolumeSteps(
+ nullptr, BAudioUsage::kUsageMedia, nullptr),
+ EINVAL);
+ EXPECT_EQ(
+ BAudioManager_getMaxVolumeSteps(nullptr, BAudioUsage::kUsageMedia, &foo),
+ EINVAL);
+ EXPECT_EQ(
+ BAudioManager_getMaxVolumeSteps(bam, BAudioUsage::kUsageMedia, nullptr),
+ EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, GetMaxVolStepsWithBAS) {
+ auto bam = GetValidManager();
+ int foo;
+ EXPECT_CALL(*bas_.get(), GetMaxVolumeSteps(AUDIO_STREAM_MUSIC, &foo))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(
+ BAudioManager_getMaxVolumeSteps(bam, BAudioUsage::kUsageMedia, &foo), 0);
+}
+
+TEST_F(BrilloAudioManagerTest, GetMaxVolStepsBASDies) {
+ auto bam = GetValidManager();
+ int foo;
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(
+ BAudioManager_getMaxVolumeSteps(bam, BAudioUsage::kUsageMedia, &foo),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioManagerTest, SetMaxVolumeStepsInvalidParams) {
+ EXPECT_EQ(
+ BAudioManager_setMaxVolumeSteps(nullptr, BAudioUsage::kUsageMedia, 100),
+ EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, SetMaxVolStepsWithBAS) {
+ auto bam = GetValidManager();
+ EXPECT_CALL(*bas_.get(), SetMaxVolumeSteps(AUDIO_STREAM_MUSIC, 100))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_setMaxVolumeSteps(bam, BAudioUsage::kUsageMedia, 100),
+ 0);
+}
+
+TEST_F(BrilloAudioManagerTest, SetMaxVolStepsBASDies) {
+ auto bam = GetValidManager();
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_setMaxVolumeSteps(bam, BAudioUsage::kUsageMedia, 100),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioManagerTest, SetVolIndexInvalidParams) {
+ auto bam = GetValidManager();
+ EXPECT_EQ(BAudioManager_setVolumeIndex(
+ nullptr, BAudioUsage::kUsageMedia, nullptr, 100),
+ EINVAL);
+ EXPECT_EQ(
+ BAudioManager_setVolumeIndex(bam, BAudioUsage::kUsageMedia, nullptr, 100),
+ EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, SetVolIndexWithBAS) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADPHONES);
+ EXPECT_CALL(
+ *bas_.get(),
+ SetVolumeIndex(AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_WIRED_HEADPHONE, 100))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(
+ BAudioManager_setVolumeIndex(bam, BAudioUsage::kUsageMedia, device, 100),
+ 0);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, SetVolIndexBASDies) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADPHONES);
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(
+ BAudioManager_setVolumeIndex(bam, BAudioUsage::kUsageMedia, device, 100),
+ ECONNABORTED);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, GetVolIndexInvalidParams) {
+ auto bam = GetValidManager();
+ int foo;
+ EXPECT_EQ(BAudioManager_getVolumeIndex(
+ nullptr, BAudioUsage::kUsageMedia, nullptr, nullptr),
+ EINVAL);
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADPHONES);
+ EXPECT_EQ(BAudioManager_getVolumeIndex(
+ bam, BAudioUsage::kUsageMedia, device, nullptr),
+ EINVAL);
+ EXPECT_EQ(BAudioManager_getVolumeIndex(
+ nullptr, BAudioUsage::kUsageMedia, device, &foo),
+ EINVAL);
+ EXPECT_EQ(BAudioManager_getVolumeIndex(
+ bam, BAudioUsage::kUsageMedia, nullptr, &foo),
+ EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, GetVolIndexWithBAS) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADPHONES);
+ int foo;
+ EXPECT_CALL(*bas_.get(),
+ GetVolumeIndex(
+ AUDIO_STREAM_MUSIC, AUDIO_DEVICE_OUT_WIRED_HEADPHONE, &foo))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(
+ BAudioManager_getVolumeIndex(bam, BAudioUsage::kUsageMedia, device, &foo),
+ 0);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, GetVolIndexBASDies) {
+ auto bam = GetValidManager();
+ auto device = BAudioDeviceInfo_new(TYPE_WIRED_HEADPHONES);
+ int foo;
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(
+ BAudioManager_getVolumeIndex(bam, BAudioUsage::kUsageMedia, device, &foo),
+ ECONNABORTED);
+ BAudioDeviceInfo_delete(device);
+}
+
+TEST_F(BrilloAudioManagerTest, GetVolumeControlUsageInvalidParams) {
+ auto bam = GetValidManager();
+ BAudioUsage foo;
+ EXPECT_EQ(BAudioManager_getVolumeControlUsage(nullptr, nullptr), EINVAL);
+ EXPECT_EQ(BAudioManager_getVolumeControlUsage(nullptr, &foo), EINVAL);
+ EXPECT_EQ(BAudioManager_getVolumeControlUsage(bam, nullptr), EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, GetVolumeControlStreamWithBAS) {
+ auto bam = GetValidManager();
+ BAudioUsage foo;
+ EXPECT_CALL(*bas_.get(), GetVolumeControlStream(_))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_getVolumeControlUsage(bam, &foo), 0);
+}
+
+TEST_F(BrilloAudioManagerTest, GetVolumeControlStreamBASDies) {
+ auto bam = GetValidManager();
+ BAudioUsage foo;
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_getVolumeControlUsage(bam, &foo), ECONNABORTED);
+}
+
+TEST_F(BrilloAudioManagerTest, SetVolumeControlUsageInvalidParams) {
+ EXPECT_EQ(
+ BAudioManager_setVolumeControlUsage(nullptr, BAudioUsage::kUsageMedia),
+ EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, SetVolumeControlStreamWithBAS) {
+ auto bam = GetValidManager();
+ EXPECT_CALL(*bas_.get(), SetVolumeControlStream(AUDIO_STREAM_MUSIC))
+ .WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_setVolumeControlUsage(bam, BAudioUsage::kUsageMedia),
+ 0);
+}
+
+TEST_F(BrilloAudioManagerTest, SetVolumeControlStreamBASDies) {
+ auto bam = GetValidManager();
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_setVolumeControlUsage(bam, BAudioUsage::kUsageMedia),
+ ECONNABORTED);
+}
+
+TEST_F(BrilloAudioManagerTest, DecIncInvalidParams) {
+ EXPECT_EQ(BAudioManager_decrementVolume(nullptr), EINVAL);
+ EXPECT_EQ(BAudioManager_incrementVolume(nullptr), EINVAL);
+}
+
+TEST_F(BrilloAudioManagerTest, IncVolWithBAS) {
+ auto bam = GetValidManager();
+ EXPECT_CALL(*bas_.get(), IncrementVolume()).WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_incrementVolume(bam), 0);
+}
+
+TEST_F(BrilloAudioManagerTest, IncVolBASDies) {
+ auto bam = GetValidManager();
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_incrementVolume(bam), ECONNABORTED);
+}
+
+TEST_F(BrilloAudioManagerTest, DecVolWithBAS) {
+ auto bam = GetValidManager();
+ EXPECT_CALL(*bas_.get(), DecrementVolume()).WillOnce(Return(Status::ok()));
+ EXPECT_EQ(BAudioManager_decrementVolume(bam), 0);
+}
+
+TEST_F(BrilloAudioManagerTest, DecVolBASDies) {
+ auto bam = GetValidManager();
+ binder_wrapper()->NotifyAboutBinderDeath(bas_);
+ EXPECT_EQ(BAudioManager_decrementVolume(bam), ECONNABORTED);
+}
+
+} // namespace brillo
diff --git a/brillo/audio/audioservice/test/brillo_audio_service_mock.h b/brillo/audio/audioservice/test/brillo_audio_service_mock.h
new file mode 100644
index 0000000..4b52ef1
--- /dev/null
+++ b/brillo/audio/audioservice/test/brillo_audio_service_mock.h
@@ -0,0 +1,58 @@
+// 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.
+//
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_SERVICE_MOCK_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_SERVICE_MOCK_H_
+
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest_prod.h>
+
+#include "brillo_audio_service.h"
+
+namespace brillo {
+
+class BrilloAudioServiceMock : public BrilloAudioService {
+ public:
+ BrilloAudioServiceMock() = default;
+ ~BrilloAudioServiceMock() {}
+
+ MOCK_METHOD2(GetDevices, Status(int flag, std::vector<int>* _aidl_return));
+ MOCK_METHOD2(SetDevice, Status(int usage, int config));
+ MOCK_METHOD2(GetMaxVolumeSteps, Status(int stream, int* _aidl_return));
+ MOCK_METHOD2(SetMaxVolumeSteps, Status(int stream, int max_steps));
+ MOCK_METHOD3(SetVolumeIndex, Status(int stream, int device, int index));
+ MOCK_METHOD3(GetVolumeIndex,
+ Status(int stream, int device, int* _aidl_return));
+ MOCK_METHOD1(GetVolumeControlStream, Status(int* _aidl_return));
+ MOCK_METHOD1(SetVolumeControlStream, Status(int stream));
+ MOCK_METHOD0(IncrementVolume, Status());
+ MOCK_METHOD0(DecrementVolume, Status());
+ MOCK_METHOD1(RegisterServiceCallback,
+ Status(const android::sp<IAudioServiceCallback>& callback));
+ MOCK_METHOD1(UnregisterServiceCallback,
+ Status(const android::sp<IAudioServiceCallback>& callback));
+
+ void RegisterHandlers(std::weak_ptr<AudioDeviceHandler>,
+ std::weak_ptr<AudioVolumeHandler>){};
+ void OnDevicesConnected(const std::vector<int>&) {}
+ void OnDevicesDisconnected(const std::vector<int>&) {}
+ void OnVolumeChanged(audio_stream_type_t, int, int){};
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_BRILLO_AUDIO_SERVICE_MOCK_H_
diff --git a/camera/src/camera_metadata.c b/camera/src/camera_metadata.c
index c58a966..9491e8e 100644
--- a/camera/src/camera_metadata.c
+++ b/camera/src/camera_metadata.c
@@ -27,7 +27,7 @@
#define OK 0
#define ERROR 1
-#define NOT_FOUND -ENOENT
+#define NOT_FOUND (-ENOENT)
#define ALIGN_TO(val, alignment) \
(((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
@@ -199,9 +199,15 @@
size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
data_capacity);
void *buffer = malloc(memory_needed);
- return place_camera_metadata(buffer, memory_needed,
- entry_capacity,
- data_capacity);
+ camera_metadata_t *metadata = place_camera_metadata(
+ buffer, memory_needed, entry_capacity, data_capacity);
+ if (!metadata) {
+ /* This should not happen when memory_needed is the same
+ * calculated in this function and in place_camera_metadata.
+ */
+ free(buffer);
+ }
+ return metadata;
}
camera_metadata_t *place_camera_metadata(void *dst,