Loading services/core/java/com/android/server/audio/AudioDeviceBroker.java +79 −63 Original line number Diff line number Diff line Loading @@ -300,7 +300,7 @@ public class AudioDeviceBroker { } postSetCommunicationDeviceForClient(new CommunicationDeviceInfo( cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""), on, BtHelper.SCO_MODE_UNDEFINED, eventSource, false, isPrivileged)); on, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged)); } /** Loading @@ -313,6 +313,11 @@ public class AudioDeviceBroker { private static final long SET_COMMUNICATION_DEVICE_TIMEOUT_MS = 3000; /** synchronization for setCommunicationDevice() and getCommunicationDevice */ private Object mCommunicationDeviceLock = new Object(); @GuardedBy("mCommunicationDeviceLock") private int mCommunicationDeviceUpdateCount = 0; /*package*/ boolean setCommunicationDevice(IBinder cb, int uid, AudioDeviceInfo device, boolean isPrivileged, String eventSource) { Loading @@ -320,29 +325,23 @@ public class AudioDeviceBroker { Log.v(TAG, "setCommunicationDevice, device: " + device + ", uid: " + uid); } synchronized (mDeviceStateLock) { if (device == null) { CommunicationRouteClient client = getCommunicationRouteClientForUid(uid); if (client == null) { return false; } } } synchronized (mCommunicationDeviceLock) { mCommunicationDeviceUpdateCount++; AudioDeviceAttributes deviceAttr = (device != null) ? new AudioDeviceAttributes(device) : null; CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo(cb, uid, deviceAttr, device != null, BtHelper.SCO_MODE_UNDEFINED, eventSource, true, isPrivileged); device != null, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged); postSetCommunicationDeviceForClient(deviceInfo); boolean status; synchronized (deviceInfo) { final long start = System.currentTimeMillis(); long elapsed = 0; while (deviceInfo.mWaitForStatus) { try { deviceInfo.wait(SET_COMMUNICATION_DEVICE_TIMEOUT_MS - elapsed); } catch (InterruptedException e) { elapsed = System.currentTimeMillis() - start; if (elapsed >= SET_COMMUNICATION_DEVICE_TIMEOUT_MS) { deviceInfo.mStatus = false; deviceInfo.mWaitForStatus = false; } } } status = deviceInfo.mStatus; } return status; return true; } /** Loading @@ -352,7 +351,7 @@ public class AudioDeviceBroker { * @return true if the communication device is set or reset */ @GuardedBy("mDeviceStateLock") /*package*/ boolean onSetCommunicationDeviceForClient(CommunicationDeviceInfo deviceInfo) { /*package*/ void onSetCommunicationDeviceForClient(CommunicationDeviceInfo deviceInfo) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "onSetCommunicationDeviceForClient: " + deviceInfo); } Loading @@ -360,14 +359,13 @@ public class AudioDeviceBroker { CommunicationRouteClient client = getCommunicationRouteClientForUid(deviceInfo.mUid); if (client == null || (deviceInfo.mDevice != null && !deviceInfo.mDevice.equals(client.getDevice()))) { return false; return; } } AudioDeviceAttributes device = deviceInfo.mOn ? deviceInfo.mDevice : null; setCommunicationRouteForClient(deviceInfo.mCb, deviceInfo.mUid, device, deviceInfo.mScoAudioMode, deviceInfo.mIsPrivileged, deviceInfo.mEventSource); return true; } @GuardedBy("mDeviceStateLock") Loading Loading @@ -536,7 +534,7 @@ public class AudioDeviceBroker { CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo( crc.getBinder(), crc.getUid(), device, false, BtHelper.SCO_MODE_UNDEFINED, "onCheckCommunicationDeviceRemoval", false, crc.isPrivileged()); crc.isPrivileged()); postSetCommunicationDeviceForClient(deviceInfo); } } Loading Loading @@ -619,7 +617,30 @@ public class AudioDeviceBroker { * @return AudioDeviceInfo the requested device for communication. */ /* package */ AudioDeviceInfo getCommunicationDevice() { synchronized (mCommunicationDeviceLock) { final long start = System.currentTimeMillis(); long elapsed = 0; while (mCommunicationDeviceUpdateCount > 0) { try { mCommunicationDeviceLock.wait( SET_COMMUNICATION_DEVICE_TIMEOUT_MS - elapsed); } catch (InterruptedException e) { Log.w(TAG, "Interrupted while waiting for communication device update."); } elapsed = System.currentTimeMillis() - start; if (elapsed >= SET_COMMUNICATION_DEVICE_TIMEOUT_MS) { Log.e(TAG, "Timeout waiting for communication device update."); break; } } } synchronized (mDeviceStateLock) { return getCommunicationDeviceInt(); } } @GuardedBy("mDeviceStateLock") private AudioDeviceInfo getCommunicationDeviceInt() { updateActiveCommunicationDevice(); AudioDeviceInfo device = mActiveCommunicationDevice; // make sure we return a valid communication device (i.e. a device that is allowed by Loading @@ -645,7 +666,6 @@ public class AudioDeviceBroker { } return device; } } /** * Updates currently active communication device (mActiveCommunicationDevice). Loading Loading @@ -1218,7 +1238,7 @@ public class AudioDeviceBroker { } postSetCommunicationDeviceForClient(new CommunicationDeviceInfo( cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""), true, scoAudioMode, eventSource, false, isPrivileged)); true, scoAudioMode, eventSource, isPrivileged)); } /*package*/ void stopBluetoothScoForClient( Loading @@ -1229,7 +1249,7 @@ public class AudioDeviceBroker { } postSetCommunicationDeviceForClient(new CommunicationDeviceInfo( cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""), false, BtHelper.SCO_MODE_UNDEFINED, eventSource, false, isPrivileged)); false, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged)); } /*package*/ int setPreferredDevicesForStrategySync(int strategy, Loading Loading @@ -1316,7 +1336,7 @@ public class AudioDeviceBroker { @GuardedBy("mDeviceStateLock") private void dispatchCommunicationDevice() { AudioDeviceInfo device = getCommunicationDevice(); AudioDeviceInfo device = getCommunicationDeviceInt(); int portId = device != null ? device.getId() : 0; if (portId == mCurCommunicationPortId) { return; Loading Loading @@ -1500,12 +1520,10 @@ public class AudioDeviceBroker { final int mScoAudioMode; // only used for SCO: requested audio mode final boolean mIsPrivileged; // true if the client app has MODIFY_PHONE_STATE permission final @NonNull String mEventSource; // caller identifier for logging boolean mWaitForStatus; // true if the caller waits for a completion status (API dependent) boolean mStatus = false; // completion status only used if mWaitForStatus is true CommunicationDeviceInfo(@NonNull IBinder cb, int uid, @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode, @NonNull String eventSource, boolean waitForStatus, boolean isPrivileged) { @NonNull String eventSource, boolean isPrivileged) { mCb = cb; mUid = uid; mDevice = device; Loading @@ -1513,7 +1531,6 @@ public class AudioDeviceBroker { mScoAudioMode = scoAudioMode; mIsPrivileged = isPrivileged; mEventSource = eventSource; mWaitForStatus = waitForStatus; } // redefine equality op so we can match messages intended for this client Loading Loading @@ -1541,9 +1558,7 @@ public class AudioDeviceBroker { + " mOn=" + mOn + " mScoAudioMode=" + mScoAudioMode + " mIsPrivileged=" + mIsPrivileged + " mEventSource=" + mEventSource + " mWaitForStatus=" + mWaitForStatus + " mStatus=" + mStatus; + " mEventSource=" + mEventSource; } } Loading Loading @@ -1882,18 +1897,19 @@ public class AudioDeviceBroker { case MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT: CommunicationDeviceInfo deviceInfo = (CommunicationDeviceInfo) msg.obj; boolean status; synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { status = onSetCommunicationDeviceForClient(deviceInfo); onSetCommunicationDeviceForClient(deviceInfo); } } synchronized (deviceInfo) { if (deviceInfo.mWaitForStatus) { deviceInfo.mStatus = status; deviceInfo.mWaitForStatus = false; deviceInfo.notify(); synchronized (mCommunicationDeviceLock) { if (mCommunicationDeviceUpdateCount > 0) { mCommunicationDeviceUpdateCount--; } else { Log.e(TAG, "mCommunicationDeviceUpdateCount already 0 in" + " MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT"); } mCommunicationDeviceLock.notify(); } break; Loading Loading
services/core/java/com/android/server/audio/AudioDeviceBroker.java +79 −63 Original line number Diff line number Diff line Loading @@ -300,7 +300,7 @@ public class AudioDeviceBroker { } postSetCommunicationDeviceForClient(new CommunicationDeviceInfo( cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""), on, BtHelper.SCO_MODE_UNDEFINED, eventSource, false, isPrivileged)); on, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged)); } /** Loading @@ -313,6 +313,11 @@ public class AudioDeviceBroker { private static final long SET_COMMUNICATION_DEVICE_TIMEOUT_MS = 3000; /** synchronization for setCommunicationDevice() and getCommunicationDevice */ private Object mCommunicationDeviceLock = new Object(); @GuardedBy("mCommunicationDeviceLock") private int mCommunicationDeviceUpdateCount = 0; /*package*/ boolean setCommunicationDevice(IBinder cb, int uid, AudioDeviceInfo device, boolean isPrivileged, String eventSource) { Loading @@ -320,29 +325,23 @@ public class AudioDeviceBroker { Log.v(TAG, "setCommunicationDevice, device: " + device + ", uid: " + uid); } synchronized (mDeviceStateLock) { if (device == null) { CommunicationRouteClient client = getCommunicationRouteClientForUid(uid); if (client == null) { return false; } } } synchronized (mCommunicationDeviceLock) { mCommunicationDeviceUpdateCount++; AudioDeviceAttributes deviceAttr = (device != null) ? new AudioDeviceAttributes(device) : null; CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo(cb, uid, deviceAttr, device != null, BtHelper.SCO_MODE_UNDEFINED, eventSource, true, isPrivileged); device != null, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged); postSetCommunicationDeviceForClient(deviceInfo); boolean status; synchronized (deviceInfo) { final long start = System.currentTimeMillis(); long elapsed = 0; while (deviceInfo.mWaitForStatus) { try { deviceInfo.wait(SET_COMMUNICATION_DEVICE_TIMEOUT_MS - elapsed); } catch (InterruptedException e) { elapsed = System.currentTimeMillis() - start; if (elapsed >= SET_COMMUNICATION_DEVICE_TIMEOUT_MS) { deviceInfo.mStatus = false; deviceInfo.mWaitForStatus = false; } } } status = deviceInfo.mStatus; } return status; return true; } /** Loading @@ -352,7 +351,7 @@ public class AudioDeviceBroker { * @return true if the communication device is set or reset */ @GuardedBy("mDeviceStateLock") /*package*/ boolean onSetCommunicationDeviceForClient(CommunicationDeviceInfo deviceInfo) { /*package*/ void onSetCommunicationDeviceForClient(CommunicationDeviceInfo deviceInfo) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "onSetCommunicationDeviceForClient: " + deviceInfo); } Loading @@ -360,14 +359,13 @@ public class AudioDeviceBroker { CommunicationRouteClient client = getCommunicationRouteClientForUid(deviceInfo.mUid); if (client == null || (deviceInfo.mDevice != null && !deviceInfo.mDevice.equals(client.getDevice()))) { return false; return; } } AudioDeviceAttributes device = deviceInfo.mOn ? deviceInfo.mDevice : null; setCommunicationRouteForClient(deviceInfo.mCb, deviceInfo.mUid, device, deviceInfo.mScoAudioMode, deviceInfo.mIsPrivileged, deviceInfo.mEventSource); return true; } @GuardedBy("mDeviceStateLock") Loading Loading @@ -536,7 +534,7 @@ public class AudioDeviceBroker { CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo( crc.getBinder(), crc.getUid(), device, false, BtHelper.SCO_MODE_UNDEFINED, "onCheckCommunicationDeviceRemoval", false, crc.isPrivileged()); crc.isPrivileged()); postSetCommunicationDeviceForClient(deviceInfo); } } Loading Loading @@ -619,7 +617,30 @@ public class AudioDeviceBroker { * @return AudioDeviceInfo the requested device for communication. */ /* package */ AudioDeviceInfo getCommunicationDevice() { synchronized (mCommunicationDeviceLock) { final long start = System.currentTimeMillis(); long elapsed = 0; while (mCommunicationDeviceUpdateCount > 0) { try { mCommunicationDeviceLock.wait( SET_COMMUNICATION_DEVICE_TIMEOUT_MS - elapsed); } catch (InterruptedException e) { Log.w(TAG, "Interrupted while waiting for communication device update."); } elapsed = System.currentTimeMillis() - start; if (elapsed >= SET_COMMUNICATION_DEVICE_TIMEOUT_MS) { Log.e(TAG, "Timeout waiting for communication device update."); break; } } } synchronized (mDeviceStateLock) { return getCommunicationDeviceInt(); } } @GuardedBy("mDeviceStateLock") private AudioDeviceInfo getCommunicationDeviceInt() { updateActiveCommunicationDevice(); AudioDeviceInfo device = mActiveCommunicationDevice; // make sure we return a valid communication device (i.e. a device that is allowed by Loading @@ -645,7 +666,6 @@ public class AudioDeviceBroker { } return device; } } /** * Updates currently active communication device (mActiveCommunicationDevice). Loading Loading @@ -1218,7 +1238,7 @@ public class AudioDeviceBroker { } postSetCommunicationDeviceForClient(new CommunicationDeviceInfo( cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""), true, scoAudioMode, eventSource, false, isPrivileged)); true, scoAudioMode, eventSource, isPrivileged)); } /*package*/ void stopBluetoothScoForClient( Loading @@ -1229,7 +1249,7 @@ public class AudioDeviceBroker { } postSetCommunicationDeviceForClient(new CommunicationDeviceInfo( cb, uid, new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""), false, BtHelper.SCO_MODE_UNDEFINED, eventSource, false, isPrivileged)); false, BtHelper.SCO_MODE_UNDEFINED, eventSource, isPrivileged)); } /*package*/ int setPreferredDevicesForStrategySync(int strategy, Loading Loading @@ -1316,7 +1336,7 @@ public class AudioDeviceBroker { @GuardedBy("mDeviceStateLock") private void dispatchCommunicationDevice() { AudioDeviceInfo device = getCommunicationDevice(); AudioDeviceInfo device = getCommunicationDeviceInt(); int portId = device != null ? device.getId() : 0; if (portId == mCurCommunicationPortId) { return; Loading Loading @@ -1500,12 +1520,10 @@ public class AudioDeviceBroker { final int mScoAudioMode; // only used for SCO: requested audio mode final boolean mIsPrivileged; // true if the client app has MODIFY_PHONE_STATE permission final @NonNull String mEventSource; // caller identifier for logging boolean mWaitForStatus; // true if the caller waits for a completion status (API dependent) boolean mStatus = false; // completion status only used if mWaitForStatus is true CommunicationDeviceInfo(@NonNull IBinder cb, int uid, @Nullable AudioDeviceAttributes device, boolean on, int scoAudioMode, @NonNull String eventSource, boolean waitForStatus, boolean isPrivileged) { @NonNull String eventSource, boolean isPrivileged) { mCb = cb; mUid = uid; mDevice = device; Loading @@ -1513,7 +1531,6 @@ public class AudioDeviceBroker { mScoAudioMode = scoAudioMode; mIsPrivileged = isPrivileged; mEventSource = eventSource; mWaitForStatus = waitForStatus; } // redefine equality op so we can match messages intended for this client Loading Loading @@ -1541,9 +1558,7 @@ public class AudioDeviceBroker { + " mOn=" + mOn + " mScoAudioMode=" + mScoAudioMode + " mIsPrivileged=" + mIsPrivileged + " mEventSource=" + mEventSource + " mWaitForStatus=" + mWaitForStatus + " mStatus=" + mStatus; + " mEventSource=" + mEventSource; } } Loading Loading @@ -1882,18 +1897,19 @@ public class AudioDeviceBroker { case MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT: CommunicationDeviceInfo deviceInfo = (CommunicationDeviceInfo) msg.obj; boolean status; synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { status = onSetCommunicationDeviceForClient(deviceInfo); onSetCommunicationDeviceForClient(deviceInfo); } } synchronized (deviceInfo) { if (deviceInfo.mWaitForStatus) { deviceInfo.mStatus = status; deviceInfo.mWaitForStatus = false; deviceInfo.notify(); synchronized (mCommunicationDeviceLock) { if (mCommunicationDeviceUpdateCount > 0) { mCommunicationDeviceUpdateCount--; } else { Log.e(TAG, "mCommunicationDeviceUpdateCount already 0 in" + " MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT"); } mCommunicationDeviceLock.notify(); } break; Loading