Loading services/core/java/com/android/server/audio/AudioDeviceBroker.java +63 −9 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.util.PrintWriterPrinter; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.server.audio.AudioService.BtCommDeviceActiveType; Loading Loading @@ -127,6 +128,10 @@ public class AudioDeviceBroker { // Delay before unmuting call after HFP device switch private static final int HFP_SWITCH_CALL_UNMUTE_DELAY_MS = 2000; // Delay before attempting to restore devices again after audioserver died and a previous // restore attempt failed private static final int DEVICE_RESTORE_TRY_AGAIN_DELAY_MS = 500; private final @NonNull AudioService mAudioService; private final @NonNull Context mContext; private final @NonNull AudioSystemAdapter mAudioSystem; Loading @@ -150,7 +155,6 @@ public class AudioDeviceBroker { // Adapter for system_server-reserved operations private final SystemServerAdapter mSystemServer; //------------------------------------------------------------------- // we use a different lock than mDeviceStateLock so as not to create // lock contention between enqueueing a message and handling them Loading @@ -161,6 +165,8 @@ public class AudioDeviceBroker { // General lock to be taken whenever the state of the audio devices is to be checked or changed private final Object mDeviceStateLock = new Object(); private final AtomicBoolean mWaitingForDeviceRestore = new AtomicBoolean(false); // Request to override default use of A2DP for media. private AtomicBoolean mBluetoothA2dpEnabled = new AtomicBoolean(false); Loading Loading @@ -242,6 +248,48 @@ public class AudioDeviceBroker { init(); } /** * Signals that device restoration is done or not after an audioserver restart. * Important: if modifying or adding a codepath using this API, be careful about the call * site as this is currently called from {@link AudioDeviceInventory#onRestoreDevices()} with * {@link AudioDeviceInventory#mDevicesLock} held, which can present a cross deadlock if * {@link #mDeviceStateLock} was not already held when calling onRestoreDevices. * @param waiting */ /*package*/ void setWaitingForDeviceRestore(boolean waiting) { Slog.i(TAG, "setWaitingForDeviceRestore " + waiting); synchronized (mDeviceStateLock) { if (!waiting) { // only allow to end the wait // - if there are no more server died messages in flight if (mAudioService.isHandlingAudioServerDeath()) { Slog.i(TAG, "not ready to stop waiting for device restore"); return; } // - if there are no more attempts to restore devices if (mBrokerHandler.hasMessages(MSG_RESTORE_DEVICES)) { return; } } mWaitingForDeviceRestore.set(waiting); } } /** * Returns whether audioserver has died and devices haven't been restored yet. * When true, new device connections (to APM) will not be attempted, and the connection will * be delayed until the device restore operation is started. * It is used inside * {@link AudioDeviceInventory#setApmDeviceConnectionAvailable(AudioDeviceAttributes, int, boolean)} * to check if a device can be made available to APM. * @return true if audioserver has died and the devices haven't been restored yet. False when * audioserver is up and running */ /*package*/ boolean isWaitingForDeviceRestore() { // lock-free reader relies on atomicity of update return mWaitingForDeviceRestore.get(); } private void initRoutingStrategyIds() { List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies(); mCommunicationStrategyId = -1; Loading Loading @@ -1912,15 +1960,21 @@ public class AudioDeviceBroker { synchronized (mDeviceStateLock) { initRoutingStrategyIds(); updateActiveCommunicationDevice(); mDeviceInventory.onRestoreDevices(); if (mDeviceInventory.onRestoreDevices()) { synchronized (mBluetoothAudioStateLock) { reapplyAudioHalBluetoothState(); } final int forceForMedia = getBluetoothA2dpEnabled() ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP; setForceUse_Async( AudioSystem.FOR_MEDIA, forceForMedia, "MSG_RESTORE_DEVICES"); AudioSystem.FOR_MEDIA, forceForMedia, "MSG_RESTORE_DEVICES"); updateCommunicationRoute("MSG_RESTORE_DEVICES"); } else { // device restoration failed and needs to be attempted again later sendMsg(MSG_RESTORE_DEVICES, SENDMSG_REPLACE, DEVICE_RESTORE_TRY_AGAIN_DELAY_MS); } } } break; Loading services/core/java/com/android/server/audio/AudioDeviceInventory.java +257 −117 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/audio/AudioService.java +20 −1 Original line number Diff line number Diff line Loading @@ -769,6 +769,10 @@ public class AudioService extends IAudioService.Stub public void onError(int error) { switch (error) { case AudioSystem.AUDIO_STATUS_SERVER_DIED: // do not handle device connections right now, tell AudioDeviceBroker // to just make note of connections, and wait for the device restoration // to complete after audioserver is back online mDeviceBroker.setWaitingForDeviceRestore(true); // check for null in case error callback is called during instance creation if (mRecordMonitor != null) { mRecordMonitor.onAudioServerDied(); Loading Loading @@ -2077,10 +2081,25 @@ public class AudioService extends IAudioService.Stub INDICATE_SYSTEM_READY_RETRY_DELAY_MS); } /** * Returns whether there are pending audioserver death messages * @return true if */ protected boolean isHandlingAudioServerDeath() { if (mAudioHandler.hasMessages(MSG_AUDIO_SERVER_DIED)) { return true; } if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) { return true; } return false; } public void onAudioServerDied() { if (!mSystemReady || (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) { Log.e(TAG, "Audioserver died."); sDeviceLogger.enqueueAndSlog("AudioService.onAudioServerDied", EventLogger.Event.ALOGE, TAG); sLifecycleLogger.enqueue(new EventLogger.StringEvent( "onAudioServerDied() audioserver died")); sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0, Loading Loading
services/core/java/com/android/server/audio/AudioDeviceBroker.java +63 −9 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.util.PrintWriterPrinter; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.server.audio.AudioService.BtCommDeviceActiveType; Loading Loading @@ -127,6 +128,10 @@ public class AudioDeviceBroker { // Delay before unmuting call after HFP device switch private static final int HFP_SWITCH_CALL_UNMUTE_DELAY_MS = 2000; // Delay before attempting to restore devices again after audioserver died and a previous // restore attempt failed private static final int DEVICE_RESTORE_TRY_AGAIN_DELAY_MS = 500; private final @NonNull AudioService mAudioService; private final @NonNull Context mContext; private final @NonNull AudioSystemAdapter mAudioSystem; Loading @@ -150,7 +155,6 @@ public class AudioDeviceBroker { // Adapter for system_server-reserved operations private final SystemServerAdapter mSystemServer; //------------------------------------------------------------------- // we use a different lock than mDeviceStateLock so as not to create // lock contention between enqueueing a message and handling them Loading @@ -161,6 +165,8 @@ public class AudioDeviceBroker { // General lock to be taken whenever the state of the audio devices is to be checked or changed private final Object mDeviceStateLock = new Object(); private final AtomicBoolean mWaitingForDeviceRestore = new AtomicBoolean(false); // Request to override default use of A2DP for media. private AtomicBoolean mBluetoothA2dpEnabled = new AtomicBoolean(false); Loading Loading @@ -242,6 +248,48 @@ public class AudioDeviceBroker { init(); } /** * Signals that device restoration is done or not after an audioserver restart. * Important: if modifying or adding a codepath using this API, be careful about the call * site as this is currently called from {@link AudioDeviceInventory#onRestoreDevices()} with * {@link AudioDeviceInventory#mDevicesLock} held, which can present a cross deadlock if * {@link #mDeviceStateLock} was not already held when calling onRestoreDevices. * @param waiting */ /*package*/ void setWaitingForDeviceRestore(boolean waiting) { Slog.i(TAG, "setWaitingForDeviceRestore " + waiting); synchronized (mDeviceStateLock) { if (!waiting) { // only allow to end the wait // - if there are no more server died messages in flight if (mAudioService.isHandlingAudioServerDeath()) { Slog.i(TAG, "not ready to stop waiting for device restore"); return; } // - if there are no more attempts to restore devices if (mBrokerHandler.hasMessages(MSG_RESTORE_DEVICES)) { return; } } mWaitingForDeviceRestore.set(waiting); } } /** * Returns whether audioserver has died and devices haven't been restored yet. * When true, new device connections (to APM) will not be attempted, and the connection will * be delayed until the device restore operation is started. * It is used inside * {@link AudioDeviceInventory#setApmDeviceConnectionAvailable(AudioDeviceAttributes, int, boolean)} * to check if a device can be made available to APM. * @return true if audioserver has died and the devices haven't been restored yet. False when * audioserver is up and running */ /*package*/ boolean isWaitingForDeviceRestore() { // lock-free reader relies on atomicity of update return mWaitingForDeviceRestore.get(); } private void initRoutingStrategyIds() { List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies(); mCommunicationStrategyId = -1; Loading Loading @@ -1912,15 +1960,21 @@ public class AudioDeviceBroker { synchronized (mDeviceStateLock) { initRoutingStrategyIds(); updateActiveCommunicationDevice(); mDeviceInventory.onRestoreDevices(); if (mDeviceInventory.onRestoreDevices()) { synchronized (mBluetoothAudioStateLock) { reapplyAudioHalBluetoothState(); } final int forceForMedia = getBluetoothA2dpEnabled() ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP; setForceUse_Async( AudioSystem.FOR_MEDIA, forceForMedia, "MSG_RESTORE_DEVICES"); AudioSystem.FOR_MEDIA, forceForMedia, "MSG_RESTORE_DEVICES"); updateCommunicationRoute("MSG_RESTORE_DEVICES"); } else { // device restoration failed and needs to be attempted again later sendMsg(MSG_RESTORE_DEVICES, SENDMSG_REPLACE, DEVICE_RESTORE_TRY_AGAIN_DELAY_MS); } } } break; Loading
services/core/java/com/android/server/audio/AudioDeviceInventory.java +257 −117 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/audio/AudioService.java +20 −1 Original line number Diff line number Diff line Loading @@ -769,6 +769,10 @@ public class AudioService extends IAudioService.Stub public void onError(int error) { switch (error) { case AudioSystem.AUDIO_STATUS_SERVER_DIED: // do not handle device connections right now, tell AudioDeviceBroker // to just make note of connections, and wait for the device restoration // to complete after audioserver is back online mDeviceBroker.setWaitingForDeviceRestore(true); // check for null in case error callback is called during instance creation if (mRecordMonitor != null) { mRecordMonitor.onAudioServerDied(); Loading Loading @@ -2077,10 +2081,25 @@ public class AudioService extends IAudioService.Stub INDICATE_SYSTEM_READY_RETRY_DELAY_MS); } /** * Returns whether there are pending audioserver death messages * @return true if */ protected boolean isHandlingAudioServerDeath() { if (mAudioHandler.hasMessages(MSG_AUDIO_SERVER_DIED)) { return true; } if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) { return true; } return false; } public void onAudioServerDied() { if (!mSystemReady || (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) { Log.e(TAG, "Audioserver died."); sDeviceLogger.enqueueAndSlog("AudioService.onAudioServerDied", EventLogger.Event.ALOGE, TAG); sLifecycleLogger.enqueue(new EventLogger.StringEvent( "onAudioServerDied() audioserver died")); sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0, Loading