diff options
author | Grant Menke <grantmenke@google.com> | 2023-12-04 23:51:23 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2023-12-04 23:51:23 +0000 |
commit | bc220b893e194454168b4b03d96e052df26fbb12 (patch) | |
tree | c0da1951fd19de783c5b68bc7e65a3492e4e5c1c | |
parent | bd0d6d8f8fa7ebc3dd3d83efed2ee0c8daa7c911 (diff) | |
parent | 45c65d16d0b178744372a62134fe5ba0c4487cdd (diff) | |
download | Telecomm-bc220b893e194454168b4b03d96e052df26fbb12.tar.gz |
Merge "Ensure the associated call count is accurately tracked for RCS." into main
10 files changed, 135 insertions, 24 deletions
diff --git a/flags/Android.bp b/flags/Android.bp index 63a67aeb3..386831cbb 100644 --- a/flags/Android.bp +++ b/flags/Android.bp @@ -36,7 +36,8 @@ aconfig_declarations { "telecom_calllog_flags.aconfig", "telecom_resolve_hidden_dependencies.aconfig", "telecom_bluetoothroutemanager_flags.aconfig", - "telecom_work_profile_flags.aconfig" + "telecom_work_profile_flags.aconfig", + "telecom_connection_service_wrapper_flags.aconfig", ], } diff --git a/flags/telecom_connection_service_wrapper_flags.aconfig b/flags/telecom_connection_service_wrapper_flags.aconfig new file mode 100644 index 000000000..5f46c272a --- /dev/null +++ b/flags/telecom_connection_service_wrapper_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.server.telecom.flags" + +flag { + name: "updated_rcs_call_count_tracking" + namespace: "telecom" + description: "Ensure that the associatedCallCount of CS and RCS is accurately being tracked." + bug: "286154316" +}
\ No newline at end of file diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java index c0fb17f3f..c9557f205 100644 --- a/src/com/android/server/telecom/Call.java +++ b/src/com/android/server/telecom/Call.java @@ -74,6 +74,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.IVideoProvider; import com.android.internal.util.Preconditions; import com.android.server.telecom.flags.FeatureFlags; +import com.android.server.telecom.flags.Flags; import com.android.server.telecom.stats.CallFailureCause; import com.android.server.telecom.stats.CallStateChangedAtomWriter; import com.android.server.telecom.ui.ToastFactory; @@ -438,6 +439,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, private int mCallerDisplayNamePresentation; /** + * The remote connection service which is attempted or already connecting this call. This is set + * to a non-null value only when a connection manager phone account is in use. When set, this + * will correspond to the target phone account of the {@link Call}. + */ + private ConnectionServiceWrapper mRemoteConnectionService; + + /** * The connection service which is attempted or already connecting this call. */ private ConnectionServiceWrapper mConnectionService; @@ -2364,11 +2372,25 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, @VisibleForTesting public void setConnectionService(ConnectionServiceWrapper service) { + setConnectionService(service, null); + } + + @VisibleForTesting + public void setConnectionService( + ConnectionServiceWrapper service, + ConnectionServiceWrapper remoteService + ) { Preconditions.checkNotNull(service); clearConnectionService(); service.incrementAssociatedCallCount(); + + if (mFlags.updatedRcsCallCountTracking() && remoteService != null) { + remoteService.incrementAssociatedCallCount(); + mRemoteConnectionService = remoteService; + } + mConnectionService = service; mAnalytics.setCallConnectionService(service.getComponentName().flattenToShortString()); mConnectionService.addCall(this); @@ -2376,10 +2398,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, /** * Perform an in-place replacement of the {@link ConnectionServiceWrapper} for this Call. - * Removes the call from its former {@link ConnectionServiceWrapper}, ensuring that the - * ConnectionService is NOT unbound if the call count hits zero. - * This is used by the {@link ConnectionServiceWrapper} when handling {@link Connection} and - * {@link Conference} additions via a ConnectionManager. + * Removes the call from its former {@link ConnectionServiceWrapper}, while still ensuring the + * former {@link ConnectionServiceWrapper} is tracked as the mRemoteConnectionService for this + * call so that the associatedCallCount of that {@link ConnectionServiceWrapper} is accurately + * tracked until it is supposed to be unbound. + * This method is used by the {@link ConnectionServiceWrapper} when handling {@link Connection} + * and {@link Conference} additions via a ConnectionManager. * The original {@link android.telecom.ConnectionService} will directly add external calls and * conferences to Telecom as well as the ConnectionManager, which will add to Telecom. In these * cases since its first added to via the original CS, we want to change the CS responsible for @@ -2392,9 +2416,18 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, if (mConnectionService != null) { ConnectionServiceWrapper serviceTemp = mConnectionService; + + if (mFlags.updatedRcsCallCountTracking()) { + // Continue to track the former CS for this call so that it doesn't unbind early: + mRemoteConnectionService = serviceTemp; + } + mConnectionService = null; serviceTemp.removeCall(this); - serviceTemp.decrementAssociatedCallCount(true /*isSuppressingUnbind*/); + + if (!mFlags.updatedRcsCallCountTracking()) { + serviceTemp.decrementAssociatedCallCount(true /*isSuppressingUnbind*/); + } } service.incrementAssociatedCallCount(); @@ -2408,6 +2441,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, void clearConnectionService() { if (mConnectionService != null) { ConnectionServiceWrapper serviceTemp = mConnectionService; + ConnectionServiceWrapper remoteServiceTemp = mRemoteConnectionService; + mRemoteConnectionService = null; mConnectionService = null; serviceTemp.removeCall(this); @@ -2418,6 +2453,10 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, // necessary, but cleaning up mConnectionService prior to triggering an unbind is good // to do. decrementAssociatedCallCount(serviceTemp); + + if (mFlags.updatedRcsCallCountTracking() && remoteServiceTemp != null) { + decrementAssociatedCallCount(remoteServiceTemp); + } } } @@ -2436,7 +2475,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, return; } mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this, - phoneAccountRegistrar, mContext); + phoneAccountRegistrar, mContext, mFlags); mCreateConnectionProcessor.process(); } diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java index 7c930a4b4..e4ea6d53a 100755 --- a/src/com/android/server/telecom/CallsManager.java +++ b/src/com/android/server/telecom/CallsManager.java @@ -5844,7 +5844,8 @@ public class CallsManager extends Call.ListenerBase return; } ConnectionServiceWrapper service = mConnectionServiceRepository.getService( - phoneAccountHandle.getComponentName(), phoneAccountHandle.getUserHandle()); + phoneAccountHandle.getComponentName(), phoneAccountHandle.getUserHandle(), + mFeatureFlags); if (service == null) { Log.i(this, "Found no connection service."); return; @@ -5869,7 +5870,8 @@ public class CallsManager extends Call.ListenerBase return; } ConnectionServiceWrapper service = mConnectionServiceRepository.getService( - phoneAccountHandle.getComponentName(), phoneAccountHandle.getUserHandle()); + phoneAccountHandle.getComponentName(), phoneAccountHandle.getUserHandle(), + mFeatureFlags); if (service == null) { Log.i(this, "Found no connection service."); return; diff --git a/src/com/android/server/telecom/ConnectionServiceRepository.java b/src/com/android/server/telecom/ConnectionServiceRepository.java index 3991ed51f..d6a78d0a8 100644 --- a/src/com/android/server/telecom/ConnectionServiceRepository.java +++ b/src/com/android/server/telecom/ConnectionServiceRepository.java @@ -23,6 +23,7 @@ import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.telecom.flags.FeatureFlags; import java.util.HashMap; @@ -61,7 +62,10 @@ public class ConnectionServiceRepository { } @VisibleForTesting - public ConnectionServiceWrapper getService(ComponentName componentName, UserHandle userHandle) { + public ConnectionServiceWrapper getService( + ComponentName componentName, + UserHandle userHandle, + FeatureFlags featureFlags) { Pair<ComponentName, UserHandle> cacheKey = Pair.create(componentName, userHandle); ConnectionServiceWrapper service = mServiceCache.get(cacheKey); if (service == null) { @@ -72,7 +76,8 @@ public class ConnectionServiceRepository { mCallsManager, mContext, mLock, - userHandle); + userHandle, + featureFlags); service.addListener(mUnbindListener); mServiceCache.put(cacheKey, service); } diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java index 07b048db5..593673061 100644 --- a/src/com/android/server/telecom/ConnectionServiceWrapper.java +++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java @@ -64,6 +64,7 @@ import com.android.internal.telecom.IConnectionServiceAdapter; import com.android.internal.telecom.IVideoProvider; import com.android.internal.telecom.RemoteServiceCallback; import com.android.internal.util.Preconditions; +import com.android.server.telecom.flags.FeatureFlags; import com.android.server.telecom.flags.Flags; import java.util.ArrayList; @@ -1353,6 +1354,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements private final CallsManager mCallsManager; private final AppOpsManager mAppOpsManager; private final Context mContext; + private final FeatureFlags mFlags; private ConnectionServiceFocusManager.ConnectionServiceFocusListener mConnSvrFocusListener; @@ -1374,8 +1376,10 @@ public class ConnectionServiceWrapper extends ServiceBinder implements CallsManager callsManager, Context context, TelecomSystem.SyncRoot lock, - UserHandle userHandle) { - super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle); + UserHandle userHandle, + FeatureFlags featureFlags) { + super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle, + featureFlags); mConnectionServiceRepository = connectionServiceRepository; phoneAccountRegistrar.addListener(new PhoneAccountRegistrar.Listener() { // TODO -- Upon changes to PhoneAccountRegistrar, need to re-wire connections @@ -1385,6 +1389,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements mCallsManager = callsManager; mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mContext = context; + mFlags = featureFlags; } /** See {@link IConnectionService#addConnectionServiceAdapter}. */ @@ -2573,7 +2578,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements isCallerConnectionManager = true; } ConnectionServiceWrapper service = mConnectionServiceRepository.getService( - handle.getComponentName(), handle.getUserHandle()); + handle.getComponentName(), handle.getUserHandle(), mFlags); if (service != null && service != this) { simServices.add(service); } else { diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java index 19691c1a2..f5b257daf 100644 --- a/src/com/android/server/telecom/CreateConnectionProcessor.java +++ b/src/com/android/server/telecom/CreateConnectionProcessor.java @@ -32,6 +32,8 @@ import android.telephony.TelephonyManager; // TODO: Needed for move to system service: import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.telecom.flags.Flags; +import com.android.server.telecom.flags.FeatureFlags; import java.util.ArrayList; import java.util.Collection; @@ -125,6 +127,7 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { private DisconnectCause mLastErrorDisconnectCause; private final PhoneAccountRegistrar mPhoneAccountRegistrar; private final Context mContext; + private final FeatureFlags mFlags; private CreateConnectionTimeout mTimeout; private ConnectionServiceWrapper mService; private int mConnectionAttempt; @@ -132,7 +135,8 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { @VisibleForTesting public CreateConnectionProcessor( Call call, ConnectionServiceRepository repository, CreateConnectionResponse response, - PhoneAccountRegistrar phoneAccountRegistrar, Context context) { + PhoneAccountRegistrar phoneAccountRegistrar, Context context, + FeatureFlags featureFlags) { Log.v(this, "CreateConnectionProcessor created for Call = %s", call); mCall = call; mRepository = repository; @@ -140,6 +144,7 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { mPhoneAccountRegistrar = phoneAccountRegistrar; mContext = context; mConnectionAttempt = 0; + mFlags = featureFlags; } boolean isProcessingComplete() { @@ -239,7 +244,7 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { Log.i(this, "Trying attempt %s", attempt); PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount; mService = mRepository.getService(phoneAccount.getComponentName(), - phoneAccount.getUserHandle()); + phoneAccount.getUserHandle(), mFlags); if (mService == null) { Log.i(this, "Found no connection service for attempt %s", attempt); attemptNextPhoneAccount(); @@ -247,7 +252,25 @@ public class CreateConnectionProcessor implements CreateConnectionResponse { mConnectionAttempt++; mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount); mCall.setTargetPhoneAccount(attempt.targetPhoneAccount); - mCall.setConnectionService(mService); + if (mFlags.updatedRcsCallCountTracking()) { + if (Objects.equals(attempt.connectionManagerPhoneAccount, + attempt.targetPhoneAccount)) { + mCall.setConnectionService(mService); + } else { + PhoneAccountHandle remotePhoneAccount = attempt.targetPhoneAccount; + ConnectionServiceWrapper mRemoteService = + mRepository.getService(remotePhoneAccount.getComponentName(), + remotePhoneAccount.getUserHandle(), mFlags); + if (mRemoteService == null) { + mCall.setConnectionService(mService); + } else { + Log.v(this, "attemptNextPhoneAccount Setting RCS = %s", mRemoteService); + mCall.setConnectionService(mService, mRemoteService); + } + } + } else { + mCall.setConnectionService(mService); + } setTimeoutIfNeeded(mService, attempt); if (mCall.isIncoming()) { if (mCall.isAdhocConferenceCall()) { diff --git a/src/com/android/server/telecom/ServiceBinder.java b/src/com/android/server/telecom/ServiceBinder.java index 7274993e7..77f7b2e65 100644 --- a/src/com/android/server/telecom/ServiceBinder.java +++ b/src/com/android/server/telecom/ServiceBinder.java @@ -29,6 +29,7 @@ import android.util.ArraySet; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; +import com.android.server.telecom.flags.FeatureFlags; import java.util.Collections; import java.util.Set; @@ -240,6 +241,8 @@ public abstract class ServiceBinder { * Abbreviated form of the package name from {@link #mComponentName}; used for session logging. */ protected final String mPackageAbbreviation; + private final FeatureFlags mFlags; + /** The set of callbacks waiting for notification of the binding's success or failure. */ private final Set<BindCallback> mCallbacks = new ArraySet<>(); @@ -282,7 +285,7 @@ public abstract class ServiceBinder { * @param userHandle The {@link UserHandle} to use for binding. */ protected ServiceBinder(String serviceAction, ComponentName componentName, Context context, - TelecomSystem.SyncRoot lock, UserHandle userHandle) { + TelecomSystem.SyncRoot lock, UserHandle userHandle, FeatureFlags featureFlags) { Preconditions.checkState(!TextUtils.isEmpty(serviceAction)); Preconditions.checkNotNull(componentName); @@ -292,6 +295,7 @@ public abstract class ServiceBinder { mComponentName = componentName; mPackageAbbreviation = Log.getPackageAbbreviation(componentName); mUserHandle = userHandle; + mFlags = featureFlags; } final UserHandle getUserHandle() { @@ -305,10 +309,16 @@ public abstract class ServiceBinder { } final void decrementAssociatedCallCount() { - decrementAssociatedCallCount(false /*isSuppressingUnbind*/); + if (mFlags.updatedRcsCallCountTracking()) { + decrementAssociatedCallCountUpdated(); + } else { + decrementAssociatedCallCount(false /*isSuppressingUnbind*/); + } } final void decrementAssociatedCallCount(boolean isSuppressingUnbind) { + // This is the legacy method - will be removed after the Flags.updatedRcsCallCountTracking + // mendel study completes. if (mAssociatedCallCount > 0) { mAssociatedCallCount--; Log.v(this, "Call count decrement %d, %s", mAssociatedCallCount, @@ -323,6 +333,21 @@ public abstract class ServiceBinder { } } + final void decrementAssociatedCallCountUpdated() { + if (mAssociatedCallCount > 0) { + mAssociatedCallCount--; + Log.i(this, "Call count decrement %d, %s", mAssociatedCallCount, + mComponentName.flattenToShortString()); + + if (mAssociatedCallCount == 0) { + unbind(); + } + } else { + Log.wtf(this, "%s: ignoring a request to decrement mAssociatedCallCount below zero", + mComponentName.getClassName()); + } + } + final int getAssociatedCallCount() { return mAssociatedCallCount; } diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java index 649f435f3..6e0e660bf 100644 --- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java +++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java @@ -2815,8 +2815,9 @@ public class CallsManagerTest extends TelecomTestCase { public void testQueryCurrentLocationCheckOnReceiveResult() throws Exception { ConnectionServiceWrapper service = new ConnectionServiceWrapper( new ComponentName(mContext.getPackageName(), - mContext.getPackageName().getClass().getName()), - null, mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null); + mContext.getPackageName().getClass().getName()), null, + mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null, + mFeatureFlags); CompletableFuture<String> resultFuture = new CompletableFuture<>(); try { @@ -2841,7 +2842,8 @@ public class CallsManagerTest extends TelecomTestCase { mSetRlagsRule.enableFlags(Flags.FLAG_UNBIND_TIMEOUT_CONNECTIONS); ConnectionServiceWrapper service = new ConnectionServiceWrapper( SIM_1_ACCOUNT.getAccountHandle().getComponentName(), null, - mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null); + mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null, + mFeatureFlags); TestScheduledExecutorService scheduledExecutorService = new TestScheduledExecutorService(); service.setScheduledExecutorService(scheduledExecutorService); Call call = addSpyCall(); diff --git a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java index 8a85a8786..c356b8fcc 100644 --- a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java +++ b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java @@ -38,6 +38,7 @@ import com.android.server.telecom.ConnectionServiceWrapper; import com.android.server.telecom.CreateConnectionProcessor; import com.android.server.telecom.CreateConnectionResponse; import com.android.server.telecom.PhoneAccountRegistrar; +import com.android.server.telecom.flags.FeatureFlags; import org.junit.After; import org.junit.Before; @@ -123,7 +124,7 @@ public class CreateConnectionProcessorTest extends TelecomTestCase { mTestCreateConnectionProcessor = new CreateConnectionProcessor(mMockCall, mMockConnectionServiceRepository, mMockCreateConnectionResponse, - mMockAccountRegistrar, mContext); + mMockAccountRegistrar, mContext, mFeatureFlags); mAccountToSub = new HashMap<>(); phoneAccounts = new ArrayList<>(); @@ -842,7 +843,7 @@ public class CreateConnectionProcessorTest extends TelecomTestCase { ConnectionServiceWrapper wrapper = mock(ConnectionServiceWrapper.class); when(mMockConnectionServiceRepository.getService( eq(makeQuickConnectionServiceComponentName()), - any(UserHandle.class))).thenReturn(wrapper); + any(UserHandle.class), any(FeatureFlags.class))).thenReturn(wrapper); return wrapper; } |