Merge changes from topic "c2-more-adjustments"

* changes:
  Codec2/AUtils: rename nom to num for 'numerator'
  Codec2: C2ParamDescriptor fixes
  Codec2: use std::list only for C2Work/C2Worklet
  Codec2: codec2_vndk is now a shared lib, plus, add internal headers
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 3aebb8a..6b3a8f0 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -1316,6 +1316,14 @@
     }
 }
 
+// -------------------------------------------------------------------------
+
+status_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+{
+    AutoMutex lock(mLock);
+    return mAudioRecord->getActiveMicrophones(activeMicrophones).transactionError();
+}
+
 // =========================================================================
 
 void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
diff --git a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
index 7572671..01e0a71 100644
--- a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.media.MicrophoneInfo;
+
 /* Native code must specify namespace media (media::IAudioRecord) when referring to this class */
 interface IAudioRecord {
 
@@ -30,4 +32,8 @@
    * will be processed, unless flush() is called.
    */
   void stop();
+
+  /* Get a list of current active microphones.
+   */
+  void getActiveMicrophones(out MicrophoneInfo[] activeMicrophones);
 }
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index 893229c..c07c397 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -23,8 +23,10 @@
 #include <media/AudioTimestamp.h>
 #include <media/MediaAnalyticsItem.h>
 #include <media/Modulo.h>
+#include <media/MicrophoneInfo.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
+#include <vector>
 
 #include "android/media/IAudioRecord.h"
 
@@ -527,6 +529,11 @@
     /* Get the flags */
             audio_input_flags_t getFlags() const { AutoMutex _l(mLock); return mFlags; }
 
+    /* Get active microphones. A empty vector of MicrophoneInfo will be passed as a parameter,
+     * the data will be filled when querying the hal.
+     */
+            status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+
     /*
      * Dumps the state of an audio record.
      */
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 72f5f58..b2c91c4 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -64,6 +64,7 @@
     SET_INPUT_DEVICE,
     GET_ROUTED_DEVICE_ID,
     ENABLE_AUDIO_DEVICE_CALLBACK,
+    GET_ACTIVE_MICROPHONES,
 
 };
 
@@ -391,6 +392,21 @@
         }
         return reply.readInt32();
     }
+
+    status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+    {
+        ALOGV("getActiveMicrophones");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_ACTIVE_MICROPHONES, data, &reply);
+        if (status != OK
+                || (status = (status_t)reply.readInt32()) != NO_ERROR) {
+            return status;
+        }
+        status = reply.readParcelableVector(activeMicrophones);
+        return status;
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(MediaRecorder, "android.media.IMediaRecorder");
@@ -631,6 +647,19 @@
                 reply->writeInt32(BAD_VALUE);
             }
             return NO_ERROR;
+        } break;
+        case GET_ACTIVE_MICROPHONES: {
+            ALOGV("GET_ACTIVE_MICROPHONES");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            std::vector<media::MicrophoneInfo> activeMicrophones;
+            status_t status = getActiveMicrophones(&activeMicrophones);
+            reply->writeInt32(status);
+            if (status != NO_ERROR) {
+                return NO_ERROR;
+            }
+            reply->writeParcelableVector(activeMicrophones);
+            return NO_ERROR;
+
         }
         default:
             return BBinder::onTransact(code, data, reply, flags);
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index 3cef329..379000e 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -19,7 +19,9 @@
 #define ANDROID_IMEDIARECORDER_H
 
 #include <binder/IInterface.h>
+#include <media/MicrophoneInfo.h>
 #include <system/audio.h>
+#include <vector>
 
 namespace android {
 
@@ -69,6 +71,9 @@
     virtual status_t setInputDevice(audio_port_handle_t deviceId) = 0;
     virtual status_t getRoutedDeviceId(audio_port_handle_t *deviceId) = 0;
     virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
+    virtual status_t getActiveMicrophones(
+                        std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+
 };
 
 // ----------------------------------------------------------------------------
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index 748153c..5340dde 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -19,10 +19,13 @@
 #define MEDIA_RECORDER_BASE_H_
 
 #include <media/AudioSystem.h>
+#include <media/MicrophoneInfo.h>
 #include <media/mediarecorder.h>
 
 #include <system/audio.h>
 
+#include <vector>
+
 namespace android {
 
 class ICameraRecordingProxy;
@@ -67,6 +70,9 @@
     virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId) = 0;
     virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) = 0;
     virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
+    virtual status_t getActiveMicrophones(
+                        std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+
 
 
 protected:
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index 5f2a6fe..d8b0fe7 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -24,6 +24,7 @@
 #include <utils/Errors.h>
 #include <media/IMediaRecorderClient.h>
 #include <media/IMediaDeathNotifier.h>
+#include <media/MicrophoneInfo.h>
 
 namespace android {
 
@@ -258,6 +259,7 @@
     status_t    setInputDevice(audio_port_handle_t deviceId);
     status_t    getRoutedDeviceId(audio_port_handle_t *deviceId);
     status_t    enableAudioDeviceCallback(bool enabled);
+    status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
 
 private:
     void                    doCleanUp();
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index aab845b..721a043 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -829,4 +829,15 @@
     return mMediaRecorder->enableAudioDeviceCallback(enabled);
 }
 
+status_t MediaRecorder::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+{
+    ALOGV("getActiveMicrophones");
+
+    if (mMediaRecorder == NULL) {
+        ALOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    return mMediaRecorder->getActiveMicrophones(activeMicrophones);
+}
+
 } // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index dcd393b..4206647 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -527,4 +527,14 @@
     }
     return NO_INIT;
 }
+
+status_t MediaRecorderClient::getActiveMicrophones(
+        std::vector<media::MicrophoneInfo>* activeMicrophones) {
+    ALOGV("getActiveMicrophones");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder != NULL) {
+        return mRecorder->getActiveMicrophones(activeMicrophones);
+    }
+    return NO_INIT;
+}
 }; // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 538b461..d2e681f 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -107,6 +107,8 @@
     virtual     status_t   setInputDevice(audio_port_handle_t deviceId);
     virtual     status_t   getRoutedDeviceId(audio_port_handle_t* deviceId);
     virtual     status_t   enableAudioDeviceCallback(bool enabled);
+    virtual     status_t   getActiveMicrophones(
+                              std::vector<media::MicrophoneInfo>* activeMicrophones);
 
 private:
     friend class           MediaPlayerService;  // for accessing private constructor
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 458b871..bc8d8c8 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -2160,6 +2160,15 @@
     return NO_ERROR;
 }
 
+status_t StagefrightRecorder::getActiveMicrophones(
+        std::vector<media::MicrophoneInfo>* activeMicrophones) {
+    if (mAudioSourceNode != 0) {
+        return mAudioSourceNode->getActiveMicrophones(activeMicrophones);
+    }
+    return NO_INIT;
+}
+
+
 status_t StagefrightRecorder::dump(
         int fd, const Vector<String16>& args) const {
     ALOGV("dump");
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index ec7e8ed..18c9256 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -76,6 +76,8 @@
     virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
     virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
     virtual status_t enableAudioDeviceCallback(bool enabled);
+    virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+
 
 private:
     mutable Mutex mLock;
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index b8da980..70ce38c 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -498,4 +498,12 @@
     return NO_INIT;
 }
 
+status_t AudioSource::getActiveMicrophones(
+        std::vector<media::MicrophoneInfo>* activeMicrophones) {
+    if (mRecord != 0) {
+        return mRecord->getActiveMicrophones(activeMicrophones);
+    }
+    return NO_INIT;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index 9414aab..f66b92d 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -21,11 +21,14 @@
 #include <media/AudioRecord.h>
 #include <media/AudioSystem.h>
 #include <media/MediaSource.h>
+#include <media/MicrophoneInfo.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <utils/List.h>
 
 #include <system/audio.h>
 
+#include <vector>
+
 namespace android {
 
 class AudioRecord;
@@ -64,6 +67,9 @@
     status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
     status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
 
+    status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+
+
 protected:
     virtual ~AudioSource();
 
diff --git a/packages/MediaComponents/res/layout/media_controller.xml b/packages/MediaComponents/res/layout/media_controller.xml
index 74a8306..dd56e7c 100644
--- a/packages/MediaComponents/res/layout/media_controller.xml
+++ b/packages/MediaComponents/res/layout/media_controller.xml
@@ -51,6 +51,7 @@
         <view class="com.android.support.mediarouter.app.MediaRouteButton" android:id="@+id/cast"
             android:layout_alignParentEnd="true"
             android:layout_centerVertical="true"
+            android:visibility="gone"
             style="@style/TitleBarButton" />
 
     </RelativeLayout>
diff --git a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
index d21edae..3e6d98f 100644
--- a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public void getBrowserRoot_impl(Bundle rootHints) {
+    public void getLibraryRoot_impl(Bundle rootHints) {
         final IMediaSession2 binder = getSessionBinder();
         if (binder != null) {
             try {
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 010cff5..41dfd00 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -43,6 +43,8 @@
 import android.support.annotation.GuardedBy;
 import android.util.Log;
 
+import com.android.media.MediaSession2Impl.CommandButtonImpl;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
@@ -650,7 +652,7 @@
             }
             List<CommandButton> layout = new ArrayList<>();
             for (int i = 0; i < commandButtonlist.size(); i++) {
-                CommandButton button = CommandButton.fromBundle(
+                CommandButton button = CommandButtonImpl.fromBundle(
                         browser.getContext(), commandButtonlist.get(i));
                 if (button != null) {
                     layout.add(button);
diff --git a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
index 2ac6898..54c8d41 100644
--- a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.media.MediaLibraryService2;
+import android.media.MediaLibraryService2.LibraryRoot;
 import android.media.MediaLibraryService2.MediaLibrarySession;
 import android.media.MediaLibraryService2.MediaLibrarySessionBuilder;
 import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
@@ -69,7 +70,7 @@
         public MediaLibrarySessionImpl(Context context,
                 MediaPlayerInterface player, String id, VolumeProvider volumeProvider,
                 int ratingType, PendingIntent sessionActivity, Executor callbackExecutor,
-                MediaLibrarySessionCallback callback)  {
+                MediaLibrarySessionCallback callback) {
             super(context, player, id, volumeProvider, ratingType, sessionActivity,
                     callbackExecutor, callback);
             mCallback = callback;
@@ -100,8 +101,8 @@
     public static class BuilderImpl
             extends BuilderBaseImpl<MediaLibrarySession, MediaLibrarySessionCallback> {
         public BuilderImpl(Context context, MediaLibrarySessionBuilder instance,
-            MediaPlayerInterface player, Executor callbackExecutor,
-            MediaLibrarySessionCallback callback) {
+                MediaPlayerInterface player, Executor callbackExecutor,
+                MediaLibrarySessionCallback callback) {
             super(context, player);
             setSessionCallback_impl(callbackExecutor, callback);
         }
@@ -112,4 +113,31 @@
                     mSessionActivity, mCallbackExecutor, mCallback).getInstance();
         }
     }
-}
+
+    public static final class LibraryRootImpl implements LibraryRootProvider {
+        private final LibraryRoot mInstance;
+        private final String mRootId;
+        private final Bundle mExtras;
+
+        public LibraryRootImpl(Context context, LibraryRoot instance, String rootId,
+                Bundle extras) {
+            if (rootId == null) {
+                throw new IllegalArgumentException("The root id in BrowserRoot cannot be null. " +
+                        "Use null for BrowserRoot instead.");
+            }
+            mInstance = instance;
+            mRootId = rootId;
+            mExtras = extras;
+        }
+
+        @Override
+        public String getRootId_impl() {
+            return mRootId;
+        }
+
+        @Override
+        public Bundle getExtras_impl() {
+            return mExtras;
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index 526046f..f820cdc 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -16,6 +16,7 @@
 
 package com.android.media;
 
+import static android.media.MediaSession2.COMMAND_CODE_CUSTOM;
 import static android.media.SessionToken2.TYPE_LIBRARY_SERVICE;
 import static android.media.SessionToken2.TYPE_SESSION;
 import static android.media.SessionToken2.TYPE_SESSION_SERVICE;
@@ -50,6 +51,7 @@
 import android.media.VolumeProvider;
 import android.media.session.MediaSessionManager;
 import android.media.update.MediaSession2Provider;
+import android.media.update.MediaSession2Provider.CommandButtonProvider;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.Process;
@@ -550,7 +552,7 @@
                 throw new IllegalArgumentException("action shouldn't be null");
             }
             mInstance = instance;
-            mCommandCode = MediaSession2.COMMAND_CODE_CUSTOM;
+            mCommandCode = COMMAND_CODE_CUSTOM;
             mCustomCommand = action;
             mExtra = extra;
         }
@@ -583,7 +585,7 @@
          */
         public static Command fromBundle_impl(Context context, Bundle command) {
             int code = command.getInt(KEY_COMMAND_CODE);
-            if (code != MediaSession2.COMMAND_CODE_CUSTOM) {
+            if (code != COMMAND_CODE_CUSTOM) {
                 return new Command(context, code);
             } else {
                 String customCommand = command.getString(KEY_COMMAND_CUSTOM_COMMAND);
@@ -657,7 +659,7 @@
 
         @Override
         public boolean hasCommand_impl(int code) {
-            if (code == MediaSession2.COMMAND_CODE_CUSTOM) {
+            if (code == COMMAND_CODE_CUSTOM) {
                 throw new IllegalArgumentException("Use hasCommand(Command) for custom command");
             }
             for (int i = 0; i < mCommands.size(); i++) {
@@ -876,6 +878,153 @@
         }
     }
 
+    public static class CommandButtonImpl implements CommandButtonProvider {
+        private static final String KEY_COMMAND
+                = "android.media.media_session2.command_button.command";
+        private static final String KEY_ICON_RES_ID
+                = "android.media.media_session2.command_button.icon_res_id";
+        private static final String KEY_DISPLAY_NAME
+                = "android.media.media_session2.command_button.display_name";
+        private static final String KEY_EXTRA
+                = "android.media.media_session2.command_button.extra";
+        private static final String KEY_ENABLED
+                = "android.media.media_session2.command_button.enabled";
+
+        private final CommandButton mInstance;
+        private Command mCommand;
+        private int mIconResId;
+        private String mDisplayName;
+        private Bundle mExtra;
+        private boolean mEnabled;
+
+        public CommandButtonImpl(Context context, @Nullable Command command, int iconResId,
+                @Nullable String displayName, Bundle extra, boolean enabled) {
+            mCommand = command;
+            mIconResId = iconResId;
+            mDisplayName = displayName;
+            mExtra = extra;
+            mEnabled = enabled;
+            mInstance = new CommandButton(this);
+        }
+
+        @Override
+        public @Nullable Command getCommand_impl() {
+            return mCommand;
+        }
+
+        @Override
+        public int getIconResId_impl() {
+            return mIconResId;
+        }
+
+        @Override
+        public @Nullable String getDisplayName_impl() {
+            return mDisplayName;
+        }
+
+        @Override
+        public @Nullable Bundle getExtra_impl() {
+            return mExtra;
+        }
+
+        @Override
+        public boolean isEnabled_impl() {
+            return mEnabled;
+        }
+
+        public @NonNull Bundle toBundle() {
+            Bundle bundle = new Bundle();
+            bundle.putBundle(KEY_COMMAND, mCommand.toBundle());
+            bundle.putInt(KEY_ICON_RES_ID, mIconResId);
+            bundle.putString(KEY_DISPLAY_NAME, mDisplayName);
+            bundle.putBundle(KEY_EXTRA, mExtra);
+            bundle.putBoolean(KEY_ENABLED, mEnabled);
+            return bundle;
+        }
+
+        public static @Nullable CommandButton fromBundle(Context context, Bundle bundle) {
+            if (bundle == null) {
+                return null;
+            }
+            CommandButton.Builder builder = new CommandButton.Builder(context);
+            builder.setCommand(Command.fromBundle(context, bundle.getBundle(KEY_COMMAND)));
+            builder.setIconResId(bundle.getInt(KEY_ICON_RES_ID, 0));
+            builder.setDisplayName(bundle.getString(KEY_DISPLAY_NAME));
+            builder.setExtra(bundle.getBundle(KEY_EXTRA));
+            builder.setEnabled(bundle.getBoolean(KEY_ENABLED));
+            try {
+                return builder.build();
+            } catch (IllegalStateException e) {
+                // Malformed or version mismatch. Return null for now.
+                return null;
+            }
+        }
+
+        /**
+         * Builder for {@link CommandButton}.
+         */
+        public static class BuilderImpl implements CommandButtonProvider.BuilderProvider {
+            private final Context mContext;
+            private final CommandButton.Builder mInstance;
+            private Command mCommand;
+            private int mIconResId;
+            private String mDisplayName;
+            private Bundle mExtra;
+            private boolean mEnabled;
+
+            public BuilderImpl(Context context, CommandButton.Builder instance) {
+                mContext = context;
+                mInstance = instance;
+                mEnabled = true;
+            }
+
+            @Override
+            public CommandButton.Builder setCommand_impl(Command command) {
+                mCommand = command;
+                return mInstance;
+            }
+
+            @Override
+            public CommandButton.Builder setIconResId_impl(int resId) {
+                mIconResId = resId;
+                return mInstance;
+            }
+
+            @Override
+            public CommandButton.Builder setDisplayName_impl(String displayName) {
+                mDisplayName = displayName;
+                return mInstance;
+            }
+
+            @Override
+            public CommandButton.Builder setEnabled_impl(boolean enabled) {
+                mEnabled = enabled;
+                return mInstance;
+            }
+
+            @Override
+            public CommandButton.Builder setExtra_impl(Bundle extra) {
+                mExtra = extra;
+                return mInstance;
+            }
+
+            @Override
+            public CommandButton build_impl() {
+                if (mEnabled && mCommand == null) {
+                    throw new IllegalStateException("Enabled button needs Command"
+                            + " for controller to invoke the command");
+                }
+                if (mCommand != null && mCommand.getCommandCode() == COMMAND_CODE_CUSTOM
+                        && (mIconResId == 0 || TextUtils.isEmpty(mDisplayName))) {
+                    throw new IllegalStateException("Custom commands needs icon and"
+                            + " and name to display");
+                }
+                return new CommandButtonImpl(
+                        mContext, mCommand, mIconResId, mDisplayName, mExtra, mEnabled).mInstance;
+            }
+        }
+    }
+
     public static abstract class BuilderBaseImpl<T extends MediaSession2, C extends SessionCallback>
             implements BuilderBaseProvider<T, C> {
         final Context mContext;
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index 9a22c25..1f71187 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 import android.media.MediaItem2;
-import android.media.MediaLibraryService2.BrowserRoot;
+import android.media.MediaLibraryService2.LibraryRoot;
 import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
 import android.media.MediaSession2;
 import android.media.MediaSession2.Command;
@@ -27,6 +27,7 @@
 import android.media.MediaSession2.ControllerInfo;
 import android.media.MediaSession2.PlaylistParams;
 import android.media.PlaybackState2;
+import android.media.update.MediaSession2Provider.CommandButtonProvider;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -36,6 +37,7 @@
 import android.util.ArrayMap;
 import android.util.Log;
 
+import com.android.media.MediaSession2Impl.CommandButtonImpl;
 import com.android.media.MediaSession2Impl.ControllerInfoImpl;
 
 import java.lang.ref.WeakReference;
@@ -261,7 +263,7 @@
         final MediaSession2Impl sessionImpl = getSession();
         if (!(sessionImpl.getCallback() instanceof MediaLibrarySessionCallback)) {
             if (DEBUG) {
-                Log.d(TAG, "Session cannot hand getBrowserRoot()");
+                Log.d(TAG, "Session cannot hand getLibraryRoot()");
             }
             return;
         }
@@ -280,7 +282,7 @@
             final MediaLibrarySessionCallback libraryCallback =
                     (MediaLibrarySessionCallback) session.getCallback();
             final ControllerInfoImpl controllerImpl = ControllerInfoImpl.from(controller);
-            BrowserRoot root = libraryCallback.onGetRoot(controller, rootHints);
+            LibraryRoot root = libraryCallback.onGetRoot(controller, rootHints);
             try {
                 controllerImpl.getControllerBinder().onGetRootResult(rootHints,
                         root == null ? null : root.getRootId(),
@@ -336,7 +338,7 @@
         try {
             List<Bundle> layoutBundles = new ArrayList<>();
             for (int i = 0; i < layout.size(); i++) {
-                Bundle bundle = layout.get(i).toBundle();
+                Bundle bundle = ((CommandButtonImpl) layout.get(i).getProvider()).toBundle();
                 if (bundle != null) {
                     layoutBundles.add(bundle);
                 }
diff --git a/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java
index 7dce109..8773df4 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java
@@ -18,7 +18,9 @@
 
 import static android.content.Context.NOTIFICATION_SERVICE;
 
+import android.app.Notification;
 import android.app.NotificationManager;
+import android.content.Context;
 import android.content.Intent;
 import android.media.MediaPlayerInterface.PlaybackListener;
 import android.media.MediaSession2;
@@ -116,7 +118,8 @@
                 if (!mIsRunningForeground) {
                     mIsRunningForeground = true;
                     mInstance.startForegroundService(mStartSelfIntent);
-                    mInstance.startForeground(mediaNotification.id, mediaNotification.notification);
+                    mInstance.startForeground(mediaNotification.getNotificationId(),
+                            mediaNotification.getNotification());
                     return;
                 }
                 break;
@@ -128,7 +131,8 @@
                 }
                 break;
         }
-        mNotificationManager.notify(mediaNotification.id, mediaNotification.notification);
+        mNotificationManager.notify(mediaNotification.getNotificationId(),
+                mediaNotification.getNotification());
     }
 
     private class SessionServicePlaybackListener implements PlaybackListener {
@@ -142,4 +146,28 @@
             updateNotification(state);
         }
     }
+
+    public static class MediaNotificationImpl implements MediaNotificationProvider {
+        private int mNotificationId;
+        private Notification mNotification;
+
+        public MediaNotificationImpl(Context context, MediaNotification instance,
+                int notificationId, Notification notification) {
+            if (notification == null) {
+                throw new IllegalArgumentException("notification shouldn't be null");
+            }
+            mNotificationId = notificationId;
+            mNotification = notification;
+        }
+
+        @Override
+        public int getNotificationId_impl() {
+            return mNotificationId;
+        }
+
+        @Override
+        public Notification getNotification_impl() {
+            return mNotification;
+        }
+    }
 }
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
index cc19ccf..661e252 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
@@ -16,6 +16,7 @@
 
 package com.android.media.update;
 
+import android.app.Notification;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -26,6 +27,7 @@
 import android.media.MediaController2.ControllerCallback;
 import android.media.MediaItem2;
 import android.media.MediaLibraryService2;
+import android.media.MediaLibraryService2.LibraryRoot;
 import android.media.MediaLibraryService2.MediaLibrarySession;
 import android.media.MediaLibraryService2.MediaLibrarySessionBuilder;
 import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
@@ -33,11 +35,13 @@
 import android.media.MediaPlayerInterface;
 import android.media.MediaSession2;
 import android.media.MediaSession2.Command;
+import android.media.MediaSession2.CommandButton.Builder;
 import android.media.MediaSession2.CommandGroup;
 import android.media.MediaSession2.ControllerInfo;
 import android.media.MediaSession2.PlaylistParams;
 import android.media.MediaSession2.SessionCallback;
 import android.media.MediaSessionService2;
+import android.media.MediaSessionService2.MediaNotification;
 import android.media.PlaybackState2;
 import android.media.Rating2;
 import android.media.SessionPlayer2;
@@ -47,11 +51,14 @@
 import android.media.update.MediaControlView2Provider;
 import android.media.update.MediaController2Provider;
 import android.media.update.MediaItem2Provider;
+import android.media.update.MediaLibraryService2Provider.LibraryRootProvider;
 import android.media.update.MediaMetadata2Provider;
 import android.media.update.MediaSession2Provider;
 import android.media.update.MediaSession2Provider.BuilderBaseProvider;
+import android.media.update.MediaSession2Provider.CommandButtonProvider.BuilderProvider;
 import android.media.update.MediaSession2Provider.PlaylistParamsProvider;
 import android.media.update.MediaSessionService2Provider;
+import android.media.update.MediaSessionService2Provider.MediaNotificationProvider;
 import android.media.update.PlaybackState2Provider;
 import android.media.update.SessionPlayer2Provider;
 import android.media.update.SessionToken2Provider;
@@ -71,6 +78,7 @@
 import com.android.media.MediaController2Impl;
 import com.android.media.MediaItem2Impl;
 import com.android.media.MediaLibraryService2Impl;
+import com.android.media.MediaLibraryService2Impl.LibraryRootImpl;
 import com.android.media.MediaMetadata2Impl;
 import com.android.media.MediaSession2Impl;
 import com.android.media.MediaSession2Impl.PlaylistParamsImpl;
@@ -151,6 +159,12 @@
         return PlaylistParamsImpl.fromBundle(context, bundle);
     }
 
+    @Override
+    public BuilderProvider createMediaSession2CommandButtonBuilder(Context context,
+            Builder instance) {
+        return new MediaSession2Impl.CommandButtonImpl.BuilderImpl(context, instance);
+    }
+
     public BuilderBaseProvider<MediaSession2, SessionCallback> createMediaSession2Builder(
             Context context, MediaSession2.Builder instance, MediaPlayerInterface player) {
         return new MediaSession2Impl.BuilderImpl(context, instance, player);
@@ -163,6 +177,13 @@
     }
 
     @Override
+    public MediaNotificationProvider createMediaSessionService2MediaNotification(Context context,
+            MediaNotification instance, int notificationId, Notification notification) {
+        return new MediaSessionService2Impl.MediaNotificationImpl(
+                context, instance, notificationId, notification);
+    }
+
+    @Override
     public MediaSessionService2Provider createMediaLibraryService2(
             MediaLibraryService2 instance) {
         return new MediaLibraryService2Impl(instance);
@@ -178,6 +199,12 @@
     }
 
     @Override
+    public LibraryRootProvider createMediaLibraryService2LibraryRoot(Context context,
+            LibraryRoot instance, String rootId, Bundle extras) {
+        return new LibraryRootImpl(context, instance, rootId, extras);
+    }
+
+    @Override
     public MediaControlView2Provider createMediaControlView2(
             MediaControlView2 instance, ViewProvider superProvider) {
         return new MediaControlView2Impl(instance, superProvider);
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
index 65fc88c..7fdcfe4 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
@@ -90,6 +90,7 @@
     private final MediaRouterCallback mCallback;
 
     private MediaRouteSelector mSelector = MediaRouteSelector.EMPTY;
+    private int mRouteCallbackFlags;
     private MediaRouteDialogFactory mDialogFactory = MediaRouteDialogFactory.getDefault();
 
     private boolean mAttachedToWindow;
@@ -174,23 +175,38 @@
      * Sets the media route selector for filtering the routes that the user can
      * select using the media route chooser dialog.
      *
-     * @param selector The selector, must not be null.
+     * @param selector The selector.
      */
     public void setRouteSelector(MediaRouteSelector selector) {
-        if (selector == null) {
-            throw new IllegalArgumentException("selector must not be null");
+        setRouteSelector(selector, 0);
+    }
+
+    /**
+     * Sets the media route selector for filtering the routes that the user can
+     * select using the media route chooser dialog.
+     *
+     * @param selector The selector.
+     * @param flags Flags to control the behavior of the callback. May be zero or a combination of
+     *              {@link #MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN} and
+     *              {@link #MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS}.
+     */
+    public void setRouteSelector(MediaRouteSelector selector, int flags) {
+        if (mSelector.equals(selector) && mRouteCallbackFlags == flags) {
+            return;
+        }
+        if (!mSelector.isEmpty()) {
+            mRouter.removeCallback(mCallback);
+        }
+        if (selector == null || selector.isEmpty()) {
+            mSelector = MediaRouteSelector.EMPTY;
+            return;
         }
 
-        if (!mSelector.equals(selector)) {
-            if (mAttachedToWindow) {
-                if (!mSelector.isEmpty()) {
-                    mRouter.removeCallback(mCallback);
-                }
-                if (!selector.isEmpty()) {
-                    mRouter.addCallback(selector, mCallback);
-                }
-            }
-            mSelector = selector;
+        mSelector = selector;
+        mRouteCallbackFlags = flags;
+
+        if (mAttachedToWindow) {
+            mRouter.addCallback(selector, mCallback, flags);
             refreshRoute();
         }
     }
@@ -411,7 +427,7 @@
 
         mAttachedToWindow = true;
         if (!mSelector.isEmpty()) {
-            mRouter.addCallback(mSelector, mCallback);
+            mRouter.addCallback(mSelector, mCallback, mRouteCallbackFlags);
         }
         refreshRoute();
     }
diff --git a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
index b4aaa79..138232e 100644
--- a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
@@ -38,6 +38,9 @@
 
 import com.android.media.update.ApiHelper;
 import com.android.media.update.R;
+import com.android.support.mediarouter.app.MediaRouteButton;
+import com.android.support.mediarouter.media.MediaRouter;
+import com.android.support.mediarouter.media.MediaRouteSelector;
 
 import java.util.Formatter;
 import java.util.List;
@@ -107,6 +110,9 @@
     private StringBuilder mFormatBuilder;
     private Formatter mFormatter;
 
+    private MediaRouteButton mRouteButton;
+    private MediaRouteSelector mRouteSelector;
+
     public MediaControlView2Impl(
             MediaControlView2 instance, ViewProvider superProvider) {
         mInstance = instance;
@@ -305,6 +311,17 @@
         mSuperProvider.setEnabled_impl(enabled);
     }
 
+    public void setRouteSelector(MediaRouteSelector selector) {
+        mRouteSelector = selector;
+        if (mRouteSelector != null && !mRouteSelector.isEmpty()) {
+            mRouteButton.setRouteSelector(selector, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
+            mRouteButton.setVisibility(View.VISIBLE);
+        } else {
+            mRouteButton.setRouteSelector(MediaRouteSelector.EMPTY);
+            mRouteButton.setVisibility(View.GONE);
+        }
+    }
+
     ///////////////////////////////////////////////////
     // Protected or private methods
     ///////////////////////////////////////////////////
@@ -375,6 +392,8 @@
         mPauseDescription = res.getText(R.string.lockscreen_pause_button_content_description);
         mReplayDescription = res.getText(R.string.lockscreen_replay_button_content_description);
 
+        mRouteButton = v.findViewById(R.id.cast);
+
         mPlayPauseButton = v.findViewById(R.id.pause);
         if (mPlayPauseButton != null) {
             mPlayPauseButton.requestFocus();
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index e90d107..7218150 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -104,7 +104,7 @@
     private MediaController mMediaController;
     private MediaSession.Callback mRouteSessionCallback = new RouteSessionCallback();
     private MediaRouter mMediaRouter;
-    private MediaRouteSelector mMediaRouteSelector;
+    private MediaRouteSelector mRouteSelector;
     private Metadata mMetadata;
     private String mTitle;
 
@@ -201,6 +201,10 @@
     @Override
     public void setMediaControlView2_impl(MediaControlView2 mediaControlView) {
         mMediaControlView = mediaControlView;
+        if (mRouteSelector != null) {
+            ((MediaControlView2Impl) mMediaControlView.getProvider())
+                    .setRouteSelector(mRouteSelector);
+        }
 
         if (mInstance.isAttachedToWindow()) {
             attachMediaControlView();
@@ -293,7 +297,11 @@
         for (String category : routeCategories) {
             builder.addControlCategory(category);
         }
-        mMediaRouteSelector = builder.build();
+        mRouteSelector = builder.build();
+        if (mMediaControlView != null) {
+            ((MediaControlView2Impl) mMediaControlView.getProvider())
+                    .setRouteSelector(mRouteSelector);
+        }
         mMediaRouter = MediaRouter.getInstance(mInstance.getContext());
         mRouteSessionCallback = sessionPlayer;
         if (mMediaSession != null) {
diff --git a/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java b/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java
index 50e59b8..38475a8 100644
--- a/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java
@@ -66,7 +66,7 @@
     }
 
     @Test
-    public void testGetBrowserRoot() throws InterruptedException {
+    public void testGetLibraryRoot() throws InterruptedException {
         final Bundle param = new Bundle();
         param.putString(TAG, TAG);
 
@@ -84,7 +84,7 @@
         final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
         MediaBrowser2 browser =
                 (MediaBrowser2) createController(token,true, callback);
-        browser.getBrowserRoot(param);
+        browser.getLibraryRoot(param);
         assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
     }
 
diff --git a/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java b/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
index 6e1501a..ec69ff6 100644
--- a/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
+++ b/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
@@ -97,8 +97,8 @@
         }
 
         @Override
-        public BrowserRoot onGetRoot(ControllerInfo controller, Bundle rootHints) {
-            return new BrowserRoot(ROOT_ID, EXTRA);
+        public LibraryRoot onGetRoot(ControllerInfo controller, Bundle rootHints) {
+            return new LibraryRoot(MockMediaLibraryService2.this, ROOT_ID, EXTRA);
         }
     }
 }
\ No newline at end of file
diff --git a/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java b/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java
index d85875e..c8ed184 100644
--- a/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java
+++ b/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java
@@ -87,7 +87,7 @@
                 .setContentTitle(getPackageName())
                 .setContentText("Playback state: " + state.getState())
                 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
-        return MediaNotification.create(DEFAULT_MEDIA_NOTIFICATION_ID, notification);
+        return new MediaNotification(this, DEFAULT_MEDIA_NOTIFICATION_ID, notification);
     }
 
     private class MySessionCallback extends SessionCallback {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 83caca7..7c38bcc 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -559,6 +559,8 @@
         virtual binder::Status    start(int /*AudioSystem::sync_event_t*/ event,
                 int /*audio_session_t*/ triggerSession);
         virtual binder::Status   stop();
+        virtual binder::Status   getActiveMicrophones(
+                std::vector<media::MicrophoneInfo>* activeMicrophones);
     private:
         const sp<RecordThread::RecordTrack> mRecordTrack;
 
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 63a3d98..1733ef5 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -66,6 +66,8 @@
             void        setSilenced(bool silenced) { mSilenced = silenced; }
             bool        isSilenced() const { return mSilenced; }
 
+            status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+
 private:
     friend class AudioFlinger;  // for mState
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 420e6e1..14d7e2e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7043,6 +7043,49 @@
 #endif
 }
 
+status_t AudioFlinger::RecordThread::getActiveMicrophones(
+        std::vector<media::MicrophoneInfo>* activeMicrophones)
+{
+    ALOGV("RecordThread::getActiveMicrophones");
+    AutoMutex _l(mLock);
+    // Fake data
+    struct audio_microphone_characteristic_t characteristic;
+    sprintf(characteristic.device_id, "builtin_mic");
+    characteristic.type = AUDIO_DEVICE_IN_BUILTIN_MIC;
+    sprintf(characteristic.address, "");
+    characteristic.location = AUDIO_MICROPHONE_LOCATION_MAINBODY;
+    characteristic.group = 0;
+    characteristic.index_in_the_group = 0;
+    characteristic.sensitivity = 1.0f;
+    characteristic.max_spl = 100.0f;
+    characteristic.min_spl = 0.0f;
+    characteristic.directionality = AUDIO_MICROPHONE_DIRECTIONALITY_OMNI;
+    characteristic.num_frequency_responses = 5;
+    for (size_t i = 0; i < characteristic.num_frequency_responses; i++) {
+        characteristic.frequency_responses[0][i] = 100.0f - i;
+        characteristic.frequency_responses[1][i] = 100.0f + i;
+    }
+    for (size_t i = 0; i < AUDIO_CHANNEL_COUNT_MAX; i++) {
+        characteristic.channel_mapping[i] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+    }
+    audio_microphone_channel_mapping_t channel_mappings[] = {
+        AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT,
+        AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED,
+    };
+    for (size_t i = 0; i < mChannelCount; i++) {
+        characteristic.channel_mapping[i] = channel_mappings[i % 2];
+    }
+    characteristic.geometric_location.x = 0.1f;
+    characteristic.geometric_location.y = 0.2f;
+    characteristic.geometric_location.z = 0.3f;
+    characteristic.orientation.x = 0.0f;
+    characteristic.orientation.y = 1.0f;
+    characteristic.orientation.z = 0.0f;
+    media::MicrophoneInfo microphoneInfo = media::MicrophoneInfo(characteristic);
+    activeMicrophones->push_back(microphoneInfo);
+    return NO_ERROR;
+}
+
 // destroyTrack_l() must be called with ThreadBase::mLock held
 void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track)
 {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index eb29497..53cb8ad 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1398,6 +1398,8 @@
             // Sets the UID records silence
             void        setRecordSilenced(uid_t uid, bool silenced);
 
+            status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+
 private:
             // Enter standby if not already in standby, and set mStandby flag
             void    standbyIfNotAlreadyInStandby();
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index cdd8ca0..ce5c53b 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1580,6 +1580,13 @@
     mRecordTrack->stop();
 }
 
+binder::Status AudioFlinger::RecordHandle::getActiveMicrophones(
+        std::vector<media::MicrophoneInfo>* activeMicrophones) {
+    ALOGV("RecordHandle::getActiveMicrophones()");
+    return binder::Status::fromStatusT(
+            mRecordTrack->getActiveMicrophones(activeMicrophones));
+}
+
 // ----------------------------------------------------------------------------
 
 // RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
@@ -1792,6 +1799,18 @@
     mServerProxy->setTimestamp(local);
 }
 
+status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
+        std::vector<media::MicrophoneInfo>* activeMicrophones)
+{
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        RecordThread *recordThread = (RecordThread *)thread.get();
+        return recordThread->getActiveMicrophones(activeMicrophones);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
 AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread,
                                                      uint32_t sampleRate,
                                                      audio_channel_mask_t channelMask,
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index f149f8a..9ba8bb7 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -3393,6 +3393,8 @@
 }
 
 void Camera3Device::HalInterface::clear() {
+    mHidlSession_3_4.clear();
+    mHidlSession_3_3.clear();
     mHidlSession.clear();
 }