﻿
# Managed Telecom Integration { #android-managed-telecom-integration }

Since version `26.1`, Libsoftphone manages its own Android Telecom integration.
Your app no longer needs to implement a `ConnectionService` or register a `PhoneAccount` itself.
The SDK also supports compatibility audio routing for devices where Android Telecom is unavailable or cannot handle a call reliably.

This guide covers strategy selection, audio endpoint selection, permission updates, and runtime diagnostics.
The examples use the `Instance` API; call them on the main thread after loading the SDK.

## Audio routing strategies

The `defaultTelecomStrategy` preference selects the preferred strategy for new calls:

| Value              | Behavior                                                                    |
|--------------------|-----------------------------------------------------------------------------|
| `system` (default) | Integrates calls with Android Telecom and uses its audio routing support.   |
| `compat`           | Manages call audio through `AudioManager` without using a `TelecomManager`. |

Changing `defaultTelecomStrategy` does not immediately switch calls that are already in progress.
To move the current call session to compatibility routing, use the [explicit switch](#switching-active-calls-to-compatibility-routing) described below.

### Automatic fallback

The SDK can switch strategies while calls are active.
If system Telecom is unavailable or reporting a call to it fails, the SDK falls back to compatibility routing.
It can also switch preemptively when a new call would require a call state that system Telecom cannot support.

Fallback applies to the **current call session**: existing calls and any additional calls started before the last call ends use compatibility routing.
Once all calls have ended, the temporary override is cleared and subsequent calls use the configured default again.
Fallback does not change the `defaultTelecomStrategy` preference.

You can observe the current routing mode through `Instance.Telecom.isUsingCompatibilityAudioRouting()`, which returns a `StateFlow<Boolean>`.
This reports the current mode, including a configured `compat` strategy, rather than only indicating that an error occurred.

### Switching active calls to compatibility routing

If your app detects a problem with system Telecom, request a switch without waiting for the calls to end:

```java
Instance.Telecom.switchReportedCallsToCompatibilityAudioRouting();
```

This moves all currently reported calls to compatibility routing and keeps that strategy for additional calls during the same session.
After the last call ends, the SDK returns to the configured default for future calls.
Calling this method when there are no reported calls has no effect; use `defaultTelecomStrategy` to configure future calls.

Telecom errors are also delivered to `Observer.onTelecomError(...)`.
Your app can use this callback to record diagnostics or offer a compatibility routing option to the user.

## Audio endpoints

Audio routes are now represented by `cz.acrobits.libsoftphone.telecom.AudioEndpoint` objects instead of only an enum of route types.
This lets your app distinguish multiple endpoints of the same type, such as two Bluetooth devices.

Each endpoint exposes:

| Property      | Meaning                                                                                                                               |
|---------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `id`          | The endpoint's identifier. Use this to distinguish endpoints of the same type.                                                        |
| `name`        | An optional endpoint name, suitable for a device selection UI. Provide a fallback label when it is `null`.                            |
| `type`        | `Unknown`, `Receiver`, `Speaker`, `Bluetooth`, `Headset`, or `Streaming`.                                                             |
| `isSynthetic` | Indicates an endpoint that cannot be associated with a specific physical device, for example because Bluetooth permission is missing. |

Use endpoint instances supplied by the SDK; do not implement `AudioEndpoint` yourself.
When building a route picker, keep separate entries for endpoints with different IDs even if their types match.

The `Instance.Audio` API provides the following operations:

| Method                             | Purpose                                                                            |
|------------------------------------|------------------------------------------------------------------------------------|
| `getAvailableCallAudioEndpoints()` | Returns a `StateFlow<List<AudioEndpoint>>` containing the available routes.        |
| `getCurrentAudioEndpoint()`        | Returns a `StateFlow` containing the current route, or `null` while it is unknown. |
| `setCallAudioEndpoint(endpoint)`   | Requests a route using an endpoint from the available list.                        |

Your existing SDK observer can also receive changes through `onAudioAvailableAudioEndpointsChanged(...)` and `onAudioEndpointChanged(...)`.
To choose a route when a call starts, implement `Observer.getStartingAudioEndpoint(...)` and return one of the supplied endpoints, or `null` to use the default.

Refresh your route picker when the available list changes, including after a strategy switch or permission update.
Use the current endpoint updates to show the route actually in use after a selection request.

## Updating permissions during a call

After your app receives a runtime permission grant, notify the SDK so it can refresh the affected audio components.
Both methods below can be called while a call is active.
See [Android permissions](permissions.md) for the required permissions and permission result handling.

### Bluetooth access

After obtaining `BLUETOOTH_CONNECT` permission, reload the endpoints:

```java
Instance.Audio.reloadAudioEndpoints();
```

This lets the SDK refresh Bluetooth device information and replace synthetic endpoints with endpoints for specific devices where available.
Update your route picker from the resulting endpoint list.

### Microphone access

After obtaining `RECORD_AUDIO` permission, refresh the recorder's permission state:

```java
Instance.Audio.reloadAudioRecorderPermissions();
```

This allows the SDK to update recording after permission is granted during an ongoing call.

## Testing system Telecom on a device

Some devices expose Android Telecom but fail when an app tries to use it.
The SDK provides a runtime test that exercises simulated outgoing and incoming calls through the system strategy.
These are local Telecom test calls; they do not place SIP or cellular calls.

Run the test only when no calls are active, and wait for it to finish before starting a call.
The SDK rejects attempts to add calls while the test is running.

```java
import cz.acrobits.commons.Disposable;

Disposable test = Instance.Telecom.testSystemAudioRoutingOnCurrentDevice(result -> {
    if (result.isSuccess()) {
        // System Telecom handled the simulated calls successfully.
    } else {
        // Inspect result.getFailureReasonOrNull() and update your UI.
    }
});
```

The test is asynchronous and returns an `AudioRoutingTestResult` to the callback.
Possible failure reasons include `ActiveCallsPresent`, `TestAlreadyRunning`, `SystemStrategyNotAvailable`, `TestTimedOut`, `SingleOutgoingCallFailed`, `SingleIncomingCallFailed`, and `UnknownError`.
The returned `Disposable` lets you cancel a test that is still running by calling `dispose()`.

The test checks whether system Telecom can handle the simulated call lifecycle; success does not verify microphone input or audible playback.
It does not change `defaultTelecomStrategy` automatically.
Your app can use the result to help the user choose between `system` and `compat`.

## Migrating from earlier SDK versions

When upgrading to `26.1` or later:

1. Remove your app's custom `ConnectionService` implementation and its service declaration from the manifest.
2. Remove the app code that registers the old service's `PhoneAccount`. You don't need to unregister them, Android Framework will do that automatically when the service is removed.
3. Use `defaultTelecomStrategy` to select the preferred routing strategy.
4. Update audio route selection code to use SDK-provided `AudioEndpoint` objects and respond to endpoint list changes.
5. Notify the SDK after Bluetooth or microphone permission is granted at runtime.

The [legacy ConnectionService integration guide](connectionservice.md) applies to SDK versions before `26.1`.

