Merge "Reduce time consuming when a lot of audio port event happen continually."
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 186b265..dab7632a 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4119,7 +4119,15 @@
Log.w(TAG, "updateAudioPortCache: listAudioPatches failed");
return status;
}
- } while (patchGeneration[0] != portGeneration[0]);
+ // Loop until patch generation is the same as port generation unless audio ports
+ // and audio patches are not null.
+ } while (patchGeneration[0] != portGeneration[0]
+ && (ports == null || patches == null));
+ // If the patch generation doesn't equal port generation, return ERROR here in case
+ // of mismatch between audio ports and audio patches.
+ if (patchGeneration[0] != portGeneration[0]) {
+ return ERROR;
+ }
for (int i = 0; i < newPatches.size(); i++) {
for (int j = 0; j < newPatches.get(i).sources().length; j++) {
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index c152245..ac3904a 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -17,6 +17,7 @@
package android.media;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import java.util.ArrayList;
@@ -30,6 +31,7 @@
class AudioPortEventHandler {
private Handler mHandler;
+ private HandlerThread mHandlerThread;
private final ArrayList<AudioManager.OnAudioPortUpdateListener> mListeners =
new ArrayList<AudioManager.OnAudioPortUpdateListener>();
@@ -40,6 +42,8 @@
private static final int AUDIOPORT_EVENT_SERVICE_DIED = 3;
private static final int AUDIOPORT_EVENT_NEW_LISTENER = 4;
+ private static final long RESCHEDULE_MESSAGE_DELAY_MS = 100;
+
/**
* Accessed by native methods: JNI Callback context.
*/
@@ -51,11 +55,12 @@
if (mHandler != null) {
return;
}
- // find the looper for our new event handler
- Looper looper = Looper.getMainLooper();
+ // create a new thread for our new event handler
+ mHandlerThread = new HandlerThread(TAG);
+ mHandlerThread.start();
- if (looper != null) {
- mHandler = new Handler(looper) {
+ if (mHandlerThread.getLooper() != null) {
+ mHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
ArrayList<AudioManager.OnAudioPortUpdateListener> listeners;
@@ -86,6 +91,12 @@
if (msg.what != AUDIOPORT_EVENT_SERVICE_DIED) {
int status = AudioManager.updateAudioPortCache(ports, patches, null);
if (status != AudioManager.SUCCESS) {
+ // Since audio ports and audio patches are not null, the return
+ // value could be ERROR due to inconsistency between port generation
+ // and patch generation. In this case, we need to reschedule the
+ // message to make sure the native callback is done.
+ sendMessageDelayed(obtainMessage(msg.what, msg.obj),
+ RESCHEDULE_MESSAGE_DELAY_MS);
return;
}
}
@@ -132,6 +143,9 @@
@Override
protected void finalize() {
native_finalize();
+ if (mHandlerThread.isAlive()) {
+ mHandlerThread.quit();
+ }
}
private native void native_finalize();
@@ -168,6 +182,10 @@
Handler handler = eventHandler.handler();
if (handler != null) {
Message m = handler.obtainMessage(what, arg1, arg2, obj);
+ if (what != AUDIOPORT_EVENT_NEW_LISTENER) {
+ // Except AUDIOPORT_EVENT_NEW_LISTENER, we can only respect the last message.
+ handler.removeMessages(what);
+ }
handler.sendMessage(m);
}
}