Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4ddd1aa authored by Grace Jia's avatar Grace Jia Committed by Xiaotong Jia
Browse files

Improve BT ICS binding/unbinding timing.

Separately bind and unbind bluetooth InCallService to improve call audio
via bluetooth devices.

Bug: b/306395598
Test: CallsManagerTest, InCallControllerTest
Change-Id: I68ee98eed46fccbb8b8d4674a0d8d44bc8dd1122
parent 2a733157
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -13,3 +13,10 @@ flag {
  description: "Ensure that users are able to return to call from keyguard UI for ECC"
  bug: "306582821"
}

flag {
  name: "separately_bind_to_bt_incall_service"
  namespace: "telecom"
  description: "Binding/Unbinding to BluetoothInCallServices in proper time to improve call audio"
  bug: "306395598"
}
+3 −0
Original line number Diff line number Diff line
@@ -79,4 +79,7 @@
    <!-- When true, the options in the call blocking settings to block unavailable and unknown
     callers are combined into a single toggle. -->
    <bool name="combine_options_to_block_unavailable_and_unknown_callers">true</bool>

    <!-- System bluetooth stack package name -->
    <string name="system_bluetooth_stack">com.android.bluetooth</string>
</resources>
+32 −3
Original line number Diff line number Diff line
@@ -27,13 +27,11 @@ import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.OutcomeReceiver;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -73,7 +71,6 @@ 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;
@@ -95,6 +92,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@@ -796,6 +794,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
     */
    private CompletableFuture<Boolean> mDisconnectFuture;

    /**
     * {@link CompletableFuture} used to delay audio routing change for a ringing call until the
     * corresponding bluetooth {@link android.telecom.InCallService} is successfully bound or timed
     * out.
     */
    private CompletableFuture<Boolean> mBtIcsFuture;

    private FeatureFlags mFlags;

    /**
@@ -4692,6 +4697,30 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        }
    }

    /**
     * Set the bluetooth {@link android.telecom.InCallService} binding completion or timeout future
     * which is used to delay the audio routing change after the bluetooth stack get notified about
     * the ringing calls.
     * @param btIcsFuture the {@link CompletableFuture}
     */
    public void setBtIcsFuture(CompletableFuture<Boolean> btIcsFuture) {
        mBtIcsFuture = btIcsFuture;
    }

    /**
     * Wait for bluetooth {@link android.telecom.InCallService} binding completion or timeout. Used
     * for audio routing operations for a ringing call.
     */
    public void waitForBtIcs() {
        if (mBtIcsFuture != null) {
            try {
                mBtIcsFuture.get();
            } catch (InterruptedException | ExecutionException e) {
                // ignore
            }
        }
    }

    /**
     * @return {@code true} if the connection has been created by the underlying
     * {@link ConnectionService}, {@code false} otherwise.
+4 −0
Original line number Diff line number Diff line
@@ -750,6 +750,10 @@ public class CallAudioManager extends CallsManagerListenerBase {

    private void onCallEnteringRinging() {
        if (mRingingCalls.size() == 1) {
            // Wait until the BT ICS binding completed to request further audio route change
            for (Call ringingCall: mRingingCalls) {
                ringingCall.waitForBtIcs();
            }
            mCallAudioModeStateMachine.sendMessageWithArgs(
                    CallAudioModeStateMachine.NEW_RINGING_CALL,
                    makeArgsForModeStateMachine());
+12 −4
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -962,8 +963,10 @@ public class CallsManager extends Call.ListenerBase

        if (incomingCall.getState() != CallState.DISCONNECTED &&
                incomingCall.getState() != CallState.DISCONNECTING) {
            if (!mFeatureFlags.separatelyBindToBtIncallService()) {
                setCallState(incomingCall, CallState.RINGING,
                        result.shouldAllowCall ? "successful incoming call" : "blocking call");
            }
        } else {
            Log.i(this, "onCallFilteringCompleted: call already disconnected.");
            return;
@@ -1008,6 +1011,10 @@ public class CallsManager extends Call.ListenerBase
        }

        if (result.shouldAllowCall) {
            if (mFeatureFlags.separatelyBindToBtIncallService()) {
                incomingCall.setBtIcsFuture(mInCallController.bindToBTService(incomingCall));
                setCallState(incomingCall, CallState.RINGING, "successful incoming call");
            }
            incomingCall.setPostCallPackageName(
                    getRoleManagerAdapter().getDefaultCallScreeningApp(
                            incomingCall.getAssociatedUser()
@@ -1022,7 +1029,6 @@ public class CallsManager extends Call.ListenerBase
                            "Exceeds maximum number of ringing calls.");
                    incomingCall.setMissedReason(AUTO_MISSED_MAXIMUM_RINGING);
                    autoMissCallAndLog(incomingCall, result);
                    return;
                }
            } else if (hasMaximumManagedDialingCalls(incomingCall)) {
                if (shouldSilenceInsteadOfReject(incomingCall)) {
@@ -1032,7 +1038,6 @@ public class CallsManager extends Call.ListenerBase
                            "dialing calls.");
                    incomingCall.setMissedReason(AUTO_MISSED_MAXIMUM_DIALING);
                    autoMissCallAndLog(incomingCall, result);
                    return;
                }
            } else if (result.shouldScreenViaAudio) {
                Log.i(this, "onCallFilteringCompleted: starting background audio processing");
@@ -1051,6 +1056,9 @@ public class CallsManager extends Call.ListenerBase
        } else {
            if (result.shouldReject) {
                Log.i(this, "onCallFilteringCompleted: blocked call, rejecting.");
                if (mFeatureFlags.separatelyBindToBtIncallService()) {
                    setCallState(incomingCall, CallState.RINGING, "blocking call");
                }
                incomingCall.reject(false, null);
            }
            if (result.shouldAddToCallLog) {
Loading