Loading flags/telecom_anomaly_report_flags.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -16,3 +16,14 @@ flag { description: "If a self-managed call is stuck in certain states, disconnect it" bug: "360298368" } # OWNER=tgunn TARGET=25Q2 flag { name: "dont_timeout_destroyed_calls" namespace: "telecom" description: "When create connection timeout is hit, if call is already destroyed, skip anomaly" bug: "381684580" metadata { purpose: PURPOSE_BUGFIX } } src/com/android/server/telecom/ConnectionServiceWrapper.java +36 −10 Original line number Diff line number Diff line Loading @@ -130,11 +130,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements synchronized (mLock) { logIncoming("handleCreateConnectionComplete %s", callId); Call call = mCallIdMapper.getCall(callId); if (call != null && mScheduledFutureMap.containsKey(call)) { ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call); existingTimeout.cancel(false /* cancelIfRunning */); mScheduledFutureMap.remove(call); } maybeRemoveCleanupFuture(call); // Check status hints image for cross user access if (connection.getStatusHints() != null) { Icon icon = connection.getStatusHints().getIcon(); Loading Loading @@ -174,11 +170,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements synchronized (mLock) { logIncoming("handleCreateConferenceComplete %s", callId); Call call = mCallIdMapper.getCall(callId); if (call != null && mScheduledFutureMap.containsKey(call)) { ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call); existingTimeout.cancel(false /* cancelIfRunning */); mScheduledFutureMap.remove(call); } maybeRemoveCleanupFuture(call); // Check status hints image for cross user access if (conference.getStatusHints() != null) { Icon icon = conference.getStatusHints().getIcon(); Loading Loading @@ -1678,6 +1670,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements Log.getExternalSession(TELECOM_ABBREVIATION)); } catch (RemoteException e) { Log.e(this, e, "Failure to createConference -- %s", getComponentName()); if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } mPendingResponses.remove(callId).handleCreateConferenceFailure( new DisconnectCause(DisconnectCause.ERROR, e.toString())); } Loading Loading @@ -1708,6 +1703,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements Log.i(ConnectionServiceWrapper.this, "Call not present" + " in call id mapper, maybe it was aborted before the bind" + " completed successfully?"); if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } response.handleCreateConnectionFailure( new DisconnectCause(DisconnectCause.CANCELED)); return; Loading Loading @@ -1793,6 +1791,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements mScheduledFutureMap.put(call, future); try { if (mFlags.cswServiceInterfaceIsNull() && mServiceInterface == null) { if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } mPendingResponses.remove(callId).handleCreateConnectionFailure( new DisconnectCause(DisconnectCause.ERROR, "CSW#oCC ServiceInterface is null")); Loading @@ -1807,6 +1808,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements } } catch (RemoteException e) { Log.e(this, e, "Failure to createConnection -- %s", getComponentName()); if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } mPendingResponses.remove(callId).handleCreateConnectionFailure( new DisconnectCause(DisconnectCause.ERROR, e.toString())); } Loading Loading @@ -2286,6 +2290,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements if (response != null) { response.handleCreateConnectionFailure(disconnectCause); } if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(mCallIdMapper.getCall(callId)); } mCallIdMapper.removeCall(callId); } Loading @@ -2295,6 +2302,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements if (response != null) { response.handleCreateConnectionFailure(disconnectCause); } if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } mCallIdMapper.removeCall(call); } Loading Loading @@ -2754,4 +2764,20 @@ public class ConnectionServiceWrapper extends ServiceBinder implements public void setAnomalyReporterAdapter(AnomalyReporterAdapter mAnomalyReporterAdapter){ mAnomalyReporter = mAnomalyReporterAdapter; } /** * Given a call, unschedule and cancel the cleanup future. * @param call the call. */ private void maybeRemoveCleanupFuture(Call call) { if (call == null) { return; } ScheduledFuture<?> future = mScheduledFutureMap.remove(call); if (future == null) { return; } future.cancel(false /* interrupt */); } } Loading
flags/telecom_anomaly_report_flags.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -16,3 +16,14 @@ flag { description: "If a self-managed call is stuck in certain states, disconnect it" bug: "360298368" } # OWNER=tgunn TARGET=25Q2 flag { name: "dont_timeout_destroyed_calls" namespace: "telecom" description: "When create connection timeout is hit, if call is already destroyed, skip anomaly" bug: "381684580" metadata { purpose: PURPOSE_BUGFIX } }
src/com/android/server/telecom/ConnectionServiceWrapper.java +36 −10 Original line number Diff line number Diff line Loading @@ -130,11 +130,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements synchronized (mLock) { logIncoming("handleCreateConnectionComplete %s", callId); Call call = mCallIdMapper.getCall(callId); if (call != null && mScheduledFutureMap.containsKey(call)) { ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call); existingTimeout.cancel(false /* cancelIfRunning */); mScheduledFutureMap.remove(call); } maybeRemoveCleanupFuture(call); // Check status hints image for cross user access if (connection.getStatusHints() != null) { Icon icon = connection.getStatusHints().getIcon(); Loading Loading @@ -174,11 +170,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements synchronized (mLock) { logIncoming("handleCreateConferenceComplete %s", callId); Call call = mCallIdMapper.getCall(callId); if (call != null && mScheduledFutureMap.containsKey(call)) { ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call); existingTimeout.cancel(false /* cancelIfRunning */); mScheduledFutureMap.remove(call); } maybeRemoveCleanupFuture(call); // Check status hints image for cross user access if (conference.getStatusHints() != null) { Icon icon = conference.getStatusHints().getIcon(); Loading Loading @@ -1678,6 +1670,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements Log.getExternalSession(TELECOM_ABBREVIATION)); } catch (RemoteException e) { Log.e(this, e, "Failure to createConference -- %s", getComponentName()); if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } mPendingResponses.remove(callId).handleCreateConferenceFailure( new DisconnectCause(DisconnectCause.ERROR, e.toString())); } Loading Loading @@ -1708,6 +1703,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements Log.i(ConnectionServiceWrapper.this, "Call not present" + " in call id mapper, maybe it was aborted before the bind" + " completed successfully?"); if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } response.handleCreateConnectionFailure( new DisconnectCause(DisconnectCause.CANCELED)); return; Loading Loading @@ -1793,6 +1791,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements mScheduledFutureMap.put(call, future); try { if (mFlags.cswServiceInterfaceIsNull() && mServiceInterface == null) { if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } mPendingResponses.remove(callId).handleCreateConnectionFailure( new DisconnectCause(DisconnectCause.ERROR, "CSW#oCC ServiceInterface is null")); Loading @@ -1807,6 +1808,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements } } catch (RemoteException e) { Log.e(this, e, "Failure to createConnection -- %s", getComponentName()); if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } mPendingResponses.remove(callId).handleCreateConnectionFailure( new DisconnectCause(DisconnectCause.ERROR, e.toString())); } Loading Loading @@ -2286,6 +2290,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements if (response != null) { response.handleCreateConnectionFailure(disconnectCause); } if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(mCallIdMapper.getCall(callId)); } mCallIdMapper.removeCall(callId); } Loading @@ -2295,6 +2302,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements if (response != null) { response.handleCreateConnectionFailure(disconnectCause); } if (mFlags.dontTimeoutDestroyedCalls()) { maybeRemoveCleanupFuture(call); } mCallIdMapper.removeCall(call); } Loading Loading @@ -2754,4 +2764,20 @@ public class ConnectionServiceWrapper extends ServiceBinder implements public void setAnomalyReporterAdapter(AnomalyReporterAdapter mAnomalyReporterAdapter){ mAnomalyReporter = mAnomalyReporterAdapter; } /** * Given a call, unschedule and cancel the cleanup future. * @param call the call. */ private void maybeRemoveCleanupFuture(Call call) { if (call == null) { return; } ScheduledFuture<?> future = mScheduledFutureMap.remove(call); if (future == null) { return; } future.cancel(false /* interrupt */); } }