1700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent/* 2700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * Copyright (C) 2014 The Android Open Source Project 3700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * 4700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License"); 5700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * you may not use this file except in compliance with the License. 6700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * You may obtain a copy of the License at 7700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * 8700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * http://www.apache.org/licenses/LICENSE-2.0 9700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * 10700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * Unless required by applicable law or agreed to in writing, software 11700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS, 12700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * See the License for the specific language governing permissions and 14700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * limitations under the License. 15700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent */ 16700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 17700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurentpackage android.media; 18700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 19700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurentimport android.os.Handler; 20c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabinimport android.os.HandlerThread; 21700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurentimport android.os.Looper; 22700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurentimport android.os.Message; 23700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurentimport java.util.ArrayList; 24700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurentimport java.lang.ref.WeakReference; 25700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 26700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent/** 27700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * The AudioPortEventHandler handles AudioManager.OnAudioPortUpdateListener callbacks 28700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * posted from JNI 29700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent * @hide 30700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent */ 31700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 32700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurentclass AudioPortEventHandler { 33f076db407029e734703d8676f806bea94393e824Eric Laurent private Handler mHandler; 34c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin private HandlerThread mHandlerThread; 35f076db407029e734703d8676f806bea94393e824Eric Laurent private final ArrayList<AudioManager.OnAudioPortUpdateListener> mListeners = 36f076db407029e734703d8676f806bea94393e824Eric Laurent new ArrayList<AudioManager.OnAudioPortUpdateListener>(); 37700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 38f076db407029e734703d8676f806bea94393e824Eric Laurent private static final String TAG = "AudioPortEventHandler"; 39700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 40700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent private static final int AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1; 41700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent private static final int AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2; 42700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent private static final int AUDIOPORT_EVENT_SERVICE_DIED = 3; 43700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent private static final int AUDIOPORT_EVENT_NEW_LISTENER = 4; 44700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 45c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin private static final long RESCHEDULE_MESSAGE_DELAY_MS = 100; 46c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin 472615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent /** 482615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent * Accessed by native methods: JNI Callback context. 492615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent */ 502615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent @SuppressWarnings("unused") 512615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent private long mJniCallback; 522615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent 53f076db407029e734703d8676f806bea94393e824Eric Laurent void init() { 54f076db407029e734703d8676f806bea94393e824Eric Laurent synchronized (this) { 55f076db407029e734703d8676f806bea94393e824Eric Laurent if (mHandler != null) { 56f076db407029e734703d8676f806bea94393e824Eric Laurent return; 57f076db407029e734703d8676f806bea94393e824Eric Laurent } 58c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin // create a new thread for our new event handler 59c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin mHandlerThread = new HandlerThread(TAG); 60c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin mHandlerThread.start(); 61f076db407029e734703d8676f806bea94393e824Eric Laurent 62c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin if (mHandlerThread.getLooper() != null) { 63c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin mHandler = new Handler(mHandlerThread.getLooper()) { 64f076db407029e734703d8676f806bea94393e824Eric Laurent @Override 65f076db407029e734703d8676f806bea94393e824Eric Laurent public void handleMessage(Message msg) { 66f076db407029e734703d8676f806bea94393e824Eric Laurent ArrayList<AudioManager.OnAudioPortUpdateListener> listeners; 67f076db407029e734703d8676f806bea94393e824Eric Laurent synchronized (this) { 68f076db407029e734703d8676f806bea94393e824Eric Laurent if (msg.what == AUDIOPORT_EVENT_NEW_LISTENER) { 69f076db407029e734703d8676f806bea94393e824Eric Laurent listeners = new ArrayList<AudioManager.OnAudioPortUpdateListener>(); 70f076db407029e734703d8676f806bea94393e824Eric Laurent if (mListeners.contains(msg.obj)) { 71f076db407029e734703d8676f806bea94393e824Eric Laurent listeners.add((AudioManager.OnAudioPortUpdateListener)msg.obj); 72f076db407029e734703d8676f806bea94393e824Eric Laurent } 73f076db407029e734703d8676f806bea94393e824Eric Laurent } else { 74f076db407029e734703d8676f806bea94393e824Eric Laurent listeners = mListeners; 75ddc93ce3438618a15f30fc20d45634325f8ce84fEric Laurent } 76700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 77f076db407029e734703d8676f806bea94393e824Eric Laurent // reset audio port cache if the event corresponds to a change coming 78f076db407029e734703d8676f806bea94393e824Eric Laurent // from audio policy service or if mediaserver process died. 79f076db407029e734703d8676f806bea94393e824Eric Laurent if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED || 80f076db407029e734703d8676f806bea94393e824Eric Laurent msg.what == AUDIOPORT_EVENT_PATCH_LIST_UPDATED || 81f076db407029e734703d8676f806bea94393e824Eric Laurent msg.what == AUDIOPORT_EVENT_SERVICE_DIED) { 82f076db407029e734703d8676f806bea94393e824Eric Laurent AudioManager.resetAudioPortGeneration(); 83ddc93ce3438618a15f30fc20d45634325f8ce84fEric Laurent } 842615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent 852615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent if (listeners.isEmpty()) { 862615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent return; 872615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent } 882615afb1b0f597f38a07832b33df9bd888a0dce1Eric Laurent 89f076db407029e734703d8676f806bea94393e824Eric Laurent ArrayList<AudioPort> ports = new ArrayList<AudioPort>(); 90f076db407029e734703d8676f806bea94393e824Eric Laurent ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>(); 91f076db407029e734703d8676f806bea94393e824Eric Laurent if (msg.what != AUDIOPORT_EVENT_SERVICE_DIED) { 928a1e7a881ee73b9b1e492e7014c3eaefe81cfbd7Eric Laurent int status = AudioManager.updateAudioPortCache(ports, patches, null); 93f076db407029e734703d8676f806bea94393e824Eric Laurent if (status != AudioManager.SUCCESS) { 94c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin // Since audio ports and audio patches are not null, the return 95c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin // value could be ERROR due to inconsistency between port generation 96c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin // and patch generation. In this case, we need to reschedule the 97c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin // message to make sure the native callback is done. 98c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin sendMessageDelayed(obtainMessage(msg.what, msg.obj), 99c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin RESCHEDULE_MESSAGE_DELAY_MS); 100f076db407029e734703d8676f806bea94393e824Eric Laurent return; 101f076db407029e734703d8676f806bea94393e824Eric Laurent } 102ddc93ce3438618a15f30fc20d45634325f8ce84fEric Laurent } 103700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 104f076db407029e734703d8676f806bea94393e824Eric Laurent switch (msg.what) { 105f076db407029e734703d8676f806bea94393e824Eric Laurent case AUDIOPORT_EVENT_NEW_LISTENER: 106f076db407029e734703d8676f806bea94393e824Eric Laurent case AUDIOPORT_EVENT_PORT_LIST_UPDATED: 107f076db407029e734703d8676f806bea94393e824Eric Laurent AudioPort[] portList = ports.toArray(new AudioPort[0]); 108f076db407029e734703d8676f806bea94393e824Eric Laurent for (int i = 0; i < listeners.size(); i++) { 109f076db407029e734703d8676f806bea94393e824Eric Laurent listeners.get(i).onAudioPortListUpdate(portList); 110f076db407029e734703d8676f806bea94393e824Eric Laurent } 111f076db407029e734703d8676f806bea94393e824Eric Laurent if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED) { 112f076db407029e734703d8676f806bea94393e824Eric Laurent break; 113f076db407029e734703d8676f806bea94393e824Eric Laurent } 114f076db407029e734703d8676f806bea94393e824Eric Laurent // FALL THROUGH 115700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 116f076db407029e734703d8676f806bea94393e824Eric Laurent case AUDIOPORT_EVENT_PATCH_LIST_UPDATED: 117f076db407029e734703d8676f806bea94393e824Eric Laurent AudioPatch[] patchList = patches.toArray(new AudioPatch[0]); 118f076db407029e734703d8676f806bea94393e824Eric Laurent for (int i = 0; i < listeners.size(); i++) { 119f076db407029e734703d8676f806bea94393e824Eric Laurent listeners.get(i).onAudioPatchListUpdate(patchList); 120f076db407029e734703d8676f806bea94393e824Eric Laurent } 121f076db407029e734703d8676f806bea94393e824Eric Laurent break; 122f076db407029e734703d8676f806bea94393e824Eric Laurent 123f076db407029e734703d8676f806bea94393e824Eric Laurent case AUDIOPORT_EVENT_SERVICE_DIED: 124f076db407029e734703d8676f806bea94393e824Eric Laurent for (int i = 0; i < listeners.size(); i++) { 125f076db407029e734703d8676f806bea94393e824Eric Laurent listeners.get(i).onServiceDied(); 126f076db407029e734703d8676f806bea94393e824Eric Laurent } 127f076db407029e734703d8676f806bea94393e824Eric Laurent break; 128ddc93ce3438618a15f30fc20d45634325f8ce84fEric Laurent 129f076db407029e734703d8676f806bea94393e824Eric Laurent default: 130f076db407029e734703d8676f806bea94393e824Eric Laurent break; 131f076db407029e734703d8676f806bea94393e824Eric Laurent } 132ddc93ce3438618a15f30fc20d45634325f8ce84fEric Laurent } 133f076db407029e734703d8676f806bea94393e824Eric Laurent }; 134f076db407029e734703d8676f806bea94393e824Eric Laurent native_setup(new WeakReference<AudioPortEventHandler>(this)); 135f076db407029e734703d8676f806bea94393e824Eric Laurent } else { 136f076db407029e734703d8676f806bea94393e824Eric Laurent mHandler = null; 137f076db407029e734703d8676f806bea94393e824Eric Laurent } 138ddc93ce3438618a15f30fc20d45634325f8ce84fEric Laurent } 139700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 140f076db407029e734703d8676f806bea94393e824Eric Laurent 141700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent private native void native_setup(Object module_this); 142700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 143700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent @Override 144700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent protected void finalize() { 145700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent native_finalize(); 146c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin if (mHandlerThread.isAlive()) { 147c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin mHandlerThread.quit(); 148c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin } 149700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 150700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent private native void native_finalize(); 151700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 152700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent void registerListener(AudioManager.OnAudioPortUpdateListener l) { 153700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent synchronized (this) { 154700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent mListeners.add(l); 155700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 156700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent if (mHandler != null) { 157700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent Message m = mHandler.obtainMessage(AUDIOPORT_EVENT_NEW_LISTENER, 0, 0, l); 158700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent mHandler.sendMessage(m); 159700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 160700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 161700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 162700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent void unregisterListener(AudioManager.OnAudioPortUpdateListener l) { 163700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent synchronized (this) { 164700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent mListeners.remove(l); 165700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 166700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 167700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 168700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent Handler handler() { 169700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent return mHandler; 170700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 171700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 172700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent @SuppressWarnings("unused") 173700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent private static void postEventFromNative(Object module_ref, 174700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent int what, int arg1, int arg2, Object obj) { 175700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent AudioPortEventHandler eventHandler = 176700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent (AudioPortEventHandler)((WeakReference)module_ref).get(); 177700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent if (eventHandler == null) { 178700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent return; 179700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 180700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 181700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent if (eventHandler != null) { 182700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent Handler handler = eventHandler.handler(); 183700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent if (handler != null) { 184700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent Message m = handler.obtainMessage(what, arg1, arg2, obj); 185c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin if (what != AUDIOPORT_EVENT_NEW_LISTENER) { 186c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin // Except AUDIOPORT_EVENT_NEW_LISTENER, we can only respect the last message. 187c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin handler.removeMessages(what); 188c4ecaa52b87cc473c15c5cb378f466a1a0108c0ajiabin } 189700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent handler.sendMessage(m); 190700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 191700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 192700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent } 193700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent 194700e73471d85348b52ecf213c36bb24b93997ec7Eric Laurent} 195