Loading src/com/android/server/telecom/Call.java +14 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.os.Looper; import android.os.RemoteException; import android.os.Trace; import android.provider.ContactsContract.Contacts; import android.telecom.CallAudioState; import android.telecom.Conference; import android.telecom.DisconnectCause; import android.telecom.Connection; Loading Loading @@ -323,6 +324,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable { private int mConnectionProperties; private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL; private boolean mIsConference = false; private final boolean mShouldAttachToExistingConnection; Loading Loading @@ -1092,6 +1095,16 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable { } } int getSupportedAudioRoutes() { return mSupportedAudioRoutes; } void setSupportedAudioRoutes(int audioRoutes) { if (mSupportedAudioRoutes != audioRoutes) { mSupportedAudioRoutes = audioRoutes; } } @VisibleForTesting public Call getParentCall() { return mParentCall; Loading Loading @@ -1216,6 +1229,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable { setConnectionCapabilities(connection.getConnectionCapabilities()); setConnectionProperties(connection.getConnectionProperties()); setSupportedAudioRoutes(connection.getSupportedAudioRoutes()); setVideoProvider(connection.getVideoProvider()); setVideoState(connection.getVideoState()); setRingbackRequested(connection.isRingbackRequested()); Loading src/com/android/server/telecom/CallAudioRouteStateMachine.java +66 −13 Original line number Diff line number Diff line Loading @@ -207,6 +207,16 @@ public class CallAudioRouteStateMachine extends StateMachine { Log.endSession(); } private int getCurrentCallSupportedRoutes() { int supportedRoutes = CallAudioState.ROUTE_ALL; if (mCallsManager.getForegroundCall() != null) { supportedRoutes &= mCallsManager.getForegroundCall().getSupportedAudioRoutes(); } return supportedRoutes; } abstract class AudioState extends State { @Override public void enter() { Loading @@ -224,31 +234,34 @@ public class CallAudioRouteStateMachine extends StateMachine { @Override public boolean processMessage(Message msg) { int addedRoutes = 0; int removedRoutes = 0; switch (msg.what) { case CONNECT_WIRED_HEADSET: Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE, "Wired headset connected"); mAvailableRoutes &= ~ROUTE_EARPIECE; mAvailableRoutes |= ROUTE_WIRED_HEADSET; return NOT_HANDLED; removedRoutes |= ROUTE_EARPIECE; addedRoutes |= ROUTE_WIRED_HEADSET; break; case CONNECT_BLUETOOTH: Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE, "Bluetooth connected"); mAvailableRoutes |= ROUTE_BLUETOOTH; return NOT_HANDLED; addedRoutes |= ROUTE_BLUETOOTH; break; case DISCONNECT_WIRED_HEADSET: Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE, "Wired headset disconnected"); mAvailableRoutes &= ~ROUTE_WIRED_HEADSET; removedRoutes |= ROUTE_WIRED_HEADSET; if (mDoesDeviceSupportEarpieceRoute) { mAvailableRoutes |= ROUTE_EARPIECE; addedRoutes |= ROUTE_EARPIECE; } return NOT_HANDLED; break; case DISCONNECT_BLUETOOTH: Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE, "Bluetooth disconnected"); mAvailableRoutes &= ~ROUTE_BLUETOOTH; return NOT_HANDLED; removedRoutes |= ROUTE_BLUETOOTH; break; case SWITCH_BASELINE_ROUTE: sendInternalMessage(calculateBaselineRouteMessage(false)); return HANDLED; Loading @@ -261,6 +274,14 @@ public class CallAudioRouteStateMachine extends StateMachine { default: return NOT_HANDLED; } if (addedRoutes != 0 || removedRoutes != 0) { mAvailableRoutes = modifyRoutes(mAvailableRoutes, removedRoutes, addedRoutes, true); mDeviceSupportedRoutes = modifyRoutes(mDeviceSupportedRoutes, removedRoutes, addedRoutes, false); } return NOT_HANDLED; } // Behavior will depend on whether the state is an active one or a quiescent one. Loading @@ -268,6 +289,18 @@ public class CallAudioRouteStateMachine extends StateMachine { abstract public boolean isActive(); } private int modifyRoutes(int base, int remove, int add, boolean considerCurrentCall) { base &= ~remove; if (considerCurrentCall) { add &= getCurrentCallSupportedRoutes(); } base |= add; return base; } class ActiveEarpieceRoute extends EarpieceRoute { @Override public String getName() { Loading Loading @@ -1114,6 +1147,7 @@ public class CallAudioRouteStateMachine extends StateMachine { * A few pieces of hidden state. Used to avoid exponential explosion of number of explicit * states */ private int mDeviceSupportedRoutes; private int mAvailableRoutes; private int mAudioFocusType; private boolean mWasOnSpeaker; Loading Loading @@ -1203,9 +1237,15 @@ public class CallAudioRouteStateMachine extends StateMachine { } public void initialize(CallAudioState initState) { if ((initState.getRoute() & getCurrentCallSupportedRoutes()) == 0) { Log.e(this, new IllegalArgumentException(), "Route " + initState.getRoute() + "specified when supported call routes are:" + getCurrentCallSupportedRoutes()); } mCurrentCallAudioState = initState; mLastKnownCallAudioState = initState; mAvailableRoutes = initState.getSupportedRouteMask(); mDeviceSupportedRoutes = initState.getSupportedRouteMask(); mAvailableRoutes = mDeviceSupportedRoutes; mIsMuted = initState.isMuted(); mWasOnSpeaker = false; Loading Loading @@ -1263,6 +1303,7 @@ public class CallAudioRouteStateMachine extends StateMachine { } return; case UPDATE_SYSTEM_AUDIO_ROUTE: updateRouteForForegroundCall(); resendSystemAudioState(); return; case RUN_RUNNABLE: Loading Loading @@ -1460,7 +1501,7 @@ public class CallAudioRouteStateMachine extends StateMachine { } private CallAudioState getInitialAudioState() { int supportedRouteMask = calculateSupportedRoutes(); int supportedRouteMask = calculateSupportedRoutes() & getCurrentCallSupportedRoutes(); final int route; if ((supportedRouteMask & ROUTE_BLUETOOTH) != 0) { Loading Loading @@ -1525,7 +1566,8 @@ public class CallAudioRouteStateMachine extends StateMachine { private void reinitialize() { CallAudioState initState = getInitialAudioState(); mAvailableRoutes = initState.getSupportedRouteMask(); mDeviceSupportedRoutes = initState.getSupportedRouteMask(); mAvailableRoutes = mDeviceSupportedRoutes & getCurrentCallSupportedRoutes(); mIsMuted = initState.isMuted(); setMuteOn(mIsMuted); mWasOnSpeaker = false; Loading @@ -1533,4 +1575,15 @@ public class CallAudioRouteStateMachine extends StateMachine { mLastKnownCallAudioState = initState; transitionTo(mRouteCodeToQuiescentState.get(initState.getRoute())); } private void updateRouteForForegroundCall() { mAvailableRoutes = mDeviceSupportedRoutes & getCurrentCallSupportedRoutes(); CallAudioState currentState = getCurrentCallAudioState(); // Move to baseline route in the case the current route is no longer available. if ((mAvailableRoutes & currentState.getRoute()) == 0) { sendInternalMessage(calculateBaselineRouteMessage(false)); } } } src/com/android/server/telecom/ParcelableCallUtils.java +3 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,8 @@ public class ParcelableCallUtils { } int capabilities = convertConnectionToCallCapabilities(call.getConnectionCapabilities()); int properties = convertConnectionToCallProperties(call.getConnectionProperties()); int supportedAudioRoutes = call.getSupportedAudioRoutes(); if (call.isConference()) { properties |= android.telecom.Call.Details.PROPERTY_CONFERENCE; } Loading Loading @@ -157,6 +159,7 @@ public class ParcelableCallUtils { call.getCannedSmsResponses(), capabilities, properties, supportedAudioRoutes, connectTimeMillis, handle, call.getHandlePresentation(), Loading src/com/android/server/telecom/PhoneAccountRegistrar.java +14 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.telecom.CallAudioState; import android.telecom.ConnectionService; import android.telecom.DefaultDialerManager; import android.telecom.Log; Loading Loading @@ -1508,6 +1509,7 @@ public class PhoneAccountRegistrar { private static final String ADDRESS = "handle"; private static final String SUBSCRIPTION_ADDRESS = "subscription_number"; private static final String CAPABILITIES = "capabilities"; private static final String SUPPORTED_AUDIO_ROUTES = "supported_audio_routes"; private static final String ICON_RES_ID = "icon_res_id"; private static final String ICON_PACKAGE_NAME = "icon_package_name"; private static final String ICON_BITMAP = "icon_bitmap"; Loading Loading @@ -1543,6 +1545,8 @@ public class PhoneAccountRegistrar { writeStringList(SUPPORTED_URI_SCHEMES, o.getSupportedUriSchemes(), serializer); writeBundle(EXTRAS, o.getExtras(), serializer); writeTextIfNonNull(ENABLED, o.isEnabled() ? "true" : "false" , serializer); writeTextIfNonNull(SUPPORTED_AUDIO_ROUTES, Integer.toString( o.getSupportedAudioRoutes()), serializer); serializer.endTag(null, CLASS_PHONE_ACCOUNT); } Loading @@ -1556,6 +1560,7 @@ public class PhoneAccountRegistrar { Uri address = null; Uri subscriptionAddress = null; int capabilities = 0; int supportedAudioRoutes = 0; int iconResId = PhoneAccount.NO_RESOURCE_ID; String iconPackageName = null; Bitmap iconBitmap = null; Loading Loading @@ -1614,6 +1619,9 @@ public class PhoneAccountRegistrar { enabled = "true".equalsIgnoreCase(parser.getText()); } else if (parser.getName().equals(EXTRAS)) { extras = readBundle(parser); } else if (parser.getName().equals(SUPPORTED_AUDIO_ROUTES)) { parser.next(); supportedAudioRoutes = Integer.parseInt(parser.getText()); } } Loading Loading @@ -1672,10 +1680,16 @@ public class PhoneAccountRegistrar { } } if (version < 9) { // Set supported audio routes to all by default supportedAudioRoutes = CallAudioState.ROUTE_ALL; } PhoneAccount.Builder builder = PhoneAccount.builder(accountHandle, label) .setAddress(address) .setSubscriptionAddress(subscriptionAddress) .setCapabilities(capabilities) .setSupportedAudioRoutes(supportedAudioRoutes) .setShortDescription(shortDescription) .setSupportedUriSchemes(supportedUriSchemes) .setHighlightColor(highlightColor) Loading tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java +2 −0 Original line number Diff line number Diff line Loading @@ -345,6 +345,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService> int addressPresentation; int capabilities; int properties; int supportedAudioRoutes; StatusHints statusHints; DisconnectCause disconnectCause; String conferenceId; Loading Loading @@ -609,6 +610,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService> c.state, c.capabilities, c.properties, c.supportedAudioRoutes, c.request.getAddress(), c.addressPresentation, c.callerDisplayName, Loading Loading
src/com/android/server/telecom/Call.java +14 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.os.Looper; import android.os.RemoteException; import android.os.Trace; import android.provider.ContactsContract.Contacts; import android.telecom.CallAudioState; import android.telecom.Conference; import android.telecom.DisconnectCause; import android.telecom.Connection; Loading Loading @@ -323,6 +324,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable { private int mConnectionProperties; private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL; private boolean mIsConference = false; private final boolean mShouldAttachToExistingConnection; Loading Loading @@ -1092,6 +1095,16 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable { } } int getSupportedAudioRoutes() { return mSupportedAudioRoutes; } void setSupportedAudioRoutes(int audioRoutes) { if (mSupportedAudioRoutes != audioRoutes) { mSupportedAudioRoutes = audioRoutes; } } @VisibleForTesting public Call getParentCall() { return mParentCall; Loading Loading @@ -1216,6 +1229,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable { setConnectionCapabilities(connection.getConnectionCapabilities()); setConnectionProperties(connection.getConnectionProperties()); setSupportedAudioRoutes(connection.getSupportedAudioRoutes()); setVideoProvider(connection.getVideoProvider()); setVideoState(connection.getVideoState()); setRingbackRequested(connection.isRingbackRequested()); Loading
src/com/android/server/telecom/CallAudioRouteStateMachine.java +66 −13 Original line number Diff line number Diff line Loading @@ -207,6 +207,16 @@ public class CallAudioRouteStateMachine extends StateMachine { Log.endSession(); } private int getCurrentCallSupportedRoutes() { int supportedRoutes = CallAudioState.ROUTE_ALL; if (mCallsManager.getForegroundCall() != null) { supportedRoutes &= mCallsManager.getForegroundCall().getSupportedAudioRoutes(); } return supportedRoutes; } abstract class AudioState extends State { @Override public void enter() { Loading @@ -224,31 +234,34 @@ public class CallAudioRouteStateMachine extends StateMachine { @Override public boolean processMessage(Message msg) { int addedRoutes = 0; int removedRoutes = 0; switch (msg.what) { case CONNECT_WIRED_HEADSET: Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE, "Wired headset connected"); mAvailableRoutes &= ~ROUTE_EARPIECE; mAvailableRoutes |= ROUTE_WIRED_HEADSET; return NOT_HANDLED; removedRoutes |= ROUTE_EARPIECE; addedRoutes |= ROUTE_WIRED_HEADSET; break; case CONNECT_BLUETOOTH: Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE, "Bluetooth connected"); mAvailableRoutes |= ROUTE_BLUETOOTH; return NOT_HANDLED; addedRoutes |= ROUTE_BLUETOOTH; break; case DISCONNECT_WIRED_HEADSET: Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE, "Wired headset disconnected"); mAvailableRoutes &= ~ROUTE_WIRED_HEADSET; removedRoutes |= ROUTE_WIRED_HEADSET; if (mDoesDeviceSupportEarpieceRoute) { mAvailableRoutes |= ROUTE_EARPIECE; addedRoutes |= ROUTE_EARPIECE; } return NOT_HANDLED; break; case DISCONNECT_BLUETOOTH: Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE, "Bluetooth disconnected"); mAvailableRoutes &= ~ROUTE_BLUETOOTH; return NOT_HANDLED; removedRoutes |= ROUTE_BLUETOOTH; break; case SWITCH_BASELINE_ROUTE: sendInternalMessage(calculateBaselineRouteMessage(false)); return HANDLED; Loading @@ -261,6 +274,14 @@ public class CallAudioRouteStateMachine extends StateMachine { default: return NOT_HANDLED; } if (addedRoutes != 0 || removedRoutes != 0) { mAvailableRoutes = modifyRoutes(mAvailableRoutes, removedRoutes, addedRoutes, true); mDeviceSupportedRoutes = modifyRoutes(mDeviceSupportedRoutes, removedRoutes, addedRoutes, false); } return NOT_HANDLED; } // Behavior will depend on whether the state is an active one or a quiescent one. Loading @@ -268,6 +289,18 @@ public class CallAudioRouteStateMachine extends StateMachine { abstract public boolean isActive(); } private int modifyRoutes(int base, int remove, int add, boolean considerCurrentCall) { base &= ~remove; if (considerCurrentCall) { add &= getCurrentCallSupportedRoutes(); } base |= add; return base; } class ActiveEarpieceRoute extends EarpieceRoute { @Override public String getName() { Loading Loading @@ -1114,6 +1147,7 @@ public class CallAudioRouteStateMachine extends StateMachine { * A few pieces of hidden state. Used to avoid exponential explosion of number of explicit * states */ private int mDeviceSupportedRoutes; private int mAvailableRoutes; private int mAudioFocusType; private boolean mWasOnSpeaker; Loading Loading @@ -1203,9 +1237,15 @@ public class CallAudioRouteStateMachine extends StateMachine { } public void initialize(CallAudioState initState) { if ((initState.getRoute() & getCurrentCallSupportedRoutes()) == 0) { Log.e(this, new IllegalArgumentException(), "Route " + initState.getRoute() + "specified when supported call routes are:" + getCurrentCallSupportedRoutes()); } mCurrentCallAudioState = initState; mLastKnownCallAudioState = initState; mAvailableRoutes = initState.getSupportedRouteMask(); mDeviceSupportedRoutes = initState.getSupportedRouteMask(); mAvailableRoutes = mDeviceSupportedRoutes; mIsMuted = initState.isMuted(); mWasOnSpeaker = false; Loading Loading @@ -1263,6 +1303,7 @@ public class CallAudioRouteStateMachine extends StateMachine { } return; case UPDATE_SYSTEM_AUDIO_ROUTE: updateRouteForForegroundCall(); resendSystemAudioState(); return; case RUN_RUNNABLE: Loading Loading @@ -1460,7 +1501,7 @@ public class CallAudioRouteStateMachine extends StateMachine { } private CallAudioState getInitialAudioState() { int supportedRouteMask = calculateSupportedRoutes(); int supportedRouteMask = calculateSupportedRoutes() & getCurrentCallSupportedRoutes(); final int route; if ((supportedRouteMask & ROUTE_BLUETOOTH) != 0) { Loading Loading @@ -1525,7 +1566,8 @@ public class CallAudioRouteStateMachine extends StateMachine { private void reinitialize() { CallAudioState initState = getInitialAudioState(); mAvailableRoutes = initState.getSupportedRouteMask(); mDeviceSupportedRoutes = initState.getSupportedRouteMask(); mAvailableRoutes = mDeviceSupportedRoutes & getCurrentCallSupportedRoutes(); mIsMuted = initState.isMuted(); setMuteOn(mIsMuted); mWasOnSpeaker = false; Loading @@ -1533,4 +1575,15 @@ public class CallAudioRouteStateMachine extends StateMachine { mLastKnownCallAudioState = initState; transitionTo(mRouteCodeToQuiescentState.get(initState.getRoute())); } private void updateRouteForForegroundCall() { mAvailableRoutes = mDeviceSupportedRoutes & getCurrentCallSupportedRoutes(); CallAudioState currentState = getCurrentCallAudioState(); // Move to baseline route in the case the current route is no longer available. if ((mAvailableRoutes & currentState.getRoute()) == 0) { sendInternalMessage(calculateBaselineRouteMessage(false)); } } }
src/com/android/server/telecom/ParcelableCallUtils.java +3 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,8 @@ public class ParcelableCallUtils { } int capabilities = convertConnectionToCallCapabilities(call.getConnectionCapabilities()); int properties = convertConnectionToCallProperties(call.getConnectionProperties()); int supportedAudioRoutes = call.getSupportedAudioRoutes(); if (call.isConference()) { properties |= android.telecom.Call.Details.PROPERTY_CONFERENCE; } Loading Loading @@ -157,6 +159,7 @@ public class ParcelableCallUtils { call.getCannedSmsResponses(), capabilities, properties, supportedAudioRoutes, connectTimeMillis, handle, call.getHandlePresentation(), Loading
src/com/android/server/telecom/PhoneAccountRegistrar.java +14 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.telecom.CallAudioState; import android.telecom.ConnectionService; import android.telecom.DefaultDialerManager; import android.telecom.Log; Loading Loading @@ -1508,6 +1509,7 @@ public class PhoneAccountRegistrar { private static final String ADDRESS = "handle"; private static final String SUBSCRIPTION_ADDRESS = "subscription_number"; private static final String CAPABILITIES = "capabilities"; private static final String SUPPORTED_AUDIO_ROUTES = "supported_audio_routes"; private static final String ICON_RES_ID = "icon_res_id"; private static final String ICON_PACKAGE_NAME = "icon_package_name"; private static final String ICON_BITMAP = "icon_bitmap"; Loading Loading @@ -1543,6 +1545,8 @@ public class PhoneAccountRegistrar { writeStringList(SUPPORTED_URI_SCHEMES, o.getSupportedUriSchemes(), serializer); writeBundle(EXTRAS, o.getExtras(), serializer); writeTextIfNonNull(ENABLED, o.isEnabled() ? "true" : "false" , serializer); writeTextIfNonNull(SUPPORTED_AUDIO_ROUTES, Integer.toString( o.getSupportedAudioRoutes()), serializer); serializer.endTag(null, CLASS_PHONE_ACCOUNT); } Loading @@ -1556,6 +1560,7 @@ public class PhoneAccountRegistrar { Uri address = null; Uri subscriptionAddress = null; int capabilities = 0; int supportedAudioRoutes = 0; int iconResId = PhoneAccount.NO_RESOURCE_ID; String iconPackageName = null; Bitmap iconBitmap = null; Loading Loading @@ -1614,6 +1619,9 @@ public class PhoneAccountRegistrar { enabled = "true".equalsIgnoreCase(parser.getText()); } else if (parser.getName().equals(EXTRAS)) { extras = readBundle(parser); } else if (parser.getName().equals(SUPPORTED_AUDIO_ROUTES)) { parser.next(); supportedAudioRoutes = Integer.parseInt(parser.getText()); } } Loading Loading @@ -1672,10 +1680,16 @@ public class PhoneAccountRegistrar { } } if (version < 9) { // Set supported audio routes to all by default supportedAudioRoutes = CallAudioState.ROUTE_ALL; } PhoneAccount.Builder builder = PhoneAccount.builder(accountHandle, label) .setAddress(address) .setSubscriptionAddress(subscriptionAddress) .setCapabilities(capabilities) .setSupportedAudioRoutes(supportedAudioRoutes) .setShortDescription(shortDescription) .setSupportedUriSchemes(supportedUriSchemes) .setHighlightColor(highlightColor) Loading
tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java +2 −0 Original line number Diff line number Diff line Loading @@ -345,6 +345,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService> int addressPresentation; int capabilities; int properties; int supportedAudioRoutes; StatusHints statusHints; DisconnectCause disconnectCause; String conferenceId; Loading Loading @@ -609,6 +610,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService> c.state, c.capabilities, c.properties, c.supportedAudioRoutes, c.request.getAddress(), c.addressPresentation, c.callerDisplayName, Loading