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

Commit 8f3a7152 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Create CallAudioWatchdog.

To aid in debugging voip app audio issues, add a CallAudioWatchdog which
watches the audio record and playback resources that voip apps allocate
and includes information about this in the Telecom dumpsys.
Audio sessions for an app that does not use the Telecom framework are
also logged as non-telecom calls in the dumpsys to further aid in
debugging issues reported by users when apps don't use Telecom.

Flag: com.android.server.telecom.flags.enable_call_audio_watchdog
Test: Added CallAudioWatchDog test.
Test: Performed manual testing with telecom aware and non-aware voip apps
to verify logging.
Bug: 384570270

Change-Id: I8b4c21ee7ddd0585115e67429870b4059660b8ce
parent 226e9c5b
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -35,3 +35,14 @@ flag {
    purpose: PURPOSE_BUGFIX
  }
}

# OWNER=tgunn TARGET=25Q2
flag {
  name: "enable_call_audio_watchdog"
  namespace: "telecom"
  description: "Enables tracking of audio resources for voip calls to aid in diagnostics."
  bug: "384570270"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}
+659 −0

File added.

Preview size limit exceeded, changes collapsed.

+34 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.ResolveInfoFlags;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
@@ -502,6 +503,7 @@ public class CallsManager extends Call.ListenerBase
    private final com.android.internal.telephony.flags.FeatureFlags mTelephonyFeatureFlags;

    private final IncomingCallFilterGraphProvider mIncomingCallFilterGraphProvider;
    private final CallAudioWatchdog mCallAudioWatchDog;

    private final ConnectionServiceFocusManager.CallsManagerRequester mRequester =
            new ConnectionServiceFocusManager.CallsManagerRequester() {
@@ -648,6 +650,31 @@ public class CallsManager extends Call.ListenerBase
        mCallerInfoLookupHelper = callerInfoLookupHelper;
        mEmergencyCallDiagnosticLogger = emergencyCallDiagnosticLogger;
        mIncomingCallFilterGraphProvider = incomingCallFilterGraphProvider;
        if (featureFlags.enableCallAudioWatchdog()) {
            mCallAudioWatchDog = new CallAudioWatchdog(
                    mContext.getSystemService(AudioManager.class),
                    new CallAudioWatchdog.PhoneAccountRegistrarProxy() {
                        @Override
                        public boolean hasPhoneAccountForUid(int uid) {
                            return mPhoneAccountRegistrar.hasPhoneAccountForUid(uid);
                        }

                        @Override
                        public int getUidForPhoneAccountHandle(PhoneAccountHandle handle) {
                            Context userContext = mContext.createContextAsUser(
                                    handle.getUserHandle(),
                                    0 /*flags */);
                            try {
                                return userContext.getPackageManager().getPackageUid(
                                        handle.getComponentName().getPackageName(), 0 /* flags */);
                            } catch (NameNotFoundException nfe) {
                                return -1;
                            }
                        }
                    }, clockProxy, mHandler);
        } else {
            mCallAudioWatchDog = null;
        }

        mDtmfLocalTonePlayer =
                new DtmfLocalTonePlayer(new DtmfLocalTonePlayer.ToneGeneratorProxy());
@@ -779,6 +806,9 @@ public class CallsManager extends Call.ListenerBase
        mListeners.add(mPhoneStateBroadcaster);
        mListeners.add(mVoipCallMonitor);
        mListeners.add(mCallStreamingNotification);
        if (featureFlags.enableCallAudioWatchdog()) {
            mListeners.add(mCallAudioWatchDog);
        }

        mVoipCallMonitor.startMonitor();

@@ -6238,6 +6268,10 @@ public class CallsManager extends Call.ListenerBase
            mConnectionSvrFocusMgr.dump(pw);
            pw.decreaseIndent();
        }

        if (mCallAudioWatchDog != null) {
            mCallAudioWatchDog.dump(pw);
        }
    }

    /**
+1 −0
Original line number Diff line number Diff line
@@ -230,6 +230,7 @@ public class LogUtils {
        public static final String LOST_FGS_DELEGATION = "LOST_FGS_DELEGATION";
        public static final String START_STREAMING = "START_STREAMING";
        public static final String STOP_STREAMING = "STOP_STREAMING";
        public static final String AUDIO_ATTR = "AUDIO_ATTR";

        public static class Timings {
            public static final String ACCEPT_TIMING = "accept";
+21 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ import java.lang.Integer;
import java.lang.SecurityException;
import java.lang.String;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -2940,4 +2941,24 @@ public class PhoneAccountRegistrar {
            return null;
        }
    };

    /**
     * Determines if an app specified by a uid has a phone account for that uid.
     * @param uid the uid to check
     * @return {@code true} if there is a phone account for that UID, {@code false} otherwise.
     */
    public boolean hasPhoneAccountForUid(int uid) {
        String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
        if (packageNames == null || packageNames.length == 0) {
            return false;
        }
        UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
        return mState.accounts.stream()
                .anyMatch(p -> {
                    PhoneAccountHandle handle = p.getAccountHandle();
                    return handle.getUserHandle().equals(userHandle)
                            && Arrays.stream(packageNames).anyMatch( s -> s.equals(
                                    handle.getComponentName().getPackageName()));
                });
    }
}
Loading