Merge changes from topics \'cam-ndk-hidden-enum\', \'cam-ndk-enum-dco\', \'cam-ndk-hidden-keys\' into nyc-dev
am: b1379bd

* commit 'b1379bdb8fe4ddf1e052bff5e76703f70ec4afab':
  Camera: hide some enum values in NDK
  Camera: codegen NDK metadata enum value documents
  Camera: modify metadata visibility attributes

Change-Id: Ife5a241f013a3f4bac5b41fc2b358005c8cb6a7b
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/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..09da9f7 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,14 +24,21 @@
   libmedia \
   libutils
 
+audio_service_sources := \
+  aidl/android/brillo/brilloaudioservice/IAudioServiceCallback.aidl \
+  aidl/android/brillo/brilloaudioservice/IBrilloAudioService.aidl \
+  audio_daemon.cpp \
+  audio_device_handler.cpp \
+  brillo_audio_service.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
@@ -41,10 +49,14 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := brilloaudioservice_test
 LOCAL_SRC_FILES := \
-  audio_device_handler.cpp \
+  $(audio_service_sources) \
+  test/audio_daemon_test.cpp \
   test/audio_device_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 \
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..01e8ba2
--- /dev/null
+++ b/brillo/audio/audioservice/aidl/android/brillo/brilloaudioservice/IAudioServiceCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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);
+}
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..dce7f81
--- /dev/null
+++ b/brillo/audio/audioservice/aidl/android/brillo/brilloaudioservice/IBrilloAudioService.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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 register callbacks to
+ * be notified when the device state changes.
+ */
+interface IBrilloAudioService {
+  const int GET_DEVICES_INPUTS = 1;
+  const int GET_DEVICES_OUTPUTS = 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);
+
+  // 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..547b116 100644
--- a/brillo/audio/audioservice/audio_daemon.cpp
+++ b/brillo/audio/audioservice/audio_daemon.cpp
@@ -26,15 +26,29 @@
 #include <binderwrapper/binder_wrapper.h>
 #include <linux/input.h>
 
+#include "brillo_audio_service.h"
+
 namespace brillo {
 
 static const char kAPSServiceName[] = "media.audio_policy";
 static const char kInputDeviceDir[] = "/dev/input";
+static const char kServiceName[] =
+    "android.brillo.brilloaudioservice.BrilloAudioService";
+
+AudioDaemon::~AudioDaemon() {}
 
 void AudioDaemon::InitializeHandler() {
   // Start and initialize the audio device handler.
   audio_device_handler_ =
-      std::unique_ptr<AudioDeviceHandler>(new AudioDeviceHandler());
+      std::shared_ptr<AudioDeviceHandler>(new AudioDeviceHandler());
+
+  // Register a callback with the handler to call when device state changes.
+  base::Callback<void(AudioDeviceHandler::DeviceConnectionState,
+                      const std::vector<int>&)> device_callback = base::Bind(
+                          &AudioDaemon::DeviceCallback,
+                          weak_ptr_factory_.GetWeakPtr());
+  audio_device_handler_->RegisterDeviceCallback(device_callback);
+
   audio_device_handler_->Init(aps_);
 
   // Poll on all files in kInputDeviceDir.
@@ -48,17 +62,30 @@
       // 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;
+  // Once the handler has been initialized, we can register with service
+  // manager.
+  InitializeBrilloAudioService();
+}
+
+void AudioDaemon::InitializeBrilloAudioService() {
+  brillo_audio_service_ = new BrilloAudioService();
+  brillo_audio_service_->RegisterDeviceHandler(
+      std::weak_ptr<AudioDeviceHandler>(audio_device_handler_));
+  android::BinderWrapper::Get()->RegisterService(kServiceName,
+                                                 brillo_audio_service_);
+  VLOG(1) << "Registered brilloaudioservice with the service manager.";
 }
 
 void AudioDaemon::ConnectToAPS() {
@@ -107,7 +134,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));
@@ -118,4 +145,21 @@
   audio_device_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);
+}
+
 }  // namespace brillo
diff --git a/brillo/audio/audioservice/audio_daemon.h b/brillo/audio/audioservice/audio_daemon.h
index 48aa35f..2358012 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,12 +29,14 @@
 #include <media/IAudioPolicyService.h>
 
 #include "audio_device_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
@@ -41,9 +44,22 @@
   int OnInit() override;
 
  private:
+  friend class AudioDaemonTest;
+  FRIEND_TEST(AudioDaemonTest, RegisterService);
+  FRIEND_TEST(AudioDaemonTest, TestAPSConnectInitializesHandlerOnlyOnce);
+  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 for audio policy service death notification.
   void OnAPSDisconnected();
@@ -52,18 +68,21 @@
   // if the audio policy service dies.
   void ConnectToAPS();
 
+  // Register the brillo audio service with the service manager.
+  void InitializeBrilloAudioService();
+
   // Initialize the audio_device_handler_.
   //
   // Note: This can only occur after we have connected to the audio policy
   // service.
-  void InitializeHandler();
+  virtual void InitializeHandler();
 
   // 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_;
   // 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.
@@ -71,7 +90,9 @@
   // Flag to indicate whether the handler has been initialized.
   bool handler_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_device_handler.cpp b/brillo/audio/audioservice/audio_device_handler.cpp
index af12c96..d4aac92 100644
--- a/brillo/audio/audioservice/audio_device_handler.cpp
+++ b/brillo/audio/audioservice/audio_device_handler.cpp
@@ -19,6 +19,7 @@
 
 #include <base/files/file.h>
 #include <base/logging.h>
+#include <brillo/message_loops/message_loop.h>
 #include <media/AudioSystem.h>
 
 namespace brillo {
@@ -32,6 +33,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 +84,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 +96,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;
@@ -104,6 +135,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 +145,7 @@
     connected_input_devices_.erase(device);
   else
     connected_output_devices_.erase(device);
+  changed_devices_.push_back(device);
 }
 
 void AudioDeviceHandler::DisconnectAllSupportedDevices() {
@@ -147,7 +180,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..a5e0daa 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>
@@ -59,6 +60,33 @@
   // |aps| is a pointer to the binder object.
   void APSConnect(android::sp<android::IAudioPolicyService> aps);
 
+  // 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);
+
+  // 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_TEST(AudioDeviceHandlerTest,
@@ -125,6 +153,11 @@
   // 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};
@@ -139,12 +172,17 @@
   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/brillo_audio_service.cpp b/brillo/audio/audioservice/brillo_audio_service.cpp
new file mode 100644
index 0000000..b1c4fcb
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_service.cpp
@@ -0,0 +1,72 @@
+// 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.h
+
+#include "brillo_audio_service.h"
+
+using android::binder::Status;
+
+namespace brillo {
+
+Status BrilloAudioService::GetDevices(int flag,
+                                      std::vector<int>* _aidl_return) {
+  auto device_handler = audio_device_handler_.lock();
+  if (device_handler) {
+    return Status::fromExceptionCode(
+        Status::EX_SERVICE_SPECIFIC,
+        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::fromExceptionCode(Status::EX_SERVICE_SPECIFIC,
+                                     android::String8("Invalid flag."));
+  }
+  return Status::ok();
+}
+
+Status BrilloAudioService::RegisterServiceCallback(
+    const android::sp<IAudioServiceCallback>& callback) {
+  callbacks_set_.insert(callback);
+  return Status::ok();
+}
+
+Status BrilloAudioService::UnregisterServiceCallback(
+    const android::sp<IAudioServiceCallback>& callback) {
+  callbacks_set_.erase(callback);
+  return Status::ok();
+}
+
+void BrilloAudioService::RegisterDeviceHandler(
+    std::weak_ptr<AudioDeviceHandler> audio_device_handler) {
+  audio_device_handler_ = audio_device_handler;
+}
+
+void BrilloAudioService::OnDevicesConnected(const std::vector<int>& devices) {
+  for (auto callback : callbacks_set_) {
+    callback->OnAudioDevicesConnected(devices);
+  }
+}
+
+void BrilloAudioService::OnDevicesDisconnected(const std::vector<int>& devices) {
+  for (auto callback : callbacks_set_) {
+    callback->OnAudioDevicesDisconnected(devices);
+  }
+}
+
+}  // namespace brillo
diff --git a/brillo/audio/audioservice/brillo_audio_service.h b/brillo/audio/audioservice/brillo_audio_service.h
new file mode 100644
index 0000000..d0dc18b
--- /dev/null
+++ b/brillo/audio/audioservice/brillo_audio_service.h
@@ -0,0 +1,71 @@
+// 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 "audio_device_handler.h"
+#include "android/brillo/brilloaudioservice/IAudioServiceCallback.h"
+
+using android::binder::Status;
+using android::brillo::brilloaudioservice::BnBrilloAudioService;
+using android::brillo::brilloaudioservice::IAudioServiceCallback;
+
+namespace brillo {
+
+class BrilloAudioService : public BnBrilloAudioService {
+ public:
+  // From AIDL.
+  Status GetDevices(int flag, std::vector<int>* _aidl_return);
+
+  Status RegisterServiceCallback(
+      const android::sp<IAudioServiceCallback>& callback);
+  Status UnregisterServiceCallback(
+      const android::sp<IAudioServiceCallback>& callback);
+
+  // Register a device handler.
+  //
+  // |audio_device_handler| is a weak pointer to an audio device handler object.
+  void RegisterDeviceHandler(
+      std::weak_ptr<AudioDeviceHandler> audio_device_handler);
+
+  // 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);
+
+  // 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);
+
+ private:
+  // A weak pointer to the audio device handler.
+  std::weak_ptr<AudioDeviceHandler> audio_device_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_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/test/audio_daemon_mock.h b/brillo/audio/audioservice/test/audio_daemon_mock.h
new file mode 100644
index 0000000..b01e947
--- /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, TestAPSConnectInitializesHandlerOnlyOnce);
+  FRIEND_TEST(AudioDaemonTest, TestDeviceCallbackInitializesBASIfNULL);
+
+  MOCK_METHOD0(InitializeHandler, 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..0ad7535
--- /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, TestAPSConnectInitializesHandlerOnlyOnce) {
+  binder_wrapper()->SetBinderForService("media.audio_policy",
+                                        binder_wrapper()->CreateLocalBinder());
+  daemon_.handler_initialized_ = false;
+  EXPECT_CALL(daemon_, InitializeHandler()).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/camera/src/camera_metadata.c b/camera/src/camera_metadata.c
index c58a966..aa94e93 100644
--- a/camera/src/camera_metadata.c
+++ b/camera/src/camera_metadata.c
@@ -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,