Merge "HLS: some fixes for seek with discontinuity."
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index f70d981..a68a9cb 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -88,8 +88,8 @@
      * user:    Pointer to context for use by the callback receiver.
      * info:    Pointer to optional parameter according to event type:
      *          - EVENT_MORE_DATA: pointer to AudioRecord::Buffer struct. The callback must not read
-     *            more bytes than indicated by 'size' field and update 'size' if fewer bytes are
-     *            consumed.
+     *                             more bytes than indicated by 'size' field and update 'size' if
+     *                             fewer bytes are consumed.
      *          - EVENT_OVERRUN: unused.
      *          - EVENT_MARKER: pointer to const uint32_t containing the marker position in frames.
      *          - EVENT_NEW_POS: pointer to const uint32_t containing the new position in frames.
@@ -106,6 +106,7 @@
      *  - BAD_VALUE: unsupported configuration
      * frameCount is guaranteed to be non-zero if status is NO_ERROR,
      * and is undefined otherwise.
+     * FIXME This API assumes a route, and so should be deprecated.
      */
 
      static status_t getMinFrameCount(size_t* frameCount,
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 2ab3dd6..ad5d6ed 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -98,10 +98,13 @@
 
     // Returned samplingRate and frameCount output values are guaranteed
     // to be non-zero if status == NO_ERROR
+    // FIXME This API assumes a route, and so should be deprecated.
     static status_t getOutputSamplingRate(uint32_t* samplingRate,
             audio_stream_type_t stream);
+    // FIXME This API assumes a route, and so should be deprecated.
     static status_t getOutputFrameCount(size_t* frameCount,
             audio_stream_type_t stream);
+    // FIXME This API assumes a route, and so should be deprecated.
     static status_t getOutputLatency(uint32_t* latency,
             audio_stream_type_t stream);
     static status_t getSamplingRate(audio_io_handle_t output,
@@ -110,19 +113,20 @@
     // audio_stream->get_buffer_size()/audio_stream_out_frame_size()
     static status_t getFrameCount(audio_io_handle_t output,
                                   size_t* frameCount);
-    // returns the audio output stream latency in ms. Corresponds to
+    // returns the audio output latency in ms. Corresponds to
     // audio_stream_out->get_latency()
     static status_t getLatency(audio_io_handle_t output,
                                uint32_t* latency);
 
     // return status NO_ERROR implies *buffSize > 0
+    // FIXME This API assumes a route, and so should deprecated.
     static status_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
         audio_channel_mask_t channelMask, size_t* buffSize);
 
     static status_t setVoiceVolume(float volume);
 
     // return the number of audio frames written by AudioFlinger to audio HAL and
-    // audio dsp to DAC since the specified output I/O handle has exited standby.
+    // audio dsp to DAC since the specified output has exited standby.
     // returned status (from utils/Errors.h) can be:
     // - NO_ERROR: successful operation, halFrames and dspFrames point to valid data
     // - INVALID_OPERATION: Not supported on current hardware platform
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 31a14f0..f927a80 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -94,6 +94,8 @@
                                 sp<IMemory>& buffers,   // return value 0 means it follows cblk
                                 status_t *status) = 0;
 
+    // FIXME Surprisingly, sampleRate/format/frameCount/latency don't work for input handles
+
     /* query the audio hardware state. This state never changes,
      * and therefore can be cached.
      */
@@ -142,6 +144,7 @@
     virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
 
     // retrieve the audio recording buffer size
+    // FIXME This API assumes a route, and so should be deprecated.
     virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
             audio_channel_mask_t channelMask) const = 0;
 
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 442c861..aa91485 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -299,6 +299,8 @@
     status_t setupRawAudioFormat(
             OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);
 
+    status_t setPriority(int32_t priority);
+
     status_t setMinBufferSize(OMX_U32 portIndex, size_t size);
 
     status_t setupMPEG4EncoderParameters(const sp<AMessage> &msg);
diff --git a/include/media/stagefright/ProcessInfo.h b/include/media/stagefright/ProcessInfo.h
new file mode 100644
index 0000000..ec0cdff
--- /dev/null
+++ b/include/media/stagefright/ProcessInfo.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 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 PROCESS_INFO_H_
+
+#define PROCESS_INFO_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/ProcessInfoInterface.h>
+
+namespace android {
+
+struct ProcessInfo : public ProcessInfoInterface {
+    ProcessInfo();
+
+    virtual bool getPriority(int pid, int* priority);
+
+protected:
+    virtual ~ProcessInfo();
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(ProcessInfo);
+};
+
+}  // namespace android
+
+#endif  // PROCESS_INFO_H_
diff --git a/media/libmediaplayerservice/ProcessInfoInterface.h b/include/media/stagefright/ProcessInfoInterface.h
similarity index 100%
rename from media/libmediaplayerservice/ProcessInfoInterface.h
rename to include/media/stagefright/ProcessInfoInterface.h
diff --git a/include/media/stagefright/foundation/ABase.h b/include/media/stagefright/foundation/ABase.h
index 72e3d87..ef1e010 100644
--- a/include/media/stagefright/foundation/ABase.h
+++ b/include/media/stagefright/foundation/ABase.h
@@ -18,7 +18,9 @@
 
 #define A_BASE_H_
 
+#ifndef ARRAY_SIZE
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+#endif
 
 #define DISALLOW_EVIL_CONSTRUCTORS(name) \
     name(const name &); \
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 7143f1a..5644428 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -53,8 +53,8 @@
 struct AudioTrackSharedStreaming {
     // similar to NBAIO MonoPipe
     // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2
-    volatile int32_t mFront;    // read by server
-    volatile int32_t mRear;     // write by client
+    volatile int32_t mFront;    // read by consumer (output: server, input: client)
+    volatile int32_t mRear;     // written by producer (output: client, input: server)
     volatile int32_t mFlush;    // incremented by client to indicate a request to flush;
                                 // server notices and discards all data between mFront and mRear
     volatile uint32_t mUnderrunFrames;  // server increments for each unavailable but desired frame
diff --git a/include/radio/IRadio.h b/include/radio/IRadio.h
new file mode 100644
index 0000000..1877f8f
--- /dev/null
+++ b/include/radio/IRadio.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_HARDWARE_IRADIO_H
+#define ANDROID_HARDWARE_IRADIO_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <system/radio.h>
+
+namespace android {
+
+class IRadio : public IInterface
+{
+public:
+
+    DECLARE_META_INTERFACE(Radio);
+
+    virtual void detach() = 0;
+
+    virtual status_t setConfiguration(const struct radio_band_config *config) = 0;
+
+    virtual status_t getConfiguration(struct radio_band_config *config) = 0;
+
+    virtual status_t setMute(bool mute) = 0;
+
+    virtual status_t getMute(bool *mute) = 0;
+
+    virtual status_t step(radio_direction_t direction, bool skipSubChannel) = 0;
+
+    virtual status_t scan(radio_direction_t direction, bool skipSubChannel) = 0;
+
+    virtual status_t tune(unsigned int channel, unsigned int subChannel) = 0;
+
+    virtual status_t cancel() = 0;
+
+    virtual status_t getProgramInformation(struct radio_program_info *info) = 0;
+
+    virtual status_t hasControl(bool *hasControl) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnRadio: public BnInterface<IRadio>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_IRADIO_H
diff --git a/include/radio/IRadioClient.h b/include/radio/IRadioClient.h
new file mode 100644
index 0000000..9062ad6
--- /dev/null
+++ b/include/radio/IRadioClient.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_HARDWARE_IRADIO_CLIENT_H
+#define ANDROID_HARDWARE_IRADIO_CLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IRadioClient : public IInterface
+{
+public:
+
+    DECLARE_META_INTERFACE(RadioClient);
+
+    virtual void onEvent(const sp<IMemory>& eventMemory) = 0;
+
+};
+
+// ----------------------------------------------------------------------------
+
+class BnRadioClient : public BnInterface<IRadioClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_IRADIO_CLIENT_H
diff --git a/include/radio/IRadioService.h b/include/radio/IRadioService.h
new file mode 100644
index 0000000..a946dd5
--- /dev/null
+++ b/include/radio/IRadioService.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_HARDWARE_IRADIO_SERVICE_H
+#define ANDROID_HARDWARE_IRADIO_SERVICE_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <system/radio.h>
+
+namespace android {
+
+class IRadio;
+class IRadioClient;
+
+class IRadioService : public IInterface
+{
+public:
+
+    DECLARE_META_INTERFACE(RadioService);
+
+    virtual status_t listModules(struct radio_properties *properties,
+                                 uint32_t *numModules) = 0;
+
+    virtual status_t attach(const radio_handle_t handle,
+                            const sp<IRadioClient>& client,
+                            const struct radio_band_config *config,
+                            bool withAudio,
+                            sp<IRadio>& radio) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnRadioService: public BnInterface<IRadioService>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_IRADIO_SERVICE_H
diff --git a/include/radio/Radio.h b/include/radio/Radio.h
new file mode 100644
index 0000000..302bf16
--- /dev/null
+++ b/include/radio/Radio.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_HARDWARE_RADIO_H
+#define ANDROID_HARDWARE_RADIO_H
+
+#include <binder/IBinder.h>
+#include <utils/threads.h>
+#include <radio/RadioCallback.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioService.h>
+#include <radio/IRadioClient.h>
+#include <system/radio.h>
+
+namespace android {
+
+class MemoryDealer;
+
+class Radio : public BnRadioClient,
+                        public IBinder::DeathRecipient
+{
+public:
+
+    virtual ~Radio();
+
+    static  status_t listModules(struct radio_properties *properties,
+                                 uint32_t *numModules);
+    static  sp<Radio> attach(radio_handle_t handle,
+                             const struct radio_band_config *config,
+                             bool withAudio,
+                             const sp<RadioCallback>& callback);
+
+
+            void detach();
+
+            status_t setConfiguration(const struct radio_band_config *config);
+
+            status_t getConfiguration(struct radio_band_config *config);
+
+            status_t setMute(bool mute);
+
+            status_t getMute(bool *mute);
+
+            status_t step(radio_direction_t direction, bool skipSubChannel);
+
+            status_t scan(radio_direction_t direction, bool skipSubChannel);
+
+            status_t tune(unsigned int channel, unsigned int subChannel);
+
+            status_t cancel();
+
+            status_t getProgramInformation(struct radio_program_info *info);
+
+            status_t hasControl(bool *hasControl);
+
+            // BpRadioClient
+            virtual void onEvent(const sp<IMemory>& eventMemory);
+
+            //IBinder::DeathRecipient
+            virtual void binderDied(const wp<IBinder>& who);
+
+private:
+            Radio(radio_handle_t handle,
+                            const sp<RadioCallback>&);
+            static const sp<IRadioService>& getRadioService();
+
+            Mutex                   mLock;
+            sp<IRadio>              mIRadio;
+            const radio_handle_t    mHandle;
+            sp<RadioCallback>       mCallback;
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_RADIO_H
diff --git a/include/radio/RadioCallback.h b/include/radio/RadioCallback.h
new file mode 100644
index 0000000..4a7f1a6
--- /dev/null
+++ b/include/radio/RadioCallback.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_HARDWARE_RADIO_CALLBACK_H
+#define ANDROID_HARDWARE_RADIO_CALLBACK_H
+
+#include <utils/RefBase.h>
+#include <system/radio.h>
+
+namespace android {
+
+class RadioCallback : public RefBase
+{
+public:
+
+            RadioCallback() {}
+    virtual ~RadioCallback() {}
+
+    virtual void onEvent(struct radio_event *event) = 0;
+
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_RADIO_CALLBACK_H
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 08241e2..6d5f1af 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -423,7 +423,6 @@
             goto end;
         }
         // check for obtainBuffer interrupted by client
-        // check for obtainBuffer interrupted by client
         if (flags & CBLK_INTERRUPT) {
             ALOGV("waitStreamEndDone() interrupted by client");
             status = -EINTR;
diff --git a/media/libmediaplayerservice/DrmSessionManager.cpp b/media/libmediaplayerservice/DrmSessionManager.cpp
index 6e17eb1..641f881 100644
--- a/media/libmediaplayerservice/DrmSessionManager.cpp
+++ b/media/libmediaplayerservice/DrmSessionManager.cpp
@@ -21,10 +21,10 @@
 #include "DrmSessionManager.h"
 
 #include "DrmSessionClientInterface.h"
-#include "ProcessInfoInterface.h"
 #include <binder/IPCThreadState.h>
 #include <binder/IProcessInfoService.h>
 #include <binder/IServiceManager.h>
+#include <media/stagefright/ProcessInfo.h>
 #include <unistd.h>
 #include <utils/String8.h>
 
@@ -38,37 +38,6 @@
     return sessionIdStr;
 }
 
-struct ProcessInfo : public ProcessInfoInterface {
-    ProcessInfo() {}
-
-    virtual bool getPriority(int pid, int* priority) {
-        sp<IBinder> binder = defaultServiceManager()->getService(String16("processinfo"));
-        sp<IProcessInfoService> service = interface_cast<IProcessInfoService>(binder);
-
-        size_t length = 1;
-        int32_t states;
-        status_t err = service->getProcessStatesFromPids(length, &pid, &states);
-        if (err != OK) {
-            ALOGE("getProcessStatesFromPids failed");
-            return false;
-        }
-        ALOGV("pid %d states %d", pid, states);
-        if (states < 0) {
-            return false;
-        }
-
-        // Use process state as the priority. Lower the value, higher the priority.
-        *priority = states;
-        return true;
-    }
-
-protected:
-    virtual ~ProcessInfo() {}
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(ProcessInfo);
-};
-
 bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
     if (sessionId1.size() != sessionId2.size()) {
         return false;
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index 27b482b..d3e760b 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -23,8 +23,8 @@
 #include "Drm.h"
 #include "DrmSessionClientInterface.h"
 #include "DrmSessionManager.h"
-#include "ProcessInfoInterface.h"
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/ProcessInfoInterface.h>
 
 namespace android {
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index c75d4df..31e10ce 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1676,6 +1676,11 @@
         err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
     }
 
+    int32_t priority;
+    if (msg->findInt32("priority", &priority)) {
+        err = setPriority(priority);
+    }
+
     mBaseOutputFormat = outputFormat;
 
     CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
@@ -1686,6 +1691,22 @@
     return err;
 }
 
+status_t ACodec::setPriority(int32_t priority) {
+    if (priority < 0) {
+        return BAD_VALUE;
+    }
+    OMX_PARAM_U32TYPE config;
+    InitOMXParams(&config);
+    config.nU32 = (OMX_U32)priority;
+    status_t temp = mOMX->setConfig(
+            mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority,
+            &config, sizeof(config));
+    if (temp != OK) {
+        ALOGI("codec does not support config priority (err %d)", temp);
+    }
+    return OK;
+}
+
 status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 38f2e34..177293d 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -47,6 +47,7 @@
         OMXClient.cpp                     \
         OMXCodec.cpp                      \
         OggExtractor.cpp                  \
+        ProcessInfo.cpp                   \
         SampleIterator.cpp                \
         SampleTable.cpp                   \
         SkipCutBuffer.cpp                 \
diff --git a/media/libstagefright/ProcessInfo.cpp b/media/libstagefright/ProcessInfo.cpp
new file mode 100644
index 0000000..b4172b3
--- /dev/null
+++ b/media/libstagefright/ProcessInfo.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ProcessInfo"
+#include <utils/Log.h>
+
+#include <media/stagefright/ProcessInfo.h>
+
+#include <binder/IProcessInfoService.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+
+ProcessInfo::ProcessInfo() {}
+
+bool ProcessInfo::getPriority(int pid, int* priority) {
+    sp<IBinder> binder = defaultServiceManager()->getService(String16("processinfo"));
+    sp<IProcessInfoService> service = interface_cast<IProcessInfoService>(binder);
+
+    size_t length = 1;
+    int32_t states;
+    status_t err = service->getProcessStatesFromPids(length, &pid, &states);
+    if (err != OK) {
+        ALOGE("getProcessStatesFromPids failed");
+        return false;
+    }
+    ALOGV("pid %d states %d", pid, states);
+    if (states < 0) {
+        return false;
+    }
+
+    // Use process state as the priority. Lower the value, higher the priority.
+    *priority = states;
+    return true;
+}
+
+ProcessInfo::~ProcessInfo() {}
+
+}  // namespace android
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 530383b..e8abf48 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -26,6 +26,7 @@
 #include <media/hardware/MetadataBufferType.h>
 
 #include <ui/GraphicBuffer.h>
+#include <gui/BufferItem.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/IGraphicBufferAlloc.h>
 #include <OMX_Component.h>
@@ -290,7 +291,7 @@
     // TODO: mCurrentSlot can be made a bufferstate since there
     // can be more than one "current" slots.
 
-    BufferQueue::BufferItem item;
+    BufferItem item;
     // If the recording has started and the queue is empty, then just
     // wait here till the frames come in from the client side
     while (mStarted) {
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 5ec3438..8ef2dca 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -26,6 +26,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
+#include <utils/misc.h>
 
 namespace android {
 
@@ -186,17 +187,31 @@
             if (aspect_ratio_idc == 255 /* extendedSAR */) {
                 sar_width = br.getBits(16);
                 sar_height = br.getBits(16);
-            } else if (aspect_ratio_idc > 0 && aspect_ratio_idc < 14) {
-                static const int32_t kFixedSARWidth[] = {
-                    1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160
+            } else {
+                static const struct { unsigned width, height; } kFixedSARs[] = {
+                        {   0,  0 }, // Invalid
+                        {   1,  1 },
+                        {  12, 11 },
+                        {  10, 11 },
+                        {  16, 11 },
+                        {  40, 33 },
+                        {  24, 11 },
+                        {  20, 11 },
+                        {  32, 11 },
+                        {  80, 33 },
+                        {  18, 11 },
+                        {  15, 11 },
+                        {  64, 33 },
+                        { 160, 99 },
+                        {   4,  3 },
+                        {   3,  2 },
+                        {   2,  1 },
                 };
 
-                static const int32_t kFixedSARHeight[] = {
-                    1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99
-                };
-
-                sar_width = kFixedSARWidth[aspect_ratio_idc - 1];
-                sar_height = kFixedSARHeight[aspect_ratio_idc - 1];
+                if (aspect_ratio_idc > 0 && aspect_ratio_idc < NELEM(kFixedSARs)) {
+                    sar_width = kFixedSARs[aspect_ratio_idc].width;
+                    sar_height = kFixedSARs[aspect_ratio_idc].height;
+                }
             }
         }
 
diff --git a/media/libstagefright/filters/GraphicBufferListener.cpp b/media/libstagefright/filters/GraphicBufferListener.cpp
index fa38192..66374ba 100644
--- a/media/libstagefright/filters/GraphicBufferListener.cpp
+++ b/media/libstagefright/filters/GraphicBufferListener.cpp
@@ -21,6 +21,8 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaErrors.h>
 
+#include <gui/BufferItem.h>
+
 #include "GraphicBufferListener.h"
 
 namespace android {
@@ -83,8 +85,8 @@
     // nothing to do
 }
 
-BufferQueue::BufferItem GraphicBufferListener::getBufferItem() {
-    BufferQueue::BufferItem item;
+BufferItem GraphicBufferListener::getBufferItem() {
+    BufferItem item;
 
     {
         Mutex::Autolock autoLock(mMutex);
@@ -124,8 +126,7 @@
     return item;
 }
 
-sp<GraphicBuffer> GraphicBufferListener::getBuffer(
-        BufferQueue::BufferItem item) {
+sp<GraphicBuffer> GraphicBufferListener::getBuffer(BufferItem item) {
     sp<GraphicBuffer> buf;
     if (item.mBuf < 0 || item.mBuf >= BufferQueue::NUM_BUFFER_SLOTS) {
         ALOGE("getBuffer() received invalid BufferItem: mBuf==%d", item.mBuf);
@@ -138,8 +139,7 @@
     return buf;
 }
 
-status_t GraphicBufferListener::releaseBuffer(
-        BufferQueue::BufferItem item) {
+status_t GraphicBufferListener::releaseBuffer(BufferItem item) {
     if (item.mBuf < 0 || item.mBuf >= BufferQueue::NUM_BUFFER_SLOTS) {
         ALOGE("getBuffer() received invalid BufferItem: mBuf==%d", item.mBuf);
         return ERROR_OUT_OF_RANGE;
diff --git a/media/libstagefright/filters/GraphicBufferListener.h b/media/libstagefright/filters/GraphicBufferListener.h
index b3e0ee3..586bf65 100644
--- a/media/libstagefright/filters/GraphicBufferListener.h
+++ b/media/libstagefright/filters/GraphicBufferListener.h
@@ -41,9 +41,9 @@
         return mProducer;
     }
 
-    BufferQueue::BufferItem getBufferItem();
-    sp<GraphicBuffer> getBuffer(BufferQueue::BufferItem item);
-    status_t releaseBuffer(BufferQueue::BufferItem item);
+    BufferItem getBufferItem();
+    sp<GraphicBuffer> getBuffer(BufferItem item);
+    status_t releaseBuffer(BufferItem item);
 
     enum {
         kWhatFrameAvailable = 'frav',
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index d2f662d..0a09575 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -31,6 +31,8 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaFilter.h>
 
+#include <gui/BufferItem.h>
+
 #include "ColorConvert.h"
 #include "GraphicBufferListener.h"
 #include "IntrinsicBlurFilter.h"
@@ -749,7 +751,7 @@
 }
 
 void MediaFilter::onInputFrameAvailable() {
-    BufferQueue::BufferItem item = mGraphicBufferListener->getBufferItem();
+    BufferItem item = mGraphicBufferListener->getBufferItem();
     sp<GraphicBuffer> buf = mGraphicBufferListener->getBuffer(item);
 
     // get pointer to graphic buffer
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index d81da3f..477cfc6 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -28,6 +28,7 @@
 
 #include <media/hardware/MetadataBufferType.h>
 #include <ui/GraphicBuffer.h>
+#include <gui/BufferItem.h>
 
 #include <inttypes.h>
 #include "FrameDropper.h"
@@ -360,7 +361,7 @@
         mSuspended = true;
 
         while (mNumFramesAvailable > 0) {
-            BufferQueue::BufferItem item;
+            BufferItem item;
             status_t err = mConsumer->acquireBuffer(&item, 0);
 
             if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
@@ -410,7 +411,7 @@
 
     ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
             mNumFramesAvailable);
-    BufferQueue::BufferItem item;
+    BufferItem item;
     status_t err = mConsumer->acquireBuffer(&item, 0);
     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
         // shouldn't happen
@@ -503,7 +504,7 @@
         return false;
     }
 
-    BufferQueue::BufferItem item;
+    BufferItem item;
     item.mBuf = mLatestBufferId;
     item.mFrameNumber = mLatestBufferFrameNum;
     item.mTimestamp = mRepeatLastFrameTimestamp;
@@ -534,7 +535,7 @@
 }
 
 void GraphicBufferSource::setLatestBuffer_l(
-        const BufferQueue::BufferItem &item, bool dropped) {
+        const BufferItem &item, bool dropped) {
     ALOGV("setLatestBuffer_l");
 
     if (mLatestBufferId >= 0) {
@@ -590,7 +591,7 @@
     return OK;
 }
 
-int64_t GraphicBufferSource::getTimestamp(const BufferQueue::BufferItem &item) {
+int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) {
     int64_t timeUs = item.mTimestamp / 1000;
 
     if (mTimePerCaptureUs > 0ll) {
@@ -651,7 +652,7 @@
 }
 
 status_t GraphicBufferSource::submitBuffer_l(
-        const BufferQueue::BufferItem &item, int cbi) {
+        const BufferItem &item, int cbi) {
     ALOGV("submitBuffer_l cbi=%d", cbi);
 
     int64_t timeUs = getTimestamp(item);
@@ -777,7 +778,7 @@
             ALOGV("onFrameAvailable: suspended, ignoring frame");
         }
 
-        BufferQueue::BufferItem item;
+        BufferItem item;
         status_t err = mConsumer->acquireBuffer(&item, 0);
         if (err == OK) {
             // If this is the first time we're seeing this buffer, add it to our
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index ce3881e..1067472 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -192,15 +192,15 @@
 
     // Marks the mCodecBuffers entry as in-use, copies the GraphicBuffer
     // reference into the codec buffer, and submits the data to the codec.
-    status_t submitBuffer_l(const BufferQueue::BufferItem &item, int cbi);
+    status_t submitBuffer_l(const BufferItem &item, int cbi);
 
     // Submits an empty buffer, with the EOS flag set.   Returns without
     // doing anything if we don't have a codec buffer available.
     void submitEndOfInputStream_l();
 
-    void setLatestBuffer_l(const BufferQueue::BufferItem &item, bool dropped);
+    void setLatestBuffer_l(const BufferItem &item, bool dropped);
     bool repeatLatestBuffer_l();
-    int64_t getTimestamp(const BufferQueue::BufferItem &item);
+    int64_t getTimestamp(const BufferItem &item);
 
     // Lock, covers all member variables.
     mutable Mutex mMutex;
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index f1b84ad..0ad0bf3 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -26,7 +26,8 @@
 	libutils \
 	liblog \
 	libbinder \
-	libsoundtriggerservice
+	libsoundtriggerservice \
+	libradioservice
 
 LOCAL_STATIC_LIBRARIES := \
 	libregistermsext
@@ -38,7 +39,8 @@
     frameworks/av/services/audiopolicy \
     frameworks/av/services/camera/libcameraservice \
     $(call include-path-for, audio-utils) \
-    frameworks/av/services/soundtrigger
+    frameworks/av/services/soundtrigger \
+    frameworks/av/services/radio
 
 LOCAL_MODULE:= mediaserver
 LOCAL_32_BIT_ONLY := true
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 263dd32..99572f8 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -35,6 +35,7 @@
 #include "MediaPlayerService.h"
 #include "service/AudioPolicyService.h"
 #include "SoundTriggerHwService.h"
+#include "RadioService.h"
 
 using namespace android;
 
@@ -130,6 +131,7 @@
         CameraService::instantiate();
         AudioPolicyService::instantiate();
         SoundTriggerHwService::instantiate();
+        RadioService::instantiate();
         registerExtensions();
         ProcessState::self()->startThreadPool();
         IPCThreadState::self()->joinThreadPool();
diff --git a/radio/Android.mk b/radio/Android.mk
new file mode 100644
index 0000000..ecbb8fd
--- /dev/null
+++ b/radio/Android.mk
@@ -0,0 +1,39 @@
+# Copyright 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	Radio.cpp \
+	IRadio.cpp \
+	IRadioClient.cpp \
+	IRadioService.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+	liblog \
+	libbinder \
+	libhardware \
+	libradio_metadata
+
+#LOCAL_C_INCLUDES += \
+	system/media/camera/include \
+	system/media/private/camera/include
+
+LOCAL_MODULE:= libradio
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/radio/IRadio.cpp b/radio/IRadio.cpp
new file mode 100644
index 0000000..242df77
--- /dev/null
+++ b/radio/IRadio.cpp
@@ -0,0 +1,344 @@
+/*
+**
+** Copyright 2015, 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.
+*/
+
+#define LOG_TAG "IRadio"
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <binder/IMemory.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioService.h>
+#include <radio/IRadioClient.h>
+#include <system/radio.h>
+#include <system/radio_metadata.h>
+
+namespace android {
+
+enum {
+    DETACH = IBinder::FIRST_CALL_TRANSACTION,
+    SET_CONFIGURATION,
+    GET_CONFIGURATION,
+    SET_MUTE,
+    GET_MUTE,
+    SCAN,
+    STEP,
+    TUNE,
+    CANCEL,
+    GET_PROGRAM_INFORMATION,
+    HAS_CONTROL
+};
+
+class BpRadio: public BpInterface<IRadio>
+{
+public:
+    BpRadio(const sp<IBinder>& impl)
+        : BpInterface<IRadio>(impl)
+    {
+    }
+
+    void detach()
+    {
+        ALOGV("detach");
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        remote()->transact(DETACH, data, &reply);
+    }
+
+    virtual status_t setConfiguration(const struct radio_band_config *config)
+    {
+        Parcel data, reply;
+        if (config == NULL) {
+            return BAD_VALUE;
+        }
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.write(config, sizeof(struct radio_band_config));
+        status_t status = remote()->transact(SET_CONFIGURATION, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t getConfiguration(struct radio_band_config *config)
+    {
+        Parcel data, reply;
+        if (config == NULL) {
+            return BAD_VALUE;
+        }
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_CONFIGURATION, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            if (status == NO_ERROR) {
+                reply.read(config, sizeof(struct radio_band_config));
+            }
+        }
+        return status;
+    }
+
+    virtual status_t setMute(bool mute)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.writeInt32(mute ? 1 : 0);
+        status_t status = remote()->transact(SET_MUTE, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t getMute(bool *mute)
+    {
+        Parcel data, reply;
+        if (mute == NULL) {
+            return BAD_VALUE;
+        }
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_MUTE, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            if (status == NO_ERROR) {
+                int muteread = reply.readInt32();
+                *mute = muteread != 0;
+            }
+        }
+        return status;
+    }
+
+    virtual status_t scan(radio_direction_t direction, bool skipSubChannel)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.writeInt32(direction);
+        data.writeInt32(skipSubChannel ? 1 : 0);
+        status_t status = remote()->transact(SCAN, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t step(radio_direction_t direction, bool skipSubChannel)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.writeInt32(direction);
+        data.writeInt32(skipSubChannel ? 1 : 0);
+        status_t status = remote()->transact(STEP, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t tune(unsigned int channel, unsigned int subChannel)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.writeInt32(channel);
+        data.writeInt32(subChannel);
+        status_t status = remote()->transact(TUNE, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t cancel()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(CANCEL, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t getProgramInformation(struct radio_program_info *info)
+    {
+        Parcel data, reply;
+        if (info == NULL) {
+            return BAD_VALUE;
+        }
+        radio_metadata_t *metadata = info->metadata;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_PROGRAM_INFORMATION, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            if (status == NO_ERROR) {
+                reply.read(info, sizeof(struct radio_program_info));
+                info->metadata = metadata;
+                if (metadata == NULL) {
+                    return status;
+                }
+                size_t size = (size_t)reply.readInt32();
+                if (size == 0) {
+                    return status;
+                }
+                metadata =
+                    (radio_metadata_t *)calloc(size / sizeof(unsigned int), sizeof(unsigned int));
+                if (metadata == NULL) {
+                    return NO_MEMORY;
+                }
+                reply.read(metadata, size);
+                status = radio_metadata_add_metadata(&info->metadata, metadata);
+                free(metadata);
+            }
+        }
+        return status;
+    }
+
+    virtual status_t hasControl(bool *hasControl)
+    {
+        Parcel data, reply;
+        if (hasControl == NULL) {
+            return BAD_VALUE;
+        }
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(HAS_CONTROL, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            if (status == NO_ERROR) {
+                *hasControl = reply.readInt32() != 0;
+            }
+        }
+        return status;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(Radio, "android.hardware.IRadio");
+
+// ----------------------------------------------------------------------
+
+status_t BnRadio::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case DETACH: {
+            ALOGV("DETACH");
+            CHECK_INTERFACE(IRadio, data, reply);
+            detach();
+            return NO_ERROR;
+        } break;
+        case SET_CONFIGURATION: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            struct radio_band_config config;
+            data.read(&config, sizeof(struct radio_band_config));
+            status_t status = setConfiguration(&config);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case GET_CONFIGURATION: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            struct radio_band_config config;
+            status_t status = getConfiguration(&config);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->write(&config, sizeof(struct radio_band_config));
+            }
+            return NO_ERROR;
+        }
+        case SET_MUTE: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            bool mute = data.readInt32() != 0;
+            status_t status = setMute(mute);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case GET_MUTE: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            bool mute;
+            status_t status = getMute(&mute);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(mute ? 1 : 0);
+            }
+            return NO_ERROR;
+        }
+        case SCAN: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            radio_direction_t direction = (radio_direction_t)data.readInt32();
+            bool skipSubChannel = data.readInt32() == 1;
+            status_t status = scan(direction, skipSubChannel);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case STEP: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            radio_direction_t direction = (radio_direction_t)data.readInt32();
+            bool skipSubChannel = data.readInt32() == 1;
+            status_t status = step(direction, skipSubChannel);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case TUNE: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            unsigned int channel = (unsigned int)data.readInt32();
+            unsigned int subChannel = (unsigned int)data.readInt32();
+            status_t status = tune(channel, subChannel);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case CANCEL: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            status_t status = cancel();
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case GET_PROGRAM_INFORMATION: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            struct radio_program_info info;
+
+            status_t status = radio_metadata_allocate(&info.metadata, 0, 0);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = getProgramInformation(&info);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->write(&info, sizeof(struct radio_program_info));
+                int count = radio_metadata_get_count(info.metadata);
+                if (count > 0) {
+                    size_t size = radio_metadata_get_size(info.metadata);
+                    reply->writeInt32(size);
+                    reply->write(info.metadata, size);
+                } else {
+                    reply->writeInt32(0);
+                }
+            }
+            radio_metadata_deallocate(info.metadata);
+            return NO_ERROR;
+        }
+        case HAS_CONTROL: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            bool control;
+            status_t status = hasControl(&control);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(control ? 1 : 0);
+            }
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/radio/IRadioClient.cpp b/radio/IRadioClient.cpp
new file mode 100644
index 0000000..033ca49
--- /dev/null
+++ b/radio/IRadioClient.cpp
@@ -0,0 +1,75 @@
+/*
+**
+** Copyright 2015, 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 <stdint.h>
+#include <sys/types.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <radio/IRadioClient.h>
+
+namespace android {
+
+enum {
+    ON_EVENT = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpRadioClient: public BpInterface<IRadioClient>
+{
+
+public:
+    BpRadioClient(const sp<IBinder>& impl)
+        : BpInterface<IRadioClient>(impl)
+    {
+    }
+
+    virtual void onEvent(const sp<IMemory>& eventMemory)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadioClient::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(eventMemory));
+        remote()->transact(ON_EVENT,
+                           data,
+                           &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(RadioClient,
+                         "android.hardware.IRadioClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnRadioClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case ON_EVENT: {
+            CHECK_INTERFACE(IRadioClient, data, reply);
+            sp<IMemory> eventMemory = interface_cast<IMemory>(
+                data.readStrongBinder());
+            onEvent(eventMemory);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }   return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/radio/IRadioService.cpp b/radio/IRadioService.cpp
new file mode 100644
index 0000000..8c2b3ef
--- /dev/null
+++ b/radio/IRadioService.cpp
@@ -0,0 +1,181 @@
+/*
+**
+** Copyright 2015, 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.
+*/
+
+#define LOG_TAG "BpRadioService"
+//
+#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <radio/IRadioService.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioClient.h>
+
+namespace android {
+
+enum {
+    LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
+    ATTACH,
+};
+
+#define MAX_ITEMS_PER_LIST 1024
+
+class BpRadioService: public BpInterface<IRadioService>
+{
+public:
+    BpRadioService(const sp<IBinder>& impl)
+        : BpInterface<IRadioService>(impl)
+    {
+    }
+
+    virtual status_t listModules(struct radio_properties *properties,
+                                 uint32_t *numModules)
+    {
+        if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
+            return BAD_VALUE;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
+        unsigned int numModulesReq = (properties == NULL) ? 0 : *numModules;
+        data.writeInt32(numModulesReq);
+        status_t status = remote()->transact(LIST_MODULES, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            *numModules = (unsigned int)reply.readInt32();
+        }
+        ALOGV("listModules() status %d got *numModules %d", status, *numModules);
+        if (status == NO_ERROR) {
+            if (numModulesReq > *numModules) {
+                numModulesReq = *numModules;
+            }
+            if (numModulesReq > 0) {
+                reply.read(properties, numModulesReq * sizeof(struct radio_properties));
+            }
+        }
+        return status;
+    }
+
+    virtual status_t attach(radio_handle_t handle,
+                            const sp<IRadioClient>& client,
+                            const struct radio_band_config *config,
+                            bool withAudio,
+                            sp<IRadio>& radio)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
+        data.writeInt32(handle);
+        data.writeStrongBinder(IInterface::asBinder(client));
+        ALOGV("attach() config %p withAudio %d region %d type %d", config, withAudio, config->region, config->band.type);
+        if (config == NULL) {
+            data.writeInt32(0);
+        } else {
+            data.writeInt32(1);
+            data.write(config, sizeof(struct radio_band_config));
+        }
+        data.writeInt32(withAudio ? 1 : 0);
+        status_t status = remote()->transact(ATTACH, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = reply.readInt32();
+        if (reply.readInt32() != 0) {
+            radio = interface_cast<IRadio>(reply.readStrongBinder());
+        }
+        return status;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(RadioService, "android.hardware.IRadioService");
+
+// ----------------------------------------------------------------------
+
+status_t BnRadioService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case LIST_MODULES: {
+            CHECK_INTERFACE(IRadioService, data, reply);
+            unsigned int numModulesReq = data.readInt32();
+            if (numModulesReq > MAX_ITEMS_PER_LIST) {
+                numModulesReq = MAX_ITEMS_PER_LIST;
+            }
+            unsigned int numModules = numModulesReq;
+            struct radio_properties *properties =
+                    (struct radio_properties *)calloc(numModulesReq,
+                                                      sizeof(struct radio_properties));
+            if (properties == NULL) {
+                reply->writeInt32(NO_MEMORY);
+                reply->writeInt32(0);
+                return NO_ERROR;
+            }
+
+            status_t status = listModules(properties, &numModules);
+            reply->writeInt32(status);
+            reply->writeInt32(numModules);
+            ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
+
+            if (status == NO_ERROR) {
+                if (numModulesReq > numModules) {
+                    numModulesReq = numModules;
+                }
+                reply->write(properties,
+                             numModulesReq * sizeof(struct radio_properties));
+            }
+            free(properties);
+            return NO_ERROR;
+        } break;
+
+        case ATTACH: {
+            CHECK_INTERFACE(IRadioService, data, reply);
+            radio_handle_t handle = data.readInt32();
+            sp<IRadioClient> client =
+                    interface_cast<IRadioClient>(data.readStrongBinder());
+            struct radio_band_config config;
+            struct radio_band_config *configPtr = NULL;
+            if (data.readInt32() != 0) {
+                data.read(&config, sizeof(struct radio_band_config));
+                configPtr = &config;
+            }
+            bool withAudio = data.readInt32() != 0;
+            ALOGV("ATTACH configPtr %p withAudio %d", configPtr, withAudio);
+            sp<IRadio> radio;
+            status_t status = attach(handle, client, configPtr, withAudio, radio);
+            reply->writeInt32(status);
+            if (radio != 0) {
+                reply->writeInt32(1);
+                reply->writeStrongBinder(IInterface::asBinder(radio));
+            } else {
+                reply->writeInt32(0);
+            }
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/radio/Radio.cpp b/radio/Radio.cpp
new file mode 100644
index 0000000..e3554c2
--- /dev/null
+++ b/radio/Radio.cpp
@@ -0,0 +1,283 @@
+/*
+**
+** Copyright (C) 2015, 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.
+*/
+
+#define LOG_TAG "Radio"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IMemory.h>
+
+#include <radio/Radio.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioService.h>
+#include <radio/IRadioClient.h>
+#include <radio/RadioCallback.h>
+
+namespace android {
+
+namespace {
+    sp<IRadioService>          gRadioService;
+    const int                  kRadioServicePollDelay = 500000; // 0.5s
+    const char*                kRadioServiceName      = "media.radio";
+    Mutex                      gLock;
+
+    class DeathNotifier : public IBinder::DeathRecipient
+    {
+    public:
+        DeathNotifier() {
+        }
+
+        virtual void binderDied(const wp<IBinder>& who __unused) {
+            ALOGV("binderDied");
+            Mutex::Autolock _l(gLock);
+            gRadioService.clear();
+            ALOGW("Radio service died!");
+        }
+    };
+
+    sp<DeathNotifier>         gDeathNotifier;
+}; // namespace anonymous
+
+const sp<IRadioService>& Radio::getRadioService()
+{
+    Mutex::Autolock _l(gLock);
+    if (gRadioService.get() == 0) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16(kRadioServiceName));
+            if (binder != 0) {
+                break;
+            }
+            ALOGW("RadioService not published, waiting...");
+            usleep(kRadioServicePollDelay);
+        } while(true);
+        if (gDeathNotifier == NULL) {
+            gDeathNotifier = new DeathNotifier();
+        }
+        binder->linkToDeath(gDeathNotifier);
+        gRadioService = interface_cast<IRadioService>(binder);
+    }
+    ALOGE_IF(gRadioService == 0, "no RadioService!?");
+    return gRadioService;
+}
+
+// Static methods
+status_t Radio::listModules(struct radio_properties *properties,
+                            uint32_t *numModules)
+{
+    ALOGV("listModules()");
+    const sp<IRadioService>& service = getRadioService();
+    if (service == 0) {
+        return NO_INIT;
+    }
+    return service->listModules(properties, numModules);
+}
+
+sp<Radio> Radio::attach(radio_handle_t handle,
+                        const struct radio_band_config *config,
+                        bool withAudio,
+                        const sp<RadioCallback>& callback)
+{
+    ALOGV("attach()");
+    sp<Radio> radio;
+    const sp<IRadioService>& service = getRadioService();
+    if (service == 0) {
+        return radio;
+    }
+    radio = new Radio(handle, callback);
+    status_t status = service->attach(handle, radio, config, withAudio, radio->mIRadio);
+
+    if (status == NO_ERROR && radio->mIRadio != 0) {
+        IInterface::asBinder(radio->mIRadio)->linkToDeath(radio);
+    } else {
+        ALOGW("Error %d connecting to radio service", status);
+        radio.clear();
+    }
+    return radio;
+}
+
+
+
+// Radio
+Radio::Radio(radio_handle_t handle, const sp<RadioCallback>& callback)
+    : mHandle(handle), mCallback(callback)
+{
+}
+
+Radio::~Radio()
+{
+    if (mIRadio != 0) {
+        mIRadio->detach();
+    }
+}
+
+
+void Radio::detach() {
+    ALOGV("detach()");
+    Mutex::Autolock _l(mLock);
+    mCallback.clear();
+    if (mIRadio != 0) {
+        mIRadio->detach();
+        IInterface::asBinder(mIRadio)->unlinkToDeath(this);
+        mIRadio = 0;
+    }
+}
+
+status_t Radio::setConfiguration(const struct radio_band_config *config)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->setConfiguration(config);
+}
+
+status_t Radio::getConfiguration(struct radio_band_config *config)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->getConfiguration(config);
+}
+
+status_t Radio::setMute(bool mute)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->setMute(mute);
+}
+
+status_t Radio::getMute(bool *mute)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->getMute(mute);
+}
+
+status_t Radio::scan(radio_direction_t direction, bool skipSubchannel)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->scan(direction, skipSubchannel);
+}
+
+status_t Radio::step(radio_direction_t direction, bool skipSubchannel)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->step(direction, skipSubchannel);
+}
+
+status_t Radio::tune(unsigned int channel, unsigned int subChannel)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->tune(channel, subChannel);
+}
+
+status_t Radio::cancel()
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->cancel();
+}
+
+status_t Radio::getProgramInformation(struct radio_program_info *info)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->getProgramInformation(info);
+}
+
+status_t Radio::hasControl(bool *hasControl)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->hasControl(hasControl);
+}
+
+
+// BpRadioClient
+void Radio::onEvent(const sp<IMemory>& eventMemory)
+{
+    Mutex::Autolock _l(mLock);
+    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+        return;
+    }
+
+    struct radio_event *event = (struct radio_event *)eventMemory->pointer();
+    // restore local metadata pointer from offset
+    switch (event->type) {
+    case RADIO_EVENT_TUNED:
+    case RADIO_EVENT_AF_SWITCH:
+        if (event->info.metadata != NULL) {
+            event->info.metadata =
+                    (radio_metadata_t *)((char *)event + (size_t)event->info.metadata);
+        }
+        break;
+    case RADIO_EVENT_METADATA:
+        if (event->metadata != NULL) {
+            event->metadata =
+                    (radio_metadata_t *)((char *)event + (size_t)event->metadata);
+        }
+        break;
+    default:
+        break;
+    }
+
+    if (mCallback != 0) {
+        mCallback->onEvent(event);
+    }
+}
+
+
+//IBinder::DeathRecipient
+void Radio::binderDied(const wp<IBinder>& who __unused) {
+    Mutex::Autolock _l(mLock);
+    ALOGW("Radio server binder Died ");
+    mIRadio = 0;
+    struct radio_event event;
+    memset(&event, 0, sizeof(struct radio_event));
+    event.type = RADIO_EVENT_SERVER_DIED;
+    event.status = DEAD_OBJECT;
+    if (mCallback != 0) {
+        mCallback->onEvent(&event);
+    }
+}
+
+}; // namespace android
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index e070f90..f1cf0aa 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -415,6 +415,7 @@
             memset(mMixerBuffer, 0, mMixerBufferSize);
             mMixerBufferState = ZEROED;
         }
+        // prepare the buffer used to write to sink
         void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer;
         if (mFormat.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format
             memcpy_by_audio_format(buffer, mFormat.mFormat, mMixerBuffer, mMixerBufferFormat,
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 9350e48..d600ea9 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -427,7 +427,7 @@
                 bool                    mStandby;     // Whether thread is currently in standby.
                 audio_devices_t         mOutDevice;   // output device
                 audio_devices_t         mInDevice;    // input device
-                audio_source_t          mAudioSource; // (see audio.h, audio_source_t)
+                audio_source_t          mAudioSource;
 
                 const audio_io_handle_t mId;
                 Vector< sp<EffectChain> > mEffectChains;
diff --git a/services/audiopolicy/managerdefault/ConfigParsingUtils.h b/services/audiopolicy/managerdefault/ConfigParsingUtils.h
index 7969661..b2d9763 100644
--- a/services/audiopolicy/managerdefault/ConfigParsingUtils.h
+++ b/services/audiopolicy/managerdefault/ConfigParsingUtils.h
@@ -26,7 +26,9 @@
 };
 
 #define STRING_TO_ENUM(string) { #string, string }
+#ifndef ARRAY_SIZE
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
 
 const StringToEnum sDeviceNameToEnumTable[] = {
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
diff --git a/services/audiopolicy/managerdefault/Devices.h b/services/audiopolicy/managerdefault/Devices.h
index 65e1416..af2fbda 100644
--- a/services/audiopolicy/managerdefault/Devices.h
+++ b/services/audiopolicy/managerdefault/Devices.h
@@ -41,7 +41,6 @@
 
     audio_devices_t mDeviceType;
     String8 mAddress;
-    audio_port_handle_t mId;
 
     static String8  emptyNameStr;
 };
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index ea5dcdd..a5a2fec 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -27,6 +27,7 @@
 
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <gui/BufferItem.h>
 #include <gui/Surface.h>
 #include <media/hardware/MetadataBufferType.h>
 
@@ -679,7 +680,7 @@
     sp<Camera2Client> client = mClient.promote();
     if (client == 0) {
         // Discard frames during shutdown
-        BufferItemConsumer::BufferItem imgBuffer;
+        BufferItem imgBuffer;
         res = mRecordingConsumer->acquireBuffer(&imgBuffer, 0);
         if (res != OK) {
             if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
@@ -697,7 +698,7 @@
             with Camera2Client code calling into StreamingProcessor */
         SharedParameters::Lock l(client->getParameters());
         Mutex::Autolock m(mMutex);
-        BufferItemConsumer::BufferItem imgBuffer;
+        BufferItem imgBuffer;
         res = mRecordingConsumer->acquireBuffer(&imgBuffer, 0);
         if (res != OK) {
             if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
@@ -823,8 +824,7 @@
 
     size_t itemIndex;
     for (itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) {
-        const BufferItemConsumer::BufferItem item =
-                mRecordingBuffers[itemIndex];
+        const BufferItem item = mRecordingBuffers[itemIndex];
         if (item.mBuf != BufferItemConsumer::INVALID_BUFFER_SLOT &&
                 item.mGraphicBuffer->handle == imgHandle) {
             break;
@@ -868,8 +868,7 @@
 
     size_t releasedCount = 0;
     for (size_t itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) {
-        const BufferItemConsumer::BufferItem item =
-                mRecordingBuffers[itemIndex];
+        const BufferItem item = mRecordingBuffers[itemIndex];
         if (item.mBuf != BufferItemConsumer::INVALID_BUFFER_SLOT) {
             res = mRecordingConsumer->releaseBuffer(mRecordingBuffers[itemIndex]);
             if (res != OK) {
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.h b/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
index 1d679a4..2474062 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
@@ -124,7 +124,7 @@
 
     static const size_t kDefaultRecordingHeapCount = 8;
     size_t mRecordingHeapCount;
-    Vector<BufferItemConsumer::BufferItem> mRecordingBuffers;
+    Vector<BufferItem> mRecordingBuffers;
     size_t mRecordingHeapHead, mRecordingHeapFree;
 
     virtual bool threadLoop();
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index db7e10d..68aca2d 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -440,7 +440,7 @@
         zslConsumer = mZslConsumer;
     }
     ALOGVV("Trying to get next buffer");
-    BufferItemConsumer::BufferItem item;
+    BufferItem item;
     res = zslConsumer->acquireBuffer(&item, 0);
     if (res != OK) {
         if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.h b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
index 2099c38..5f50d7b 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
@@ -22,6 +22,7 @@
 #include <utils/Vector.h>
 #include <utils/Mutex.h>
 #include <utils/Condition.h>
+#include <gui/BufferItem.h>
 #include <gui/BufferItemConsumer.h>
 #include <camera/CameraMetadata.h>
 #include <camera/CaptureResult.h>
@@ -103,7 +104,7 @@
     sp<ANativeWindow>      mZslWindow;
 
     struct ZslPair {
-        BufferItemConsumer::BufferItem buffer;
+        BufferItem buffer;
         CameraMetadata frame;
     };
 
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.h b/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
index fc9f70c..2960478 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
@@ -22,6 +22,7 @@
 #include <utils/Vector.h>
 #include <utils/Mutex.h>
 #include <utils/Condition.h>
+#include <gui/BufferItem.h>
 #include <gui/BufferItemConsumer.h>
 #include <camera/CameraMetadata.h>
 
@@ -104,7 +105,7 @@
     sp<camera3::Camera3ZslStream> mZslStream;
 
     struct ZslPair {
-        BufferItemConsumer::BufferItem buffer;
+        BufferItem buffer;
         CameraMetadata frame;
     };
 
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 85ed88d..87907bf 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -18,6 +18,7 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <gui/BufferItem.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
 #include "Camera3InputStream.h"
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index ae49467..fd17f4f 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -48,8 +48,6 @@
 
   private:
 
-    typedef BufferItemConsumer::BufferItem BufferItem;
-
     sp<BufferItemConsumer> mConsumer;
     Vector<BufferItem> mBuffersInFlight;
 
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
index d0f29de..8cd6800 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
@@ -268,7 +268,7 @@
     return OK;
 }
 
-void RingBufferConsumer::onFrameAvailable(const android::BufferItem& item) {
+void RingBufferConsumer::onFrameAvailable(const BufferItem& item) {
     status_t err;
 
     {
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h
index 90fd734..83e7298 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.h
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_GUI_RINGBUFFERCONSUMER_H
 #define ANDROID_GUI_RINGBUFFERCONSUMER_H
 
+#include <gui/BufferItem.h>
 #include <gui/ConsumerBase.h>
 
 #include <ui/GraphicBuffer.h>
@@ -54,8 +55,6 @@
   public:
     typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
 
-    typedef BufferQueue::BufferItem BufferItem;
-
     enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
     enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
 
@@ -165,7 +164,7 @@
   private:
 
     // Override ConsumerBase::onFrameAvailable
-    virtual void onFrameAvailable(const android::BufferItem& item);
+    virtual void onFrameAvailable(const BufferItem& item);
 
     void pinBufferLocked(const BufferItem& item);
     void unpinBuffer(const BufferItem& item);
diff --git a/services/radio/Android.mk b/services/radio/Android.mk
new file mode 100644
index 0000000..5e89b22
--- /dev/null
+++ b/services/radio/Android.mk
@@ -0,0 +1,35 @@
+# Copyright 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+
+LOCAL_SRC_FILES:=               \
+    RadioService.cpp
+
+LOCAL_SHARED_LIBRARIES:= \
+    libui \
+    liblog \
+    libutils \
+    libbinder \
+    libcutils \
+    libhardware \
+    libradio \
+    libradio_metadata
+
+LOCAL_MODULE:= libradioservice
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/radio/RadioRegions.h b/services/radio/RadioRegions.h
new file mode 100644
index 0000000..3335b8a
--- /dev/null
+++ b/services/radio/RadioRegions.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_HARDWARE_RADIO_REGIONS_H
+#define ANDROID_HARDWARE_RADIO_REGIONS_H
+
+namespace android {
+
+#define RADIO_BAND_LOWER_FM_ITU1    87500
+#define RADIO_BAND_UPPER_FM_ITU1    108000
+#define RADIO_BAND_SPACING_FM_ITU1  100
+
+#define RADIO_BAND_LOWER_FM_ITU2    87900
+#define RADIO_BAND_UPPER_FM_ITU2    107900
+#define RADIO_BAND_SPACING_FM_ITU2  200
+
+#define RADIO_BAND_LOWER_FM_JAPAN    76000
+#define RADIO_BAND_UPPER_FM_JAPAN    90000
+#define RADIO_BAND_SPACING_FM_JAPAN  100
+
+#define RADIO_BAND_LOWER_FM_OIRT    65800
+#define RADIO_BAND_UPPER_FM_OIRT    74000
+#define RADIO_BAND_SPACING_FM_OIRT  10
+
+#define RADIO_BAND_LOWER_LW         153
+#define RADIO_BAND_UPPER_LW         279
+#define RADIO_BAND_SPACING_LW       9
+
+#define RADIO_BAND_LOWER_MW_IUT1    531
+#define RADIO_BAND_UPPER_MW_ITU1    1611
+#define RADIO_BAND_SPACING_MW_ITU1  9
+
+#define RADIO_BAND_LOWER_MW_IUT2    540
+#define RADIO_BAND_UPPER_MW_ITU2    1610
+#define RADIO_BAND_SPACING_MW_ITU2  10
+
+#define RADIO_BAND_LOWER_SW         2300
+#define RADIO_BAND_UPPER_SW         26100
+#define RADIO_BAND_SPACING_SW       5
+
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+const radio_band_config_t sKnownRegionConfigs[] = {
+    {   // FM ITU 1
+        RADIO_REGION_ITU_1,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_ITU1,
+            RADIO_BAND_UPPER_FM_ITU1,
+            1,
+            {RADIO_BAND_SPACING_FM_ITU1},
+            {
+            RADIO_DEEMPHASIS_50,
+            true,
+            RADIO_RDS_WORLD,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM Americas
+        RADIO_REGION_ITU_2,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_ITU2,
+            RADIO_BAND_UPPER_FM_ITU2,
+            1,
+            {RADIO_BAND_SPACING_FM_ITU2},
+            {
+            RADIO_DEEMPHASIS_75,
+            true,
+            RADIO_RDS_US,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM Japan
+        RADIO_REGION_JAPAN,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_JAPAN,
+            RADIO_BAND_UPPER_FM_JAPAN,
+            1,
+            {RADIO_BAND_SPACING_FM_JAPAN},
+            {
+            RADIO_DEEMPHASIS_50,
+            true,
+            RADIO_RDS_WORLD,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM Korea
+        RADIO_REGION_KOREA,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_ITU1,
+            RADIO_BAND_UPPER_FM_ITU1,
+            1,
+            {RADIO_BAND_SPACING_FM_ITU1},
+            {
+            RADIO_DEEMPHASIS_75,
+            true,
+            RADIO_RDS_WORLD,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM OIRT
+        RADIO_REGION_OIRT,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_OIRT,
+            RADIO_BAND_UPPER_FM_OIRT,
+            1,
+            {RADIO_BAND_SPACING_FM_OIRT},
+            {
+            RADIO_DEEMPHASIS_50,
+            true,
+            RADIO_RDS_WORLD,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM US HD radio
+        RADIO_REGION_ITU_2,
+        {
+            RADIO_BAND_FM_HD,
+            false,
+            RADIO_BAND_LOWER_FM_ITU2,
+            RADIO_BAND_UPPER_FM_ITU2,
+            1,
+            {RADIO_BAND_SPACING_FM_ITU2},
+            {
+            RADIO_DEEMPHASIS_75,
+            true,
+            RADIO_RDS_US,
+            true,
+            true,
+            }
+        }
+    },
+    {   // AM LW
+        RADIO_REGION_ITU_1,
+        {
+            RADIO_BAND_AM,
+            false,
+            RADIO_BAND_LOWER_LW,
+            RADIO_BAND_UPPER_LW,
+            1,
+            {RADIO_BAND_SPACING_LW},
+            {
+            }
+        }
+    },
+    {   // AM SW
+        RADIO_REGION_ITU_1,
+        {
+            RADIO_BAND_AM,
+            false,
+            RADIO_BAND_LOWER_SW,
+            RADIO_BAND_UPPER_SW,
+            1,
+            {RADIO_BAND_SPACING_SW},
+            {
+            }
+        }
+    },
+    {   // AM MW ITU1
+        RADIO_REGION_ITU_1,
+        {
+            RADIO_BAND_AM,
+            false,
+            RADIO_BAND_LOWER_MW_IUT1,
+            RADIO_BAND_UPPER_MW_ITU1,
+            1,
+            {RADIO_BAND_SPACING_MW_ITU1},
+            {
+            }
+        }
+    },
+    {   // AM MW ITU2
+        RADIO_REGION_ITU_2,
+        {
+            RADIO_BAND_AM,
+            false,
+            RADIO_BAND_LOWER_MW_IUT2,
+            RADIO_BAND_UPPER_MW_ITU2,
+            1,
+            {RADIO_BAND_SPACING_MW_ITU2},
+            {
+            }
+        }
+    }
+};
+
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_RADIO_REGIONS_H
diff --git a/services/radio/RadioService.cpp b/services/radio/RadioService.cpp
new file mode 100644
index 0000000..152619b
--- /dev/null
+++ b/services/radio/RadioService.cpp
@@ -0,0 +1,845 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "RadioService"
+//#define LOG_NDEBUG 0
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <system/radio.h>
+#include <system/radio_metadata.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <hardware/hardware.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <hardware/radio.h>
+#include "RadioService.h"
+#include "RadioRegions.h"
+
+namespace android {
+
+
+RadioService::RadioService()
+    : BnRadioService(), mNextUniqueId(1)
+{
+    ALOGI("%s", __FUNCTION__);
+}
+
+void RadioService::onFirstRef()
+{
+    const hw_module_t *mod;
+    int rc;
+    struct radio_hw_device *dev;
+
+    ALOGI("%s", __FUNCTION__);
+
+    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, RADIO_HARDWARE_MODULE_ID_FM, &mod);
+    if (rc != 0) {
+        ALOGE("couldn't load radio module %s.%s (%s)",
+              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
+        return;
+    }
+    rc = radio_hw_device_open(mod, &dev);
+    if (rc != 0) {
+        ALOGE("couldn't open radio hw device in %s.%s (%s)",
+              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
+        return;
+    }
+    if (dev->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
+        ALOGE("wrong radio hw device version %04x", dev->common.version);
+        return;
+    }
+
+    struct radio_hal_properties halProperties;
+    rc = dev->get_properties(dev, &halProperties);
+    if (rc != 0) {
+        ALOGE("could not read implementation properties");
+        return;
+    }
+
+    radio_properties_t properties;
+    properties.handle =
+            (radio_handle_t)android_atomic_inc(&mNextUniqueId);
+
+    ALOGI("loaded default module %s, handle %d", properties.product, properties.handle);
+
+    convertProperties(&properties, &halProperties);
+    sp<Module> module = new Module(this, dev, properties);
+    mModules.add(properties.handle, module);
+}
+
+RadioService::~RadioService()
+{
+    for (size_t i = 0; i < mModules.size(); i++) {
+        radio_hw_device_close(mModules.valueAt(i)->hwDevice());
+    }
+}
+
+status_t RadioService::listModules(struct radio_properties *properties,
+                             uint32_t *numModules)
+{
+    ALOGV("listModules");
+
+    AutoMutex lock(mServiceLock);
+    if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
+        return BAD_VALUE;
+    }
+    size_t maxModules = *numModules;
+    *numModules = mModules.size();
+    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
+        properties[i] = mModules.valueAt(i)->properties();
+    }
+    return NO_ERROR;
+}
+
+status_t RadioService::attach(radio_handle_t handle,
+                        const sp<IRadioClient>& client,
+                        const struct radio_band_config *config,
+                        bool withAudio,
+                        sp<IRadio>& radio)
+{
+    ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);
+
+    AutoMutex lock(mServiceLock);
+    radio.clear();
+    if (client == 0) {
+        return BAD_VALUE;
+    }
+    ssize_t index = mModules.indexOfKey(handle);
+    if (index < 0) {
+        return BAD_VALUE;
+    }
+    sp<Module> module = mModules.valueAt(index);
+
+    if (config == NULL) {
+        config = module->getDefaultConfig();
+        if (config == NULL) {
+            return INVALID_OPERATION;
+        }
+    }
+    ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);
+
+    radio = module->addClient(client, config, withAudio);
+
+    if (radio == 0) {
+        NO_INIT;
+    }
+    return NO_ERROR;
+}
+
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 60000;
+
+static bool tryLock(Mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
+status_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
+    String8 result;
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        result.appendFormat("Permission Denial: can't dump RadioService");
+        write(fd, result.string(), result.size());
+    } else {
+        bool locked = tryLock(mServiceLock);
+        // failed to lock - RadioService is probably deadlocked
+        if (!locked) {
+            result.append("RadioService may be deadlocked\n");
+            write(fd, result.string(), result.size());
+        }
+
+        if (locked) mServiceLock.unlock();
+    }
+    return NO_ERROR;
+}
+
+status_t RadioService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    return BnRadioService::onTransact(code, data, reply, flags);
+}
+
+
+// static
+void RadioService::callback(radio_hal_event_t *halEvent, void *cookie)
+{
+    CallbackThread *callbackThread = (CallbackThread *)cookie;
+    if (callbackThread == NULL) {
+        return;
+    }
+    callbackThread->sendEvent(halEvent);
+}
+
+/* static */
+void RadioService::convertProperties(radio_properties_t *properties,
+                                     const radio_hal_properties_t *halProperties)
+{
+    memset(properties, 0, sizeof(struct radio_properties));
+    properties->class_id = halProperties->class_id;
+    strlcpy(properties->implementor, halProperties->implementor,
+            RADIO_STRING_LEN_MAX);
+    strlcpy(properties->product, halProperties->product,
+            RADIO_STRING_LEN_MAX);
+    strlcpy(properties->version, halProperties->version,
+            RADIO_STRING_LEN_MAX);
+    strlcpy(properties->serial, halProperties->serial,
+            RADIO_STRING_LEN_MAX);
+    properties->num_tuners = halProperties->num_tuners;
+    properties->num_audio_sources = halProperties->num_audio_sources;
+    properties->supports_capture = halProperties->supports_capture;
+
+    for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
+        const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
+        size_t j;
+        for (j = 0; j < halProperties->num_bands; j++) {
+            const radio_hal_band_config_t *halBand = &halProperties->bands[j];
+            size_t k;
+            if (band->type != halBand->type) continue;
+            if (band->lower_limit < halBand->lower_limit) continue;
+            if (band->upper_limit > halBand->upper_limit) continue;
+            for (k = 0; k < halBand->num_spacings; k++) {
+                if (band->spacings[0] == halBand->spacings[k]) break;
+            }
+            if (k == halBand->num_spacings) continue;
+            if (band->type == RADIO_BAND_AM) break;
+            if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
+            if (halBand->fm.rds == 0) break;
+            if ((band->fm.rds & halBand->fm.rds) != 0) break;
+        }
+        if (j == halProperties->num_bands) continue;
+
+        ALOGI("convertProperties() Adding band type %d region %d",
+              sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);
+
+        memcpy(&properties->bands[properties->num_bands++],
+               &sKnownRegionConfigs[i],
+               sizeof(radio_band_config_t));
+    }
+}
+
+#undef LOG_TAG
+#define LOG_TAG "RadioService::CallbackThread"
+
+RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
+    : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
+{
+}
+
+RadioService::CallbackThread::~CallbackThread()
+{
+    mEventQueue.clear();
+}
+
+void RadioService::CallbackThread::onFirstRef()
+{
+    run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
+}
+
+bool RadioService::CallbackThread::threadLoop()
+{
+    while (!exitPending()) {
+        sp<IMemory> eventMemory;
+        sp<ModuleClient> moduleClient;
+        {
+            Mutex::Autolock _l(mCallbackLock);
+            while (mEventQueue.isEmpty() && !exitPending()) {
+                ALOGV("CallbackThread::threadLoop() sleep");
+                mCallbackCond.wait(mCallbackLock);
+                ALOGV("CallbackThread::threadLoop() wake up");
+            }
+            if (exitPending()) {
+                break;
+            }
+            eventMemory = mEventQueue[0];
+            mEventQueue.removeAt(0);
+            moduleClient = mModuleClient.promote();
+        }
+        if (moduleClient != 0) {
+            moduleClient->onCallbackEvent(eventMemory);
+            eventMemory.clear();
+        }
+    }
+    return false;
+}
+
+void RadioService::CallbackThread::exit()
+{
+    Mutex::Autolock _l(mCallbackLock);
+    requestExit();
+    mCallbackCond.broadcast();
+}
+
+sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
+{
+    sp<IMemory> eventMemory;
+
+    size_t headerSize =
+            (sizeof(struct radio_event) + sizeof(unsigned int) - 1) /sizeof(unsigned int);
+    size_t metadataSize = 0;
+    switch (halEvent->type) {
+    case RADIO_EVENT_TUNED:
+    case RADIO_EVENT_AF_SWITCH:
+        if (radio_metadata_check(halEvent->info.metadata) == 0) {
+            metadataSize = radio_metadata_get_size(halEvent->info.metadata);
+        }
+        break;
+    case RADIO_EVENT_METADATA:
+        if (radio_metadata_check(halEvent->metadata) != 0) {
+            return eventMemory;
+        }
+        metadataSize = radio_metadata_get_size(halEvent->metadata);
+        break;
+    default:
+        break;
+    }
+    size_t size = headerSize + metadataSize;
+    eventMemory = mMemoryDealer->allocate(size);
+    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+        eventMemory.clear();
+        return eventMemory;
+    }
+    struct radio_event *event = (struct radio_event *)eventMemory->pointer();
+    event->type = halEvent->type;
+    event->status = halEvent->status;
+
+    switch (event->type) {
+    case RADIO_EVENT_CONFIG:
+        event->config.band = halEvent->config;
+        break;
+    case RADIO_EVENT_TUNED:
+    case RADIO_EVENT_AF_SWITCH:
+        event->info = halEvent->info;
+        if (metadataSize != 0) {
+            memcpy((char *)event + headerSize, halEvent->info.metadata, metadataSize);
+            // replace meta data pointer by offset while in shared memory so that receiving side
+            // can restore the pointer in destination process.
+            event->info.metadata = (radio_metadata_t *)headerSize;
+        }
+        break;
+    case RADIO_EVENT_TA:
+    case RADIO_EVENT_ANTENNA:
+    case RADIO_EVENT_CONTROL:
+        event->on = halEvent->on;
+        break;
+    case RADIO_EVENT_METADATA:
+        memcpy((char *)event + headerSize, halEvent->metadata, metadataSize);
+        // replace meta data pointer by offset while in shared memory so that receiving side
+        // can restore the pointer in destination process.
+        event->metadata = (radio_metadata_t *)headerSize;
+        break;
+    case RADIO_EVENT_HW_FAILURE:
+    default:
+        break;
+    }
+
+    return eventMemory;
+}
+
+void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
+ {
+     sp<IMemory> eventMemory = prepareEvent(event);
+     if (eventMemory == 0) {
+         return;
+     }
+
+     AutoMutex lock(mCallbackLock);
+     mEventQueue.add(eventMemory);
+     mCallbackCond.signal();
+     ALOGV("%s DONE", __FUNCTION__);
+}
+
+
+#undef LOG_TAG
+#define LOG_TAG "RadioService::Module"
+
+RadioService::Module::Module(const sp<RadioService>& service,
+                                      radio_hw_device* hwDevice,
+                                      radio_properties properties)
+ : mService(service), mHwDevice(hwDevice), mProperties(properties), mMute(true)
+{
+}
+
+RadioService::Module::~Module() {
+    mModuleClients.clear();
+}
+
+status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
+    String8 result;
+    return NO_ERROR;
+}
+
+sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
+                                    const struct radio_band_config *config,
+                                    bool audio)
+{
+    ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
+    AutoMutex lock(mLock);
+    sp<ModuleClient> moduleClient;
+    int ret;
+
+    for (size_t i = 0; i < mModuleClients.size(); i++) {
+        if (mModuleClients[i]->client() == client) {
+            // client already connected: reject
+            return moduleClient;
+        }
+    }
+    moduleClient = new ModuleClient(this, client, config, audio);
+
+    struct radio_hal_band_config halConfig;
+    halConfig = config->band;
+
+    sp<ModuleClient> oldestTuner;
+    sp<ModuleClient> oldestAudio;
+    size_t allocatedTuners = 0;
+    size_t allocatedAudio = 0;
+    for (size_t i = 0; i < mModuleClients.size(); i++) {
+        if (mModuleClients[i]->getTuner() != NULL) {
+            if (mModuleClients[i]->audio()) {
+                if (oldestAudio == 0) {
+                    oldestAudio = mModuleClients[i];
+                }
+                allocatedAudio++;
+            } else {
+                if (oldestTuner == 0) {
+                    oldestTuner = mModuleClients[i];
+                }
+                allocatedTuners++;
+            }
+        }
+    }
+
+    const struct radio_tuner *halTuner;
+    if (audio) {
+        if (allocatedAudio >= mProperties.num_audio_sources) {
+            ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
+            halTuner = oldestAudio->getTuner();
+            oldestAudio->setTuner(NULL);
+            mHwDevice->close_tuner(mHwDevice, halTuner);
+        }
+    } else {
+        if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
+            if (allocatedTuners != 0) {
+                ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
+                halTuner = oldestTuner->getTuner();
+                oldestTuner->setTuner(NULL);
+                mHwDevice->close_tuner(mHwDevice, halTuner);
+            } else {
+                ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
+                halTuner = oldestAudio->getTuner();
+                oldestAudio->setTuner(NULL);
+                mHwDevice->close_tuner(mHwDevice, halTuner);
+            }
+        }
+    }
+
+    ret = mHwDevice->open_tuner(mHwDevice, &halConfig, audio,
+                                RadioService::callback, moduleClient->callbackThread().get(),
+                                &halTuner);
+    if (ret == 0) {
+        ALOGV("addClient() setTuner %p", halTuner);
+        moduleClient->setTuner(halTuner);
+        mModuleClients.add(moduleClient);
+    } else {
+        moduleClient.clear();
+    }
+
+    //TODO notify audio device connection to audio policy manager if audio is on
+
+    ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
+
+    return moduleClient;
+}
+
+void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
+    ALOGV("removeClient()");
+    AutoMutex lock(mLock);
+    int ret;
+    ssize_t index = -1;
+
+    for (size_t i = 0; i < mModuleClients.size(); i++) {
+        if (mModuleClients[i] == moduleClient) {
+            index = i;
+            break;
+        }
+    }
+    if (index == -1) {
+        return;
+    }
+
+    mModuleClients.removeAt(index);
+    const struct radio_tuner *halTuner = moduleClient->getTuner();
+    if (halTuner == NULL) {
+        return;
+    }
+
+    mHwDevice->close_tuner(mHwDevice, halTuner);
+
+    //TODO notify audio device disconnection to audio policy manager if audio was on
+    mMute = true;
+
+    if (mModuleClients.isEmpty()) {
+        return;
+    }
+
+    sp<ModuleClient> youngestClient;
+    sp<ModuleClient> youngestClientAudio;
+    size_t allocatedTuners = 0;
+    size_t allocatedAudio = 0;
+    for (ssize_t i = mModuleClients.size(); i >= 0; i--) {
+        if (mModuleClients[i]->getTuner() == NULL) {
+            if (mModuleClients[i]->audio()) {
+                if (youngestClientAudio == 0) {
+                    youngestClientAudio = mModuleClients[i];
+                }
+            } else {
+                if (youngestClient == 0) {
+                    youngestClient = mModuleClients[i];
+                }
+            }
+        } else {
+            if (mModuleClients[i]->audio()) {
+                allocatedAudio++;
+            } else {
+                allocatedTuners++;
+            }
+        }
+    }
+
+    ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
+                "removeClient() removed client but no tuner available");
+
+    ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
+                "removeClient() removed audio client but no tuner with audio available");
+
+    if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
+        youngestClient = youngestClientAudio;
+    }
+
+    ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
+
+    struct radio_hal_band_config halConfig = youngestClient->halConfig();
+    ret = mHwDevice->open_tuner(mHwDevice, &halConfig, youngestClient->audio(),
+                                RadioService::callback, moduleClient->callbackThread().get(),
+                                &halTuner);
+
+    //TODO notify audio device connection to audio policy manager if audio is on
+
+    if (ret == 0) {
+        youngestClient->setTuner(halTuner);
+    }
+}
+
+status_t RadioService::Module::setMute(bool mute)
+{
+    Mutex::Autolock _l(mLock);
+    if (mute != mMute) {
+        mMute = mute;
+        //TODO notifify audio policy manager of media activity on radio audio device
+    }
+    return NO_ERROR;
+}
+
+status_t RadioService::Module::getMute(bool *mute)
+{
+    Mutex::Autolock _l(mLock);
+    *mute = mMute;
+    return NO_ERROR;
+}
+
+
+const struct radio_band_config *RadioService::Module::getDefaultConfig() const
+{
+    if (mProperties.num_bands == 0) {
+        return NULL;
+    }
+    return &mProperties.bands[0];
+}
+
+#undef LOG_TAG
+#define LOG_TAG "RadioService::ModuleClient"
+
+RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
+                                         const sp<IRadioClient>& client,
+                                         const struct radio_band_config *config,
+                                         bool audio)
+ : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(NULL)
+{
+}
+
+void RadioService::ModuleClient::onFirstRef()
+{
+    mCallbackThread = new CallbackThread(this);
+    IInterface::asBinder(mClient)->linkToDeath(this);
+}
+
+RadioService::ModuleClient::~ModuleClient() {
+    if (mClient != 0) {
+        IInterface::asBinder(mClient)->unlinkToDeath(this);
+        mClient.clear();
+    }
+    if (mCallbackThread != 0) {
+        mCallbackThread->exit();
+    }
+}
+
+status_t RadioService::ModuleClient::dump(int fd __unused,
+                                             const Vector<String16>& args __unused) {
+    String8 result;
+    return NO_ERROR;
+}
+
+void RadioService::ModuleClient::detach() {
+    ALOGV("%s", __FUNCTION__);
+    sp<ModuleClient> strongMe = this;
+    {
+        AutoMutex lock(mLock);
+        if (mClient != 0) {
+            IInterface::asBinder(mClient)->unlinkToDeath(this);
+            mClient.clear();
+        }
+    }
+    sp<Module> module = mModule.promote();
+    if (module == 0) {
+        return;
+    }
+    module->removeClient(this);
+}
+
+radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    return mConfig.band;
+}
+
+const struct radio_tuner *RadioService::ModuleClient::getTuner() const
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    return mTuner;
+}
+
+void RadioService::ModuleClient::setTuner(const struct radio_tuner *tuner)
+{
+    ALOGV("%s %p", __FUNCTION__, this);
+
+    AutoMutex lock(mLock);
+    mTuner = tuner;
+    ALOGV("%s locked", __FUNCTION__);
+
+    radio_hal_event_t event;
+    event.type = RADIO_EVENT_CONTROL;
+    event.status = 0;
+    event.on = mTuner != NULL;
+    mCallbackThread->sendEvent(&event);
+    ALOGV("%s DONE", __FUNCTION__);
+
+}
+
+status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
+{
+    AutoMutex lock(mLock);
+    status_t status = NO_ERROR;
+    ALOGV("%s locked", __FUNCTION__);
+
+    if (mTuner != NULL) {
+        struct radio_hal_band_config halConfig;
+        halConfig = config->band;
+        status = (status_t)mTuner->set_configuration(mTuner, &halConfig);
+        if (status == NO_ERROR) {
+            mConfig = *config;
+        }
+    } else {
+        mConfig = *config;
+        status == INVALID_OPERATION;
+    }
+
+    return status;
+}
+
+status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
+{
+    AutoMutex lock(mLock);
+    status_t status = NO_ERROR;
+    ALOGV("%s locked", __FUNCTION__);
+
+    if (mTuner != NULL) {
+        struct radio_hal_band_config halConfig;
+        status = (status_t)mTuner->get_configuration(mTuner, &halConfig);
+        if (status == NO_ERROR) {
+            mConfig.band = halConfig;
+        }
+    }
+    *config = mConfig;
+
+    return status;
+}
+
+status_t RadioService::ModuleClient::setMute(bool mute)
+{
+    sp<Module> module;
+    {
+        Mutex::Autolock _l(mLock);
+        ALOGV("%s locked", __FUNCTION__);
+        if (mTuner == NULL || !mAudio) {
+            return INVALID_OPERATION;
+        }
+        module = mModule.promote();
+        if (module == 0) {
+            return NO_INIT;
+        }
+    }
+    module->setMute(mute);
+    return NO_ERROR;
+}
+
+status_t RadioService::ModuleClient::getMute(bool *mute)
+{
+    sp<Module> module;
+    {
+        Mutex::Autolock _l(mLock);
+        ALOGV("%s locked", __FUNCTION__);
+        module = mModule.promote();
+        if (module == 0) {
+            return NO_INIT;
+        }
+    }
+    return module->getMute(mute);
+}
+
+status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->scan(mTuner, direction, skipSubChannel);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->step(mTuner, direction, skipSubChannel);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::tune(unsigned int channel, unsigned int subChannel)
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->tune(mTuner, channel, subChannel);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::cancel()
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->cancel(mTuner);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->get_program_information(mTuner, info);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::hasControl(bool *hasControl)
+{
+    Mutex::Autolock lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    *hasControl = mTuner != NULL;
+    return NO_ERROR;
+}
+
+void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
+{
+    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+        return;
+    }
+
+    sp<IRadioClient> client;
+    {
+        AutoMutex lock(mLock);
+        ALOGV("%s locked", __FUNCTION__);
+        radio_event_t *event = (radio_event_t *)eventMemory->pointer();
+        switch (event->type) {
+        case RADIO_EVENT_CONFIG:
+            mConfig.band = event->config.band;
+            event->config.region = mConfig.region;
+            break;
+        default:
+            break;
+        }
+
+        client = mClient;
+    }
+    if (client != 0) {
+        client->onEvent(eventMemory);
+    }
+}
+
+
+void RadioService::ModuleClient::binderDied(
+    const wp<IBinder> &who __unused) {
+    ALOGW("client binder died for client %p", this);
+    detach();
+}
+
+}; // namespace android
diff --git a/services/radio/RadioService.h b/services/radio/RadioService.h
new file mode 100644
index 0000000..9ede020
--- /dev/null
+++ b/services/radio/RadioService.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2015 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 ANDROID_HARDWARE_RADIO_SERVICE_H
+#define ANDROID_HARDWARE_RADIO_SERVICE_H
+
+#include <utils/Vector.h>
+//#include <binder/AppOpsManager.h>
+#include <binder/MemoryDealer.h>
+#include <binder/BinderService.h>
+#include <binder/IAppOpsCallback.h>
+#include <radio/IRadioService.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioClient.h>
+#include <system/radio.h>
+#include <hardware/radio.h>
+
+namespace android {
+
+class MemoryHeapBase;
+
+class RadioService :
+    public BinderService<RadioService>,
+    public BnRadioService
+{
+    friend class BinderService<RadioService>;
+
+public:
+    class ModuleClient;
+    class Module;
+
+    static char const* getServiceName() { return "media.radio"; }
+
+                        RadioService();
+    virtual             ~RadioService();
+
+    // IRadioService
+    virtual status_t listModules(struct radio_properties *properties,
+                                 uint32_t *numModules);
+
+    virtual status_t attach(radio_handle_t handle,
+                            const sp<IRadioClient>& client,
+                            const struct radio_band_config *config,
+                            bool withAudio,
+                            sp<IRadio>& radio);
+
+    virtual status_t    onTransact(uint32_t code, const Parcel& data,
+                                   Parcel* reply, uint32_t flags);
+
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+
+
+    class Module : public virtual RefBase {
+    public:
+
+       Module(const sp<RadioService>& service,
+              radio_hw_device* hwDevice,
+              struct radio_properties properties);
+
+       virtual ~Module();
+
+               sp<ModuleClient> addClient(const sp<IRadioClient>& client,
+                                  const struct radio_band_config *config,
+                                  bool audio);
+
+               void removeClient(const sp<ModuleClient>& moduleClient);
+
+               status_t setMute(bool mute);
+
+               status_t getMute(bool *mute);
+
+       virtual status_t dump(int fd, const Vector<String16>& args);
+
+       const struct radio_hw_device *hwDevice() const { return mHwDevice; }
+       const struct radio_properties properties() const { return mProperties; }
+       const struct radio_band_config *getDefaultConfig() const ;
+
+       wp<RadioService> service() const { return mService; }
+
+    private:
+
+        Mutex                         mLock;
+        wp<RadioService>              mService;
+        const struct radio_hw_device        *mHwDevice;
+        const struct radio_properties       mProperties;
+        Vector< sp<ModuleClient> >    mModuleClients;
+        bool                          mMute;
+    }; // class Module
+
+    class CallbackThread : public Thread {
+    public:
+
+        CallbackThread(const wp<ModuleClient>& moduleClient);
+
+        virtual ~CallbackThread();
+
+
+        // Thread virtuals
+        virtual bool threadLoop();
+
+        // RefBase
+        virtual void onFirstRef();
+
+                void exit();
+
+                void sendEvent(radio_hal_event_t *halEvent);
+                sp<IMemory> prepareEvent(radio_hal_event_t *halEvent);
+
+    private:
+        wp<ModuleClient>      mModuleClient;
+        Condition             mCallbackCond;
+        Mutex                 mCallbackLock;
+        Vector< sp<IMemory> > mEventQueue;
+        sp<MemoryDealer>      mMemoryDealer;
+    }; // class CallbackThread
+
+    class ModuleClient : public BnRadio,
+                   public IBinder::DeathRecipient {
+    public:
+
+       ModuleClient(const sp<Module>& module,
+              const sp<IRadioClient>& client,
+              const struct radio_band_config *config,
+              bool audio);
+
+       virtual ~ModuleClient();
+
+       // IRadio
+       virtual void detach();
+
+       virtual status_t setConfiguration(const struct radio_band_config *config);
+
+       virtual status_t getConfiguration(struct radio_band_config *config);
+
+       virtual status_t setMute(bool mute);
+
+       virtual status_t getMute(bool *mute);
+
+       virtual status_t scan(radio_direction_t direction, bool skipSubChannel);
+
+       virtual status_t step(radio_direction_t direction, bool skipSubChannel);
+
+       virtual status_t tune(unsigned int channel, unsigned int subChannel);
+
+       virtual status_t cancel();
+
+       virtual status_t getProgramInformation(struct radio_program_info *info);
+
+       virtual status_t hasControl(bool *hasControl);
+
+       virtual status_t dump(int fd, const Vector<String16>& args);
+
+               sp<IRadioClient> client() const { return mClient; }
+               wp<Module> module() const { return mModule; }
+               radio_hal_band_config_t halConfig() const;
+               sp<CallbackThread> callbackThread() const { return mCallbackThread; }
+               void setTuner(const struct radio_tuner *tuner);
+               const struct radio_tuner *getTuner() const;
+               bool audio() const { return mAudio; }
+
+               void onCallbackEvent(const sp<IMemory>& event);
+
+       virtual void onFirstRef();
+
+
+       // IBinder::DeathRecipient implementation
+       virtual void        binderDied(const wp<IBinder> &who);
+
+    private:
+
+        mutable Mutex               mLock;
+        wp<Module>                  mModule;
+        sp<IRadioClient>            mClient;
+        radio_band_config_t         mConfig;
+        sp<CallbackThread>          mCallbackThread;
+        const bool                  mAudio;
+        const struct radio_tuner    *mTuner;
+    }; // class ModuleClient
+
+
+    static void callback(radio_hal_event_t *halEvent, void *cookie);
+
+private:
+
+    virtual void onFirstRef();
+
+    static void convertProperties(radio_properties_t *properties,
+                                  const radio_hal_properties_t *halProperties);
+    Mutex               mServiceLock;
+    volatile int32_t    mNextUniqueId;
+    DefaultKeyedVector< radio_handle_t, sp<Module> > mModules;
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_RADIO_SERVICE_H