Loading src/com/android/server/telecom/Call.java +21 −4 Original line number Diff line number Diff line Loading @@ -1250,6 +1250,23 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, return mIsVideoCallingSupportedByPhoneAccount; } /** * Sets whether video calling is supported by the current phone account. Since video support * can change during a call, this method facilitates updating call video state. * @param isVideoCallingSupported Sets whether video calling is supported. */ public void setVideoCallingSupportedByPhoneAccount(boolean isVideoCallingSupported) { if (mIsVideoCallingSupportedByPhoneAccount == isVideoCallingSupported) { return; } Log.i(this, "setVideoCallingSupportedByPhoneAccount: isSupp=%b", isVideoCallingSupported); mIsVideoCallingSupportedByPhoneAccount = isVideoCallingSupported; // Force an update of the connection capabilities so that the dialer is informed of the new // video capabilities based on the phone account's support for video. setConnectionCapabilities(getConnectionCapabilities(), true /* force */); } /** * @return {@code true} if the {@link Call} locally supports video. */ Loading Loading @@ -1363,8 +1380,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } PhoneAccount phoneAccount = phoneAccountRegistrar.getPhoneAccountUnchecked(mTargetPhoneAccountHandle); mIsVideoCallingSupportedByPhoneAccount = phoneAccount != null && phoneAccount.hasCapabilities( PhoneAccount.CAPABILITY_VIDEO_CALLING); mIsVideoCallingSupportedByPhoneAccount = phoneAccount != null && phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING); if (!mIsVideoCallingSupportedByPhoneAccount && VideoProfile.isVideo(getVideoState())) { // The PhoneAccount for the Call was set to one which does not support video calling, Loading Loading @@ -1455,7 +1472,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, mConnectElapsedTimeMillis = connectElapsedTimeMillis; } int getConnectionCapabilities() { public int getConnectionCapabilities() { return mConnectionCapabilities; } Loading @@ -1463,7 +1480,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, return mConnectionProperties; } void setConnectionCapabilities(int connectionCapabilities) { public void setConnectionCapabilities(int connectionCapabilities) { setConnectionCapabilities(connectionCapabilities, false /* forceUpdate */); } Loading src/com/android/server/telecom/CallsManager.java +30 −0 Original line number Diff line number Diff line Loading @@ -340,6 +340,12 @@ public class CallsManager extends Call.ListenerBase PhoneAccountHandle handle) { broadcastUnregisterIntent(handle); } @Override public void onPhoneAccountChanged(PhoneAccountRegistrar registrar, PhoneAccount phoneAccount) { handlePhoneAccountChanged(registrar, phoneAccount); } }; /** Loading Loading @@ -924,6 +930,11 @@ public class CallsManager extends Call.ListenerBase return mEmergencyCallHelper; } @VisibleForTesting public PhoneAccountRegistrar.Listener getPhoneAccountListener() { return mPhoneAccountListener; } @VisibleForTesting public boolean hasEmergencyCall() { for (Call call : mCalls) { Loading Loading @@ -4461,4 +4472,23 @@ public class CallsManager extends Call.ListenerBase errorIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(errorIntent, UserHandle.CURRENT); } /** * Handles changes to a {@link PhoneAccount}. * * Checks for changes to video calling availability and updates whether calls for that phone * account are video capable. * * @param registrar The {@link PhoneAccountRegistrar} originating the change. * @param phoneAccount The {@link PhoneAccount} which changed. */ private void handlePhoneAccountChanged(PhoneAccountRegistrar registrar, PhoneAccount phoneAccount) { Log.i(this, "handlePhoneAccountChanged: phoneAccount=%s", phoneAccount); boolean isVideoNowSupported = phoneAccount.hasCapabilities( PhoneAccount.CAPABILITY_VIDEO_CALLING); mCalls.stream() .filter(c -> phoneAccount.getAccountHandle().equals(c.getTargetPhoneAccount())) .forEach(c -> c.setVideoCallingSupportedByPhoneAccount(isVideoNowSupported)); } } src/com/android/server/telecom/PhoneAccountRegistrar.java +10 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,8 @@ public class PhoneAccountRegistrar { PhoneAccountHandle handle) {} public void onPhoneAccountUnRegistered(PhoneAccountRegistrar registrar, PhoneAccountHandle handle) {} public void onPhoneAccountChanged(PhoneAccountRegistrar registrar, PhoneAccount phoneAccount) {} } /** Loading Loading @@ -743,6 +745,8 @@ public class PhoneAccountRegistrar { fireAccountsChanged(); if (isNewAccount) { fireAccountRegistered(account.getAccountHandle()); } else { fireAccountChanged(account); } } Loading Loading @@ -804,6 +808,12 @@ public class PhoneAccountRegistrar { } } private void fireAccountChanged(PhoneAccount account) { for (Listener l : mListeners) { l.onPhoneAccountChanged(this, account); } } private void fireAccountUnRegistered(PhoneAccountHandle handle) { for (Listener l : mListeners) { l.onPhoneAccountUnRegistered(this, handle); Loading tests/src/com/android/server/telecom/tests/CallsManagerTest.java +66 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.telecom.tests; import static junit.framework.TestCase.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; Loading Loading @@ -102,9 +104,12 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @RunWith(JUnit4.class) public class CallsManagerTest extends TelecomTestCase { private static final int TEST_TIMEOUT = 5000; // milliseconds private static final PhoneAccountHandle SIM_1_HANDLE = new PhoneAccountHandle( ComponentName.unflattenFromString("com.foo/.Blah"), "Sim1"); private static final PhoneAccountHandle SIM_2_HANDLE = new PhoneAccountHandle( Loading Loading @@ -960,6 +965,67 @@ public class CallsManagerTest extends TelecomTestCase { assertTrue(mCallsManager.isInEmergencyCall()); } /** * Verifies that changes to a {@link PhoneAccount}'s * {@link PhoneAccount#CAPABILITY_VIDEO_CALLING} capability will be reflected on a call. * @throws Exception */ @SmallTest @Test public void testPhoneAccountVideoAvailability() throws InterruptedException { Call ongoingCall = addSpyCall(); // adds to SIM_2_ACCT LinkedBlockingQueue<Integer> capabilitiesQueue = new LinkedBlockingQueue<>(1); ongoingCall.addListener(new Call.ListenerBase() { @Override public void onConnectionCapabilitiesChanged(Call call) { try { Log.i("TYLER", "Listener got " + call.getConnectionCapabilities()); capabilitiesQueue.put(call.getConnectionCapabilities()); } catch (InterruptedException e) { fail(); } } }); // Lets make the phone account video capable. PhoneAccount videoCapableAccount = new PhoneAccount.Builder(SIM_2_ACCOUNT) .setCapabilities(SIM_2_ACCOUNT.getCapabilities() | PhoneAccount.CAPABILITY_VIDEO_CALLING) .build(); mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar, videoCapableAccount); // Absorb first update; it'll be from when phone account changed initially (since we force // a capabilities update. int newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS); // Lets pretend the ConnectionService made it video capable as well. ongoingCall.setConnectionCapabilities( Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL); newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS); assertTrue(Connection.can(newCapabilities, Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)); assertTrue(ongoingCall.isVideoCallingSupportedByPhoneAccount()); // Fire a changed event for the phone account making it not capable. mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar, SIM_2_ACCOUNT); newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS); assertFalse(Connection.can(newCapabilities, Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)); assertFalse(ongoingCall.isVideoCallingSupportedByPhoneAccount()); // Fire a change for an unrelated phone account. PhoneAccount anotherVideoCapableAcct = new PhoneAccount.Builder(SIM_1_ACCOUNT) .setCapabilities(SIM_2_ACCOUNT.getCapabilities() | PhoneAccount.CAPABILITY_VIDEO_CALLING) .build(); mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar, anotherVideoCapableAcct); // Call still should not be video capable assertFalse(Connection.can(ongoingCall.getConnectionCapabilities(), Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)); } private Call addSpyCallWithConnectionService(ConnectionServiceWrapper connSvr) { Call call = addSpyCall(); doReturn(connSvr).when(call).getConnectionService(); Loading Loading
src/com/android/server/telecom/Call.java +21 −4 Original line number Diff line number Diff line Loading @@ -1250,6 +1250,23 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, return mIsVideoCallingSupportedByPhoneAccount; } /** * Sets whether video calling is supported by the current phone account. Since video support * can change during a call, this method facilitates updating call video state. * @param isVideoCallingSupported Sets whether video calling is supported. */ public void setVideoCallingSupportedByPhoneAccount(boolean isVideoCallingSupported) { if (mIsVideoCallingSupportedByPhoneAccount == isVideoCallingSupported) { return; } Log.i(this, "setVideoCallingSupportedByPhoneAccount: isSupp=%b", isVideoCallingSupported); mIsVideoCallingSupportedByPhoneAccount = isVideoCallingSupported; // Force an update of the connection capabilities so that the dialer is informed of the new // video capabilities based on the phone account's support for video. setConnectionCapabilities(getConnectionCapabilities(), true /* force */); } /** * @return {@code true} if the {@link Call} locally supports video. */ Loading Loading @@ -1363,8 +1380,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } PhoneAccount phoneAccount = phoneAccountRegistrar.getPhoneAccountUnchecked(mTargetPhoneAccountHandle); mIsVideoCallingSupportedByPhoneAccount = phoneAccount != null && phoneAccount.hasCapabilities( PhoneAccount.CAPABILITY_VIDEO_CALLING); mIsVideoCallingSupportedByPhoneAccount = phoneAccount != null && phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING); if (!mIsVideoCallingSupportedByPhoneAccount && VideoProfile.isVideo(getVideoState())) { // The PhoneAccount for the Call was set to one which does not support video calling, Loading Loading @@ -1455,7 +1472,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, mConnectElapsedTimeMillis = connectElapsedTimeMillis; } int getConnectionCapabilities() { public int getConnectionCapabilities() { return mConnectionCapabilities; } Loading @@ -1463,7 +1480,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, return mConnectionProperties; } void setConnectionCapabilities(int connectionCapabilities) { public void setConnectionCapabilities(int connectionCapabilities) { setConnectionCapabilities(connectionCapabilities, false /* forceUpdate */); } Loading
src/com/android/server/telecom/CallsManager.java +30 −0 Original line number Diff line number Diff line Loading @@ -340,6 +340,12 @@ public class CallsManager extends Call.ListenerBase PhoneAccountHandle handle) { broadcastUnregisterIntent(handle); } @Override public void onPhoneAccountChanged(PhoneAccountRegistrar registrar, PhoneAccount phoneAccount) { handlePhoneAccountChanged(registrar, phoneAccount); } }; /** Loading Loading @@ -924,6 +930,11 @@ public class CallsManager extends Call.ListenerBase return mEmergencyCallHelper; } @VisibleForTesting public PhoneAccountRegistrar.Listener getPhoneAccountListener() { return mPhoneAccountListener; } @VisibleForTesting public boolean hasEmergencyCall() { for (Call call : mCalls) { Loading Loading @@ -4461,4 +4472,23 @@ public class CallsManager extends Call.ListenerBase errorIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(errorIntent, UserHandle.CURRENT); } /** * Handles changes to a {@link PhoneAccount}. * * Checks for changes to video calling availability and updates whether calls for that phone * account are video capable. * * @param registrar The {@link PhoneAccountRegistrar} originating the change. * @param phoneAccount The {@link PhoneAccount} which changed. */ private void handlePhoneAccountChanged(PhoneAccountRegistrar registrar, PhoneAccount phoneAccount) { Log.i(this, "handlePhoneAccountChanged: phoneAccount=%s", phoneAccount); boolean isVideoNowSupported = phoneAccount.hasCapabilities( PhoneAccount.CAPABILITY_VIDEO_CALLING); mCalls.stream() .filter(c -> phoneAccount.getAccountHandle().equals(c.getTargetPhoneAccount())) .forEach(c -> c.setVideoCallingSupportedByPhoneAccount(isVideoNowSupported)); } }
src/com/android/server/telecom/PhoneAccountRegistrar.java +10 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,8 @@ public class PhoneAccountRegistrar { PhoneAccountHandle handle) {} public void onPhoneAccountUnRegistered(PhoneAccountRegistrar registrar, PhoneAccountHandle handle) {} public void onPhoneAccountChanged(PhoneAccountRegistrar registrar, PhoneAccount phoneAccount) {} } /** Loading Loading @@ -743,6 +745,8 @@ public class PhoneAccountRegistrar { fireAccountsChanged(); if (isNewAccount) { fireAccountRegistered(account.getAccountHandle()); } else { fireAccountChanged(account); } } Loading Loading @@ -804,6 +808,12 @@ public class PhoneAccountRegistrar { } } private void fireAccountChanged(PhoneAccount account) { for (Listener l : mListeners) { l.onPhoneAccountChanged(this, account); } } private void fireAccountUnRegistered(PhoneAccountHandle handle) { for (Listener l : mListeners) { l.onPhoneAccountUnRegistered(this, handle); Loading
tests/src/com/android/server/telecom/tests/CallsManagerTest.java +66 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.telecom.tests; import static junit.framework.TestCase.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; Loading Loading @@ -102,9 +104,12 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @RunWith(JUnit4.class) public class CallsManagerTest extends TelecomTestCase { private static final int TEST_TIMEOUT = 5000; // milliseconds private static final PhoneAccountHandle SIM_1_HANDLE = new PhoneAccountHandle( ComponentName.unflattenFromString("com.foo/.Blah"), "Sim1"); private static final PhoneAccountHandle SIM_2_HANDLE = new PhoneAccountHandle( Loading Loading @@ -960,6 +965,67 @@ public class CallsManagerTest extends TelecomTestCase { assertTrue(mCallsManager.isInEmergencyCall()); } /** * Verifies that changes to a {@link PhoneAccount}'s * {@link PhoneAccount#CAPABILITY_VIDEO_CALLING} capability will be reflected on a call. * @throws Exception */ @SmallTest @Test public void testPhoneAccountVideoAvailability() throws InterruptedException { Call ongoingCall = addSpyCall(); // adds to SIM_2_ACCT LinkedBlockingQueue<Integer> capabilitiesQueue = new LinkedBlockingQueue<>(1); ongoingCall.addListener(new Call.ListenerBase() { @Override public void onConnectionCapabilitiesChanged(Call call) { try { Log.i("TYLER", "Listener got " + call.getConnectionCapabilities()); capabilitiesQueue.put(call.getConnectionCapabilities()); } catch (InterruptedException e) { fail(); } } }); // Lets make the phone account video capable. PhoneAccount videoCapableAccount = new PhoneAccount.Builder(SIM_2_ACCOUNT) .setCapabilities(SIM_2_ACCOUNT.getCapabilities() | PhoneAccount.CAPABILITY_VIDEO_CALLING) .build(); mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar, videoCapableAccount); // Absorb first update; it'll be from when phone account changed initially (since we force // a capabilities update. int newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS); // Lets pretend the ConnectionService made it video capable as well. ongoingCall.setConnectionCapabilities( Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL); newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS); assertTrue(Connection.can(newCapabilities, Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)); assertTrue(ongoingCall.isVideoCallingSupportedByPhoneAccount()); // Fire a changed event for the phone account making it not capable. mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar, SIM_2_ACCOUNT); newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS); assertFalse(Connection.can(newCapabilities, Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)); assertFalse(ongoingCall.isVideoCallingSupportedByPhoneAccount()); // Fire a change for an unrelated phone account. PhoneAccount anotherVideoCapableAcct = new PhoneAccount.Builder(SIM_1_ACCOUNT) .setCapabilities(SIM_2_ACCOUNT.getCapabilities() | PhoneAccount.CAPABILITY_VIDEO_CALLING) .build(); mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar, anotherVideoCapableAcct); // Call still should not be video capable assertFalse(Connection.can(ongoingCall.getConnectionCapabilities(), Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)); } private Call addSpyCallWithConnectionService(ConnectionServiceWrapper connSvr) { Call call = addSpyCall(); doReturn(connSvr).when(call).getConnectionService(); Loading