AudioPortEventHandler.java revision 08c7116ab9cd04ad6dd3c04aa1017237e7f409ac
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.media;
18
19import android.os.Handler;
20import android.os.Looper;
21import android.os.Message;
22import java.util.ArrayList;
23import java.lang.ref.WeakReference;
24
25/**
26 * The AudioPortEventHandler handles AudioManager.OnAudioPortUpdateListener callbacks
27 * posted from JNI
28 * @hide
29 */
30
31class AudioPortEventHandler {
32    private Handler mHandler;
33    private final ArrayList<AudioManager.OnAudioPortUpdateListener> mListeners =
34            new ArrayList<AudioManager.OnAudioPortUpdateListener>();
35
36    private static final String TAG = "AudioPortEventHandler";
37
38    private static final int AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1;
39    private static final int AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2;
40    private static final int AUDIOPORT_EVENT_SERVICE_DIED = 3;
41    private static final int AUDIOPORT_EVENT_NEW_LISTENER = 4;
42
43    void init() {
44        synchronized (this) {
45            if (mHandler != null) {
46                return;
47            }
48            // find the looper for our new event handler
49            Looper looper = Looper.getMainLooper();
50
51            if (looper != null) {
52                mHandler = new Handler(looper) {
53                    @Override
54                    public void handleMessage(Message msg) {
55                        ArrayList<AudioManager.OnAudioPortUpdateListener> listeners;
56                        synchronized (this) {
57                            if (msg.what == AUDIOPORT_EVENT_NEW_LISTENER) {
58                                listeners = new ArrayList<AudioManager.OnAudioPortUpdateListener>();
59                                if (mListeners.contains(msg.obj)) {
60                                    listeners.add((AudioManager.OnAudioPortUpdateListener)msg.obj);
61                                }
62                            } else {
63                                listeners = mListeners;
64                            }
65                        }
66                        if (listeners.isEmpty()) {
67                            return;
68                        }
69                        // reset audio port cache if the event corresponds to a change coming
70                        // from audio policy service or if mediaserver process died.
71                        if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED ||
72                                msg.what == AUDIOPORT_EVENT_PATCH_LIST_UPDATED ||
73                                msg.what == AUDIOPORT_EVENT_SERVICE_DIED) {
74                            AudioManager.resetAudioPortGeneration();
75                        }
76                        ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
77                        ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
78                        if (msg.what != AUDIOPORT_EVENT_SERVICE_DIED) {
79                            int status = AudioManager.updateAudioPortCache(ports, patches);
80                            if (status != AudioManager.SUCCESS) {
81                                return;
82                            }
83                        }
84
85                        switch (msg.what) {
86                        case AUDIOPORT_EVENT_NEW_LISTENER:
87                        case AUDIOPORT_EVENT_PORT_LIST_UPDATED:
88                            AudioPort[] portList = ports.toArray(new AudioPort[0]);
89                            for (int i = 0; i < listeners.size(); i++) {
90                                listeners.get(i).onAudioPortListUpdate(portList);
91                            }
92                            if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED) {
93                                break;
94                            }
95                            // FALL THROUGH
96
97                        case AUDIOPORT_EVENT_PATCH_LIST_UPDATED:
98                            AudioPatch[] patchList = patches.toArray(new AudioPatch[0]);
99                            for (int i = 0; i < listeners.size(); i++) {
100                                listeners.get(i).onAudioPatchListUpdate(patchList);
101                            }
102                            break;
103
104                        case AUDIOPORT_EVENT_SERVICE_DIED:
105                            for (int i = 0; i < listeners.size(); i++) {
106                                listeners.get(i).onServiceDied();
107                            }
108                            break;
109
110                        default:
111                            break;
112                        }
113                    }
114                };
115                native_setup(new WeakReference<AudioPortEventHandler>(this));
116            } else {
117                mHandler = null;
118            }
119        }
120    }
121
122    private native void native_setup(Object module_this);
123
124    @Override
125    protected void finalize() {
126        native_finalize();
127    }
128    private native void native_finalize();
129
130    void registerListener(AudioManager.OnAudioPortUpdateListener l) {
131        synchronized (this) {
132            mListeners.add(l);
133        }
134        if (mHandler != null) {
135            Message m = mHandler.obtainMessage(AUDIOPORT_EVENT_NEW_LISTENER, 0, 0, l);
136            mHandler.sendMessage(m);
137        }
138    }
139
140    void unregisterListener(AudioManager.OnAudioPortUpdateListener l) {
141        synchronized (this) {
142            mListeners.remove(l);
143        }
144    }
145
146    Handler handler() {
147        return mHandler;
148    }
149
150    @SuppressWarnings("unused")
151    private static void postEventFromNative(Object module_ref,
152                                            int what, int arg1, int arg2, Object obj) {
153        AudioPortEventHandler eventHandler =
154                (AudioPortEventHandler)((WeakReference)module_ref).get();
155        if (eventHandler == null) {
156            return;
157        }
158
159        if (eventHandler != null) {
160            Handler handler = eventHandler.handler();
161            if (handler != null) {
162                Message m = handler.obtainMessage(what, arg1, arg2, obj);
163                handler.sendMessage(m);
164            }
165        }
166    }
167
168}
169