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