summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-05-31 00:49:43 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-05-31 00:49:44 +0000
commit8725859ee3a9fb7dd09641c2b13baa4f7a16ca99 (patch)
tree3893300514607088109f32e74023fbb50965d46a /media
parenta89eb2d8e550b511285ab3b4fb7dec1ed4ca5028 (diff)
parent700e73471d85348b52ecf213c36bb24b93997ec7 (diff)
downloadframeworks_base-8725859ee3a9fb7dd09641c2b13baa4f7a16ca99.zip
frameworks_base-8725859ee3a9fb7dd09641c2b13baa4f7a16ca99.tar.gz
frameworks_base-8725859ee3a9fb7dd09641c2b13baa4f7a16ca99.tar.bz2
Merge "audio routing update listener" into lmp-preview-dev
Diffstat (limited to 'media')
-rw-r--r--media/java/android/media/AudioManager.java9
-rw-r--r--media/java/android/media/AudioPortEventHandler.java168
2 files changed, 175 insertions, 2 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index bbe5331..e6988b6 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -41,6 +41,7 @@ import android.view.KeyEvent;
import java.util.HashMap;
import java.util.ArrayList;
+
/**
* AudioManager provides access to volume and ringer mode control.
* <p>
@@ -61,6 +62,7 @@ public class AudioManager {
private final boolean mUseVolumeKeySounds;
private final Binder mToken = new Binder();
private static String TAG = "AudioManager";
+ AudioPortEventHandler mAudioPortEventHandler;
/**
* Broadcast intent, a hint for applications that audio is about to become
@@ -438,6 +440,7 @@ public class AudioManager {
com.android.internal.R.bool.config_useMasterVolume);
mUseVolumeKeySounds = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useVolumeKeySounds);
+ mAudioPortEventHandler = new AudioPortEventHandler(this);
}
private static IAudioService getService()
@@ -3112,17 +3115,19 @@ public class AudioManager {
}
/**
- * Register an audio port update listener.
+ * Register an audio port list update listener.
* @hide
*/
public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) {
+ mAudioPortEventHandler.registerListener(l);
}
/**
- * Unregister an audio port update listener.
+ * Unregister an audio port list update listener.
* @hide
*/
public void unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l) {
+ mAudioPortEventHandler.unregisterListener(l);
}
//
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
new file mode 100644
index 0000000..cd9a4de
--- /dev/null
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package android.media;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.lang.ref.WeakReference;
+
+/**
+ * The AudioPortEventHandler handles AudioManager.OnAudioPortUpdateListener callbacks
+ * posted from JNI
+ * @hide
+ */
+
+class AudioPortEventHandler {
+ private final Handler mHandler;
+ private ArrayList<AudioManager.OnAudioPortUpdateListener> mListeners;
+ private AudioManager mAudioManager;
+
+ private static String TAG = "AudioPortEventHandler";
+
+ private static final int AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1;
+ private static final int AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2;
+ private static final int AUDIOPORT_EVENT_SERVICE_DIED = 3;
+ private static final int AUDIOPORT_EVENT_NEW_LISTENER = 4;
+
+ AudioPortEventHandler(AudioManager audioManager) {
+ mAudioManager = audioManager;
+ mListeners = new ArrayList<AudioManager.OnAudioPortUpdateListener>();
+
+ // find the looper for our new event handler
+ Looper looper = Looper.myLooper();
+ if (looper == null) {
+ throw new IllegalArgumentException("Calling thread not associated with a looper");
+ }
+
+ mHandler = new Handler(looper) {
+ @Override
+ public void handleMessage(Message msg) {
+ Log.i(TAG, "handleMessage: "+msg.what);
+ ArrayList<AudioManager.OnAudioPortUpdateListener> listeners;
+ synchronized (this) {
+ if (msg.what == AUDIOPORT_EVENT_NEW_LISTENER) {
+ listeners = new ArrayList<AudioManager.OnAudioPortUpdateListener>();
+ if (mListeners.contains(msg.obj)) {
+ listeners.add((AudioManager.OnAudioPortUpdateListener)msg.obj);
+ }
+ } else {
+ listeners = mListeners;
+ }
+ }
+ if (listeners.isEmpty()) {
+ return;
+ }
+ // reset audio port cache if the event corresponds to a change coming
+ // from audio policy service or if mediaserver process died.
+ if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED ||
+ msg.what == AUDIOPORT_EVENT_PATCH_LIST_UPDATED ||
+ msg.what == AUDIOPORT_EVENT_SERVICE_DIED) {
+ mAudioManager.resetAudioPortGeneration();
+ }
+ ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
+ ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
+ if (msg.what != AUDIOPORT_EVENT_SERVICE_DIED) {
+ int status = mAudioManager.updateAudioPortCache(ports, patches);
+ if (status != AudioManager.SUCCESS) {
+ return;
+ }
+ }
+
+ switch (msg.what) {
+ case AUDIOPORT_EVENT_NEW_LISTENER:
+ case AUDIOPORT_EVENT_PORT_LIST_UPDATED:
+ AudioPort[] portList = ports.toArray(new AudioPort[0]);
+ for (int i = 0; i < listeners.size(); i++) {
+ listeners.get(i).OnAudioPortListUpdate(portList);
+ }
+ if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED) {
+ break;
+ }
+ // FALL THROUGH
+
+ case AUDIOPORT_EVENT_PATCH_LIST_UPDATED:
+ AudioPatch[] patchList = patches.toArray(new AudioPatch[0]);
+ for (int i = 0; i < listeners.size(); i++) {
+ listeners.get(i).OnAudioPatchListUpdate(patchList);
+ }
+ break;
+
+ case AUDIOPORT_EVENT_SERVICE_DIED:
+ for (int i = 0; i < listeners.size(); i++) {
+ listeners.get(i).OnServiceDied();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ };
+
+ native_setup(new WeakReference<AudioPortEventHandler>(this));
+ }
+ private native void native_setup(Object module_this);
+
+ @Override
+ protected void finalize() {
+ native_finalize();
+ }
+ private native void native_finalize();
+
+ void registerListener(AudioManager.OnAudioPortUpdateListener l) {
+ synchronized (this) {
+ mListeners.add(l);
+ }
+ if (mHandler != null) {
+ Message m = mHandler.obtainMessage(AUDIOPORT_EVENT_NEW_LISTENER, 0, 0, l);
+ mHandler.sendMessage(m);
+ }
+ }
+
+ void unregisterListener(AudioManager.OnAudioPortUpdateListener l) {
+ synchronized (this) {
+ mListeners.remove(l);
+ }
+ }
+
+ Handler handler() {
+ return mHandler;
+ }
+
+ @SuppressWarnings("unused")
+ private static void postEventFromNative(Object module_ref,
+ int what, int arg1, int arg2, Object obj) {
+ AudioPortEventHandler eventHandler =
+ (AudioPortEventHandler)((WeakReference)module_ref).get();
+ if (eventHandler == null) {
+ return;
+ }
+
+ if (eventHandler != null) {
+ Handler handler = eventHandler.handler();
+ if (handler != null) {
+ Message m = handler.obtainMessage(what, arg1, arg2, obj);
+ handler.sendMessage(m);
+ }
+ }
+ }
+
+}