OSDN Git Service

AudioSystem: new audioflinger restart detection
authorEric Laurent <elaurent@google.com>
Thu, 18 Jul 2013 21:41:39 +0000 (14:41 -0700)
committerEric Laurent <elaurent@google.com>
Tue, 20 Aug 2013 01:26:21 +0000 (18:26 -0700)
Add a specific method to AudioSystem for AudioService to poll
for AudioFlinger service restart instead of relying on current
callback mechanism which is flaky.

Bug: 9693068.
Change-Id: Id21d142a22b257205700201978cce1cb8b15180d

core/jni/android_media_AudioSystem.cpp
media/java/android/media/AudioService.java
media/java/android/media/AudioSystem.java

index 2c1440f..7d99464 100644 (file)
@@ -41,11 +41,15 @@ enum AudioError {
 
 static int check_AudioSystem_Command(status_t status)
 {
-    if (status == NO_ERROR) {
+    switch (status) {
+    case DEAD_OBJECT:
+        return kAudioStatusMediaServerDied;
+    case NO_ERROR:
         return kAudioStatusOk;
-    } else {
-        return kAudioStatusError;
+    default:
+        break;
     }
+    return kAudioStatusError;
 }
 
 static int
@@ -122,21 +126,9 @@ android_media_AudioSystem_error_callback(status_t err)
 
     jclass clazz = env->FindClass(kClassPathName);
 
-    int error;
-
-    switch (err) {
-    case DEAD_OBJECT:
-        error = kAudioStatusMediaServerDied;
-        break;
-    case NO_ERROR:
-        error = kAudioStatusOk;
-        break;
-    default:
-        error = kAudioStatusError;
-        break;
-    }
-
-    env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error);
+    env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
+                              "errorCallbackFromNative","(I)V"),
+                              check_AudioSystem_Command(err));
 }
 
 static int
@@ -283,6 +275,12 @@ android_media_AudioSystem_setLowRamDevice(JNIEnv *env, jobject clazz, jboolean i
     return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice);
 }
 
+static int
+android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
+{
+    return check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
@@ -310,6 +308,7 @@ static JNINativeMethod gMethods[] = {
     {"getPrimaryOutputFrameCount",   "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
     {"getOutputLatency",    "(I)I",     (void *)android_media_AudioSystem_getOutputLatency},
     {"setLowRamDevice",     "(Z)I",     (void *)android_media_AudioSystem_setLowRamDevice},
+    {"checkAudioFlinger",    "()I",     (void *)android_media_AudioSystem_checkAudioFlinger},
 };
 
 int register_android_media_AudioSystem(JNIEnv *env)
index 4814d6a..3478007 100644 (file)
@@ -140,23 +140,22 @@ public class AudioService extends IAudioService.Stub {
     private static final int MSG_PERSIST_MASTER_VOLUME = 2;
     private static final int MSG_PERSIST_RINGER_MODE = 3;
     private static final int MSG_MEDIA_SERVER_DIED = 4;
-    private static final int MSG_MEDIA_SERVER_STARTED = 5;
-    private static final int MSG_PLAY_SOUND_EFFECT = 6;
-    private static final int MSG_BTA2DP_DOCK_TIMEOUT = 7;
-    private static final int MSG_LOAD_SOUND_EFFECTS = 8;
-    private static final int MSG_SET_FORCE_USE = 9;
-    private static final int MSG_BT_HEADSET_CNCT_FAILED = 10;
-    private static final int MSG_SET_ALL_VOLUMES = 11;
-    private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 12;
-    private static final int MSG_REPORT_NEW_ROUTES = 13;
-    private static final int MSG_SET_FORCE_BT_A2DP_USE = 14;
-    private static final int MSG_CHECK_MUSIC_ACTIVE = 16;
-    private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 17;
-    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 18;
-    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 19;
-    private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 20;
-    private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 21;
-    private static final int MSG_UNLOAD_SOUND_EFFECTS = 22;
+    private static final int MSG_PLAY_SOUND_EFFECT = 5;
+    private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6;
+    private static final int MSG_LOAD_SOUND_EFFECTS = 7;
+    private static final int MSG_SET_FORCE_USE = 8;
+    private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
+    private static final int MSG_SET_ALL_VOLUMES = 10;
+    private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11;
+    private static final int MSG_REPORT_NEW_ROUTES = 12;
+    private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
+    private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
+    private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15;
+    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16;
+    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17;
+    private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18;
+    private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19;
+    private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -180,8 +179,6 @@ public class AudioService extends IAudioService.Stub {
     // protects mRingerMode
     private final Object mSettingsLock = new Object();
 
-    private boolean mMediaServerOk;
-
     private SoundPool mSoundPool;
     private final Object mSoundEffectsLock = new Object();
     private static final int NUM_SOUNDPOOL_CHANNELS = 4;
@@ -286,23 +283,13 @@ public class AudioService extends IAudioService.Stub {
         public void onError(int error) {
             switch (error) {
             case AudioSystem.AUDIO_STATUS_SERVER_DIED:
-                if (mMediaServerOk) {
-                    sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0,
-                            null, 1500);
-                    mMediaServerOk = false;
-                }
-                break;
-            case AudioSystem.AUDIO_STATUS_OK:
-                if (!mMediaServerOk) {
-                    sendMsg(mAudioHandler, MSG_MEDIA_SERVER_STARTED, SENDMSG_NOOP, 0, 0,
-                            null, 0);
-                    mMediaServerOk = true;
-                }
+                sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED,
+                        SENDMSG_NOOP, 0, 0, null, 0);
                 break;
             default:
                 break;
             }
-       }
+        }
     };
 
     /**
@@ -499,6 +486,8 @@ public class AudioService extends IAudioService.Stub {
         mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(),
                 mContext, /*VolumeController*/ mVolumePanel, this);
 
+        AudioSystem.setErrorCallback(mAudioSystemCallback);
+
         boolean cameraSoundForced = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_camera_sound_forced);
         mCameraSoundForced = new Boolean(cameraSoundForced);
@@ -528,15 +517,12 @@ public class AudioService extends IAudioService.Stub {
         createStreamStates();
 
         readAndSetLowRamDevice();
-        mMediaServerOk = true;
 
         // Call setRingerModeInt() to apply correct mute
         // state on streams affected by ringer mode.
         mRingerModeMutedStreams = 0;
         setRingerModeInt(getRingerMode(), false);
 
-        AudioSystem.setErrorCallback(mAudioSystemCallback);
-
         // Register for device connection intent broadcasts.
         IntentFilter intentFilter =
                 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
@@ -3432,21 +3418,17 @@ public class AudioService extends IAudioService.Stub {
                     break;
 
                 case MSG_MEDIA_SERVER_DIED:
-                    if (!mMediaServerOk) {
+                    if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) {
                         Log.e(TAG, "Media server died.");
-                        // Force creation of new IAudioFlinger interface so that we are notified
-                        // when new media_server process is back to life.
-                        AudioSystem.setErrorCallback(mAudioSystemCallback);
                         sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0,
                                 null, 500);
+                        break;
                     }
-                    break;
-
-                case MSG_MEDIA_SERVER_STARTED:
                     Log.e(TAG, "Media server started.");
+
                     // indicate to audio HAL that we start the reconfiguration phase after a media
                     // server crash
-                    // Note that MSG_MEDIA_SERVER_STARTED message is only received when the media server
+                    // Note that we only execute this when the media server
                     // process restarts after a crash, not the first time it is started.
                     AudioSystem.setParameters("restarting=true");
 
index 4805da5..661b0fd 100644 (file)
@@ -177,12 +177,10 @@ public class AudioSystem
     {
         synchronized (AudioSystem.class) {
             mErrorCallback = cb;
+            if (cb != null) {
+                cb.onError(checkAudioFlinger());
+            }
         }
-        // Calling a method on AudioFlinger here makes sure that we bind to IAudioFlinger
-        // binder interface death. Not doing that would result in not being notified of
-        // media_server process death if no other method is called on AudioSystem that reaches
-        // to AudioFlinger.
-        isMicrophoneMuted();
     }
 
     private static void errorCallbackFromNative(int error)
@@ -404,5 +402,5 @@ public class AudioSystem
     public static native int getOutputLatency(int stream);
 
     public static native int setLowRamDevice(boolean isLowRamDevice);
-
+    public static native int checkAudioFlinger();
 }