Merge "Move carrier in-service check to after E911 timeout." into main
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 872b423..29eb419 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -2550,7 +2550,7 @@
return;
}
mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
- phoneAccountRegistrar, mContext, mFlags);
+ phoneAccountRegistrar, mContext, mFlags, new Timeouts.Adapter());
mCreateConnectionProcessor.process();
}
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 607aa27..f6f4889 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -2032,7 +2032,8 @@
}
/** @see IConnectionService#disconnect(String, Session.Info) */
- void disconnect(Call call) {
+ @VisibleForTesting
+ public void disconnect(Call call) {
final String callId = mCallIdMapper.getCallId(call);
if (callId != null && isServiceValid("disconnect")) {
try {
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index abb2d8c..a2c742d 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -138,15 +138,19 @@
private final PhoneAccountRegistrar mPhoneAccountRegistrar;
private final Context mContext;
private final FeatureFlags mFlags;
+ private final Timeouts.Adapter mTimeoutsAdapter;
private CreateConnectionTimeout mTimeout;
private ConnectionServiceWrapper mService;
private int mConnectionAttempt;
@VisibleForTesting
- public CreateConnectionProcessor(
- Call call, ConnectionServiceRepository repository, CreateConnectionResponse response,
- PhoneAccountRegistrar phoneAccountRegistrar, Context context,
- FeatureFlags featureFlags) {
+ public CreateConnectionProcessor(Call call,
+ ConnectionServiceRepository repository,
+ CreateConnectionResponse response,
+ PhoneAccountRegistrar phoneAccountRegistrar,
+ Context context,
+ FeatureFlags featureFlags,
+ Timeouts.Adapter timeoutsAdapter) {
Log.v(this, "CreateConnectionProcessor created for Call = %s", call);
mCall = call;
mRepository = repository;
@@ -155,6 +159,7 @@
mContext = context;
mConnectionAttempt = 0;
mFlags = featureFlags;
+ mTimeoutsAdapter = timeoutsAdapter;
}
boolean isProcessingComplete() {
@@ -327,7 +332,7 @@
clearTimeout();
CreateConnectionTimeout timeout = new CreateConnectionTimeout(
- mContext, mPhoneAccountRegistrar, service, mCall);
+ mContext, mPhoneAccountRegistrar, service, mCall, mTimeoutsAdapter);
if (timeout.isTimeoutNeededForCall(getConnectionServices(mAttemptRecords),
attempt.connectionManagerPhoneAccount)) {
mTimeout = timeout;
diff --git a/src/com/android/server/telecom/CreateConnectionTimeout.java b/src/com/android/server/telecom/CreateConnectionTimeout.java
index 904ec81..7615d21 100644
--- a/src/com/android/server/telecom/CreateConnectionTimeout.java
+++ b/src/com/android/server/telecom/CreateConnectionTimeout.java
@@ -44,15 +44,17 @@
private final Handler mHandler = new Handler(Looper.getMainLooper());
private boolean mIsRegistered;
private boolean mIsCallTimedOut;
+ private final Timeouts.Adapter mTimeoutsAdapter;
@VisibleForTesting
public CreateConnectionTimeout(Context context, PhoneAccountRegistrar phoneAccountRegistrar,
- ConnectionServiceWrapper service, Call call) {
+ ConnectionServiceWrapper service, Call call, Timeouts.Adapter timeoutsAdapter) {
super("CCT", null /*lock*/);
mContext = context;
mPhoneAccountRegistrar = phoneAccountRegistrar;
mConnectionService = service;
mCall = call;
+ mTimeoutsAdapter = timeoutsAdapter;
}
@VisibleForTesting
@@ -60,6 +62,7 @@
PhoneAccountHandle currentAccount) {
// Non-emergency calls timeout automatically at the radio layer. No need for a timeout here.
if (!mCall.isEmergencyCall()) {
+ Log.d(this, "isTimeoutNeededForCall, not an emergency call");
return false;
}
@@ -68,11 +71,13 @@
PhoneAccountHandle connectionManager =
mPhoneAccountRegistrar.getSimCallManagerFromCall(mCall);
if (!accounts.contains(connectionManager)) {
+ Log.d(this, "isTimeoutNeededForCall, no connection manager");
return false;
}
// No need to add a timeout if the current attempt is over the connection manager.
if (Objects.equals(connectionManager, currentAccount)) {
+ Log.d(this, "isTimeoutNeededForCall, already attempting over connection manager");
return false;
}
@@ -83,17 +88,6 @@
return false;
}
- // Timeout is not required if carrier is not in service.
- if (carrierEnabledSatelliteFlag() && connectionManager != null) {
- PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccount(connectionManager,
- connectionManager.getUserHandle());
- if (account.hasCapabilities(PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS)
- && !account.hasCapabilities(PhoneAccount.CAPABILITY_VOICE_CALLING_AVAILABLE)) {
- Log.d(this, "isTimeoutNeededForCall, carrier is not in service.");
- return false;
- }
- }
-
Log.i(this, "isTimeoutNeededForCall, returning true");
return true;
}
@@ -123,8 +117,31 @@
@Override
public void loggedRun() {
+ if (!carrierEnabledSatelliteFlag()) {
+ timeoutCallIfNeeded();
+ return;
+ }
+
+ PhoneAccountHandle connectionManager =
+ mPhoneAccountRegistrar.getSimCallManagerFromCall(mCall);
+ if (connectionManager != null) {
+ PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccount(connectionManager,
+ connectionManager.getUserHandle());
+ if (account != null && account.hasCapabilities(
+ (PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS
+ | PhoneAccount.CAPABILITY_VOICE_CALLING_AVAILABLE))) {
+ // If we have encountered the timeout and there is an in service
+ // ConnectionManager, disconnect the call so that it can be attempted over
+ // the ConnectionManager.
+ timeoutCallIfNeeded();
+ return;
+ }
+ }
+ }
+
+ private void timeoutCallIfNeeded() {
if (mIsRegistered && isCallBeingPlaced(mCall)) {
- Log.i(this, "run, call timed out, calling disconnect");
+ Log.i(this, "timeoutCallIfNeeded, call timed out, calling disconnect");
mIsCallTimedOut = true;
mConnectionService.disconnect(mCall);
}
@@ -145,14 +162,15 @@
TelephonyManager telephonyManager =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager.isRadioOn()) {
- return Timeouts.getEmergencyCallTimeoutMillis(mContext.getContentResolver());
+ return mTimeoutsAdapter.getEmergencyCallTimeoutMillis(
+ mContext.getContentResolver());
} else {
- return Timeouts.getEmergencyCallTimeoutRadioOffMillis(
+ return mTimeoutsAdapter.getEmergencyCallTimeoutRadioOffMillis(
mContext.getContentResolver());
}
} catch (UnsupportedOperationException uoe) {
Log.e(this, uoe, "getTimeoutLengthMillis - telephony is not supported");
- return Timeouts.getEmergencyCallTimeoutMillis(mContext.getContentResolver());
+ return mTimeoutsAdapter.getEmergencyCallTimeoutMillis(mContext.getContentResolver());
}
}
}
diff --git a/src/com/android/server/telecom/Timeouts.java b/src/com/android/server/telecom/Timeouts.java
index abc7ff6..0ed71df 100644
--- a/src/com/android/server/telecom/Timeouts.java
+++ b/src/com/android/server/telecom/Timeouts.java
@@ -61,6 +61,14 @@
return Timeouts.getEmergencyCallbackWindowMillis(cr);
}
+ public long getEmergencyCallTimeoutMillis(ContentResolver cr) {
+ return Timeouts.getEmergencyCallTimeoutMillis(cr);
+ }
+
+ public long getEmergencyCallTimeoutRadioOffMillis(ContentResolver cr) {
+ return Timeouts.getEmergencyCallTimeoutRadioOffMillis(cr);
+ }
+
public long getUserDefinedCallRedirectionTimeoutMillis(ContentResolver cr) {
return Timeouts.getUserDefinedCallRedirectionTimeoutMillis(cr);
}
@@ -127,7 +135,6 @@
public int getDaysBackToSearchEmergencyDiagnosticEntries(){
return Timeouts.getDaysBackToSearchEmergencyDiagnosticEntries();
-
}
}
diff --git a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java
index 5bfacaa..ddbc250 100644
--- a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java
+++ b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java
@@ -21,11 +21,11 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.after;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -50,6 +50,7 @@
import com.android.internal.telephony.flags.Flags;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallIdMapper;
+import com.android.server.telecom.CallState;
import com.android.server.telecom.ConnectionServiceFocusManager;
import com.android.server.telecom.ConnectionServiceRepository;
import com.android.server.telecom.ConnectionServiceWrapper;
@@ -57,7 +58,7 @@
import com.android.server.telecom.CreateConnectionResponse;
import com.android.server.telecom.CreateConnectionTimeout;
import com.android.server.telecom.PhoneAccountRegistrar;
-import com.android.server.telecom.flags.FeatureFlags;
+import com.android.server.telecom.Timeouts;
import org.junit.After;
import org.junit.Before;
@@ -70,6 +71,7 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -98,6 +100,7 @@
Call mMockCall;
@Mock
ConnectionServiceFocusManager mConnectionServiceFocusManager;
+ @Mock Timeouts.Adapter mTimeoutsAdapter;
CreateConnectionProcessor mTestCreateConnectionProcessor;
CreateConnectionTimeout mTestCreateConnectionTimeout;
@@ -131,7 +134,7 @@
mTestCreateConnectionProcessor = new CreateConnectionProcessor(mMockCall,
mMockConnectionServiceRepository, mMockCreateConnectionResponse,
- mMockAccountRegistrar, mContext, mFeatureFlags);
+ mMockAccountRegistrar, mContext, mFeatureFlags, mTimeoutsAdapter);
mAccountToSub = new HashMap<>();
phoneAccounts = new ArrayList<>();
@@ -156,7 +159,7 @@
thenReturn(Binder.getCallingUserHandle());
mTestCreateConnectionTimeout = new CreateConnectionTimeout(mContext, mMockAccountRegistrar,
- makeConnectionServiceWrapper(), mMockCall);
+ makeConnectionServiceWrapper(), mMockCall, mTimeoutsAdapter);
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
}
@@ -786,30 +789,6 @@
}
@Test
- public void testIsTimeoutNeededForCall_carrierNotInService() {
- when(mMockCall.isEmergencyCall()).thenReturn(true);
- when(mMockAccountRegistrar.getSystemSimCallManagerComponent()).thenReturn(
- new ComponentName(TEST_PACKAGE, TEST_CLASS));
-
- List<PhoneAccountHandle> phoneAccountHandles = new ArrayList<>();
- // Put in a regular phone account handle
- PhoneAccount regularAccount = makePhoneAccount("tel_acct1",
- PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
- phoneAccountHandles.add(regularAccount.getAccountHandle());
- // Create a connection manager for the call and include it in phoneAccountHandles
- int capability = PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS;
- PhoneAccount callManagerPA = createNewConnectionManagerPhoneAccountForCall(mMockCall,
- "cm_acct", capability);
- PhoneAccount phoneAccountWithoutService = makeQuickAccount("cm_acct", capability, null);
- when(mMockAccountRegistrar.getPhoneAccount(callManagerPA.getAccountHandle(),
- callManagerPA.getAccountHandle().getUserHandle()))
- .thenReturn(phoneAccountWithoutService);
- phoneAccountHandles.add(callManagerPA.getAccountHandle());
-
- assertFalse(mTestCreateConnectionTimeout.isTimeoutNeededForCall(phoneAccountHandles, null));
- }
-
- @Test
public void testIsTimeoutNeededForCall() {
when(mMockCall.isEmergencyCall()).thenReturn(true);
when(mMockAccountRegistrar.getSystemSimCallManagerComponent()).thenReturn(
@@ -834,6 +813,79 @@
assertTrue(mTestCreateConnectionTimeout.isTimeoutNeededForCall(phoneAccountHandles, null));
}
+ @Test
+ public void testConnTimeout_carrierSatelliteEnabled_noInServiceConnManager_callNeverTimesOut() {
+ when(mMockCall.isEmergencyCall()).thenReturn(true);
+ when(mMockCall.isTestEmergencyCall()).thenReturn(false);
+ when(mMockCall.getHandle()).thenReturn(Uri.parse(""));
+ when(mMockCall.getState()).thenReturn(CallState.DIALING);
+ // Primary phone account, meant to fail
+ PhoneAccount regularAccount = makePhoneAccount("tel_acct1",
+ PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
+ | PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS);
+ phoneAccounts.add(regularAccount);
+ when(mMockAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
+ nullable(String.class))).thenReturn(regularAccount.getAccountHandle());
+ when(mMockAccountRegistrar.getSystemSimCallManagerComponent()).thenReturn(
+ new ComponentName(TEST_PACKAGE, TEST_CLASS));
+ PhoneAccount callManagerPA = getNewEmergencyConnectionManagerPhoneAccount(
+ "cm_acct", PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS
+ | PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS);
+ phoneAccounts.add(callManagerPA);
+ ConnectionServiceWrapper service = makeConnectionServiceWrapper();
+ when(mMockAccountRegistrar.getSimCallManagerFromCall(mMockCall)).thenReturn(
+ callManagerPA.getAccountHandle());
+ when(mMockAccountRegistrar.getPhoneAccount(eq(callManagerPA.getAccountHandle()),
+ any())).thenReturn(callManagerPA);
+ Duration timeout = Duration.ofMillis(10);
+ when(mTimeoutsAdapter.getEmergencyCallTimeoutMillis(any())).thenReturn(timeout.toMillis());
+ when(mTimeoutsAdapter.getEmergencyCallTimeoutRadioOffMillis(any())).thenReturn(
+ timeout.toMillis());
+
+
+ mTestCreateConnectionProcessor.process();
+
+ // Validate the call is not disconnected after the timeout.
+ verify(service, after(timeout.toMillis() + 100).never()).disconnect(eq(mMockCall));
+ }
+
+ @Test
+ public void testConnTimeout_carrierSatelliteEnabled_inServiceConnManager_callTimesOut() {
+ when(mMockCall.isEmergencyCall()).thenReturn(true);
+ when(mMockCall.isTestEmergencyCall()).thenReturn(false);
+ when(mMockCall.getHandle()).thenReturn(Uri.parse(""));
+ when(mMockCall.getState()).thenReturn(CallState.DIALING);
+ // Primary phone account, meant to fail
+ PhoneAccount regularAccount = makePhoneAccount("tel_acct1",
+ PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
+ | PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS);
+ phoneAccounts.add(regularAccount);
+ when(mMockAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
+ nullable(String.class))).thenReturn(regularAccount.getAccountHandle());
+ when(mMockAccountRegistrar.getSystemSimCallManagerComponent()).thenReturn(
+ new ComponentName(TEST_PACKAGE, TEST_CLASS));
+ PhoneAccount callManagerPA = getNewEmergencyConnectionManagerPhoneAccount(
+ "cm_acct", PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS
+ | PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS
+ | PhoneAccount.CAPABILITY_VOICE_CALLING_AVAILABLE
+ );
+ phoneAccounts.add(callManagerPA);
+ ConnectionServiceWrapper service = makeConnectionServiceWrapper();
+ when(mMockAccountRegistrar.getSimCallManagerFromCall(mMockCall)).thenReturn(
+ callManagerPA.getAccountHandle());
+ when(mMockAccountRegistrar.getPhoneAccount(eq(callManagerPA.getAccountHandle()),
+ any())).thenReturn(callManagerPA);
+ Duration timeout = Duration.ofMillis(10);
+ when(mTimeoutsAdapter.getEmergencyCallTimeoutMillis(any())).thenReturn(timeout.toMillis());
+ when(mTimeoutsAdapter.getEmergencyCallTimeoutRadioOffMillis(any())).thenReturn(
+ timeout.toMillis());
+
+ mTestCreateConnectionProcessor.process();
+
+ // Validate the call was disconnected after the timeout.
+ verify(service, after(timeout.toMillis() + 100)).disconnect(eq(mMockCall));
+ }
+
/**
* Verifies when telephony is not available that we just get invalid sub id for a phone acct.
*/