/*
* 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 java.util.ArrayList;
import java.lang.ref.WeakReference;
/**
* The AudioPortEventHandler handles AudioManager.OnAudioPortUpdateListener callbacks
* posted from JNI
* @hide
*/
class AudioPortEventHandler {
private Handler mHandler;
private final ArrayList<AudioManager.OnAudioPortUpdateListener> mListeners =
new ArrayList<AudioManager.OnAudioPortUpdateListener>();
private static final 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;
/**
* Accessed by native methods: JNI Callback context.
*/
@SuppressWarnings("unused")
private long mJniCallback;
void init() {
synchronized (this) {
if (mHandler != null) {
return;
}
// find the looper for our new event handler
Looper looper = Looper.getMainLooper();
if (looper != null) {
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
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;
}
}
// 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) {
AudioManager.resetAudioPortGeneration();
}
if (listeners.isEmpty()) {
return;
}
ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
if (msg.what != AUDIOPORT_EVENT_SERVICE_DIED) {
int status = AudioManager.updateAudioPortCache(ports, patches, null);
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));
} else {
mHandler = null;
}
}
}
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);
}
}
}
}