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,