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

Commit d70141c7 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Correct DND audio focus issue related to VoIP calls.

The `IncomingCallFilterGraph` includes the `DndFilter` which is used to
compute `AudioManager#matchesCallFilter`.  The existing behavior is to
use the output of this to set `Call#setCallIsSuppressedByDoNotDisturb`.
When the call filtering graph is bypassed, as it is for VoIP calls, we
end up setting `setCallIsSuppressedByDoNotDisturb` to `false`, which
means that we will always get audio focus for the call.

To fix this changed the `CallFilteringResult` so that the DND suppression
status can be either "not determined", "suppressed" or "not suppressed".
By default it will be "not determined".  This way when we skip the the
call filtering graph and use the default filtering result, it will be
"not determined".  As a result, `Ringer` will no longer see that the
DND suppression status is "false" in this case.

The next problem we had was in Ringer.java itself.  The logic to determine
if `shouldAcquireAudioFocus` ALWAYS returned true for Voip.  Realistically
VoIP should take into account DND and zero volume for the ringer as well.
The comments tell the story if you want to know more.

Test: Added CallFilteringResultTest to test behavior of the tri-state
dnd status as combined in call filtering results.
Test: Updated RingerTest to verify behavior when no DND filter computation
took place.
Test: Added new CTS CUJ tests for these scenarios
Fixes: 415288638
Flag: com.android.server.telecom.flags.voip_dnd_focus
Change-Id: I8a8c8552a1a4787ded1ab744df8093cd00efe0b5

Change-Id: Ide76caa2cd2b1f9f90e4b13856bfa5b5d4d46558
parent f4760885
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -82,3 +82,14 @@ flag {
      purpose: PURPOSE_BUGFIX
    }
}

# OWNER=tgunn TARGET=25Q3
flag {
  name: "voip_dnd_focus"
  namespace: "telecom"
  description: "Ensure when call filtering is skipped that we do not use the DND filter results since they were not calculated"
  bug: "415288638"
  metadata {
      purpose: PURPOSE_BUGFIX
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -424,6 +424,8 @@ public class CallAudioModeStateMachine extends StateMachine {
                return;
            }

            // Note: startRinging will take DND into account; if a call is suppressed by DND,
            // the method will return false and we will not get audio focus.
            if (mCallAudioManager.startRinging()) {
                Log.i(this, "tryStartRinging: AudioManager#requestAudioFocus(RING)");
                mAudioManager.requestAudioFocusForCall(
+10 −1
Original line number Diff line number Diff line
@@ -1089,7 +1089,16 @@ public class CallsManager extends Call.ListenerBase
        }

        // Store the shouldSuppress value in the call object which will be passed to InCallServices
        if (mFeatureFlags.voipDndFocus()) {
            // The DND call filter may not have run (e.g. for VoIP calls); in this case we should
            // not set the DND suppression on the call to ensure Ringer.java will recalculate this
            // and not try to use an invalid cached value.
            if (result.isDndSuppressionDetermined()) {
                incomingCall.setCallIsSuppressedByDoNotDisturb(result.shouldSuppressDueToDnd());
            }
        } else {
            incomingCall.setCallIsSuppressedByDoNotDisturb(result.shouldSuppressCallDueToDndStatus);
        }

        // Inform our connection service that call filtering is done (if it was performed at all).
        if (incomingCall.isUsingCallFiltering()) {
+22 −6
Original line number Diff line number Diff line
@@ -341,6 +341,8 @@ public class Ringer {
                return false;
            }

            Log.i(this, "startRinging: attributes=%s", attributes);

            if (attributes.isEndEarly()) {
                boolean acquireAudioFocus = attributes.shouldAcquireAudioFocus();
                if (attributes.letDialerHandleRinging()) {
@@ -841,23 +843,37 @@ public class Ringer {
        if (endEarly) {
            Log.i(
                    this,
                    "Ending early -- letDialerHandleRinging=%s, isSelfManaged=%s, "
                    "getRingerAttributtes: ending -- letDialerHandleRinging=%s, isSelfManaged=%s, "
                            + "hasExternalRinger=%s, silentRingingRequested=%s, "
                            + "isWorkProfileInQuietMode=%s",
                            + "isWorkProfileInQuietMode=%s, shouldRingForContact=%s, "
                            + "isVolumeOverZero=%s",
                    letDialerHandleRinging,
                    isSelfManaged,
                    hasExternalRinger,
                    isSilentRingingRequested,
                    isWorkProfileInQuietMode);
                    isWorkProfileInQuietMode, shouldRingForContact, isVolumeOverZero);
        }

        // Acquire audio focus under any of the following conditions:
        // 1. Should ring for contact and there's an HFP device attached
        // 2. Volume is over zero, we should ring for the contact, and there's a audible ringtone
        //    present. (This check is deferred until ringer knows the ringtone)
        // 3. The call is self-managed.
        boolean shouldAcquireAudioFocus = !isWorkProfileInQuietMode &&
        boolean shouldAcquireAudioFocus;
        if (mFlags.voipDndFocus()) {
            shouldAcquireAudioFocus = !isWorkProfileInQuietMode &&
                    // The previous logic for determining if audio focus should be acquired
                    // assumed we should ALWAYS acquire audio focus for a voip call.  For non-voip
                    // calls, the value of shouldAcquireAudioFocus we calculate here is combined
                    // with other factors later such as whether the ringer volume is zero or if
                    // there is a ringtone present.
                    // For voip we should ideally only acquire ringing focus if DND didn't block the
                    // contact and the ringer volume is over zero.
                    ((!isSelfManaged && isHfpDeviceAttached && shouldRingForContact)
                            || isSelfManaged && shouldRingForContact && isVolumeOverZero);
        } else {
            shouldAcquireAudioFocus = !isWorkProfileInQuietMode &&
                    ((isHfpDeviceAttached && shouldRingForContact) || isSelfManaged);
        }

        // Set missed reason according to attributes
        if (!isVolumeOverZero) {
+15 −0
Original line number Diff line number Diff line
@@ -75,6 +75,21 @@ public class RingerAttributes {
    }

    private boolean mEndEarly;

    @Override
    public String toString() {
        return "RingerAttributes{" +
                "mEndEarly=" + mEndEarly +
                ", mLetDialerHandleRinging=" + mLetDialerHandleRinging +
                ", mAcquireAudioFocus=" + mAcquireAudioFocus +
                ", mRingerAudible=" + mRingerAudible +
                ", mInaudibleReason='" + mInaudibleReason + '\'' +
                ", mShouldRingForContact=" + mShouldRingForContact +
                ", mSilentRingingRequested=" + mSilentRingingRequested +
                ", mWorkProfileQuietMode=" + mWorkProfileQuietMode +
                '}';
    }

    private boolean mLetDialerHandleRinging;
    private boolean mAcquireAudioFocus;
    private boolean mRingerAudible;
Loading