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

Commit 9930c57c authored by Tyler Gunn's avatar Tyler Gunn Committed by Automerger Merge Worker
Browse files

Merge "Call Diagnostic Service implementation" am: f4f7063e

Original change: https://android-review.googlesource.com/c/platform/packages/services/Telecomm/+/1604772

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I63cde3ff5a1af9a9a9d89e35f3ed355336d50f01
parents 77b01841 f4f7063e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -69,4 +69,8 @@
    <!-- When true, the options in the call blocking settings to block restricted and unknown
         callers are combined into a single toggle. -->
    <bool name="combine_options_to_block_restricted_and_unknown_callers">true</bool>

    <!-- When set, Telecom will attempt to bind to the {@link CallDiagnosticService} implementation
         defined by the app with this package name. -->
    <string name="call_diagnostic_service_package_name"></string>
</resources>
+99 −0
Original line number Diff line number Diff line
@@ -37,11 +37,13 @@ import android.os.Trace;
import android.os.UserHandle;
import android.provider.CallLog;
import android.provider.ContactsContract.Contacts;
import android.telecom.BluetoothCallQualityReport;
import android.telecom.CallAudioState;
import android.telecom.CallerInfo;
import android.telecom.Conference;
import android.telecom.Connection;
import android.telecom.ConnectionService;
import android.telecom.DiagnosticCall;
import android.telecom.DisconnectCause;
import android.telecom.GatewayInfo;
import android.telecom.InCallService;
@@ -156,6 +158,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
                                 Bundle extras, boolean isLegacy);
        void onHandoverFailed(Call call, int error);
        void onHandoverComplete(Call call);
        void onBluetoothCallQualityReport(Call call, BluetoothCallQualityReport report);
        void onReceivedDeviceToDeviceMessage(Call call, int messageType, int messageValue);
    }

    public abstract static class ListenerBase implements Listener {
@@ -244,6 +248,10 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        public void onHandoverFailed(Call call, int error) {}
        @Override
        public void onHandoverComplete(Call call) {}
        @Override
        public void onBluetoothCallQualityReport(Call call, BluetoothCallQualityReport report) {}
        @Override
        public void onReceivedDeviceToDeviceMessage(Call call, int messageType, int messageValue) {}
    }

    private final CallerInfoLookupHelper.OnQueryCompleteListener mCallerInfoQueryListener =
@@ -646,6 +654,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
     */
    private String mCallScreeningComponentName;

    /**
     * When {@code true} indicates this call originated from a SIM-based {@link PhoneAccount}.
     * A sim-based {@link PhoneAccount} is one with {@link PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION}
     * set.
     */
    private boolean mIsSimCall;

    /**
     * Persists the specified parameters and initializes the new instance.
     * @param context The context.
@@ -1077,6 +1092,10 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        }
    }

    public void handleOverrideDisconnectMessage(@Nullable CharSequence message) {

    }

    /**
     * Sets the call state. Although there exists the notion of appropriate state transitions
     * (see {@link CallState}), in practice those expectations break down when cellular systems
@@ -1703,6 +1722,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        PhoneAccountRegistrar phoneAccountRegistrar = mCallsManager.getPhoneAccountRegistrar();
        boolean isWorkCall = false;
        boolean isCallRecordingToneSupported = false;
        boolean isSimCall = false;
        PhoneAccount phoneAccount =
                phoneAccountRegistrar.getPhoneAccountUnchecked(mTargetPhoneAccountHandle);
        if (phoneAccount != null) {
@@ -1720,9 +1740,11 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
                    PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) && phoneAccount.getExtras() != null
                    && phoneAccount.getExtras().getBoolean(
                    PhoneAccount.EXTRA_PLAY_CALL_RECORDING_TONE, false));
            isSimCall = phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
        }
        mIsWorkCall = isWorkCall;
        mUseCallRecordingTone = isCallRecordingToneSupported;
        mIsSimCall = isSimCall;
    }

    /**
@@ -2952,6 +2974,14 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
                }
                requestHandover(phoneAccountHandle, videoState, handoverExtrasBundle, true);
            } else {
                // Relay bluetooth call quality reports to the call diagnostic service.
                if (BluetoothCallQualityReport.EVENT_BLUETOOTH_CALL_QUALITY_REPORT.equals(event)
                        && extras.containsKey(
                        BluetoothCallQualityReport.EXTRA_BLUETOOTH_CALL_QUALITY_REPORT)) {
                    notifyBluetoothCallQualityReport(extras.getParcelable(
                            BluetoothCallQualityReport.EXTRA_BLUETOOTH_CALL_QUALITY_REPORT
                    ));
                }
                Log.addEvent(this, LogUtils.Events.CALL_EVENT, event);
                mConnectionService.sendCallEvent(this, event, extras);
            }
@@ -2961,6 +2991,17 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        }
    }

    /**
     * Notifies listeners when a bluetooth quality report is received.
     * @param report The bluetooth quality report.
     */
    void notifyBluetoothCallQualityReport(@NonNull BluetoothCallQualityReport report) {
        Log.addEvent(this, LogUtils.Events.BT_QUALITY_REPORT, "choppy=" + report.isChoppyVoice());
        for (Listener l : mListeners) {
            l.onBluetoothCallQualityReport(this, report);
        }
    }

    /**
     * Initiates a handover of this Call to the {@link ConnectionService} identified
     * by destAcct.
@@ -3691,6 +3732,17 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
            for (Listener l : mListeners) {
                l.onCallSwitchFailed(this);
            }
        } else if (Connection.EVENT_DEVICE_TO_DEVICE_MESSAGE.equals(event)
                && extras != null && extras.containsKey(
                Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_TYPE)
                && extras.containsKey(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE)) {
            // Relay an incoming D2D message to interested listeners; most notably the
            // CallDiagnosticService.
            int messageType = extras.getInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_TYPE);
            int messageValue = extras.getInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE);
            for (Listener l : mListeners) {
                l.onReceivedDeviceToDeviceMessage(this, messageType, messageValue);
            }
        } else {
            for (Listener l : mListeners) {
                l.onConnectionEvent(this, event, extras);
@@ -3891,6 +3943,44 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        }
    }

    /**
     * Sends a device to device message to the other part of the call.
     * @param message the message type to send.
     * @param value the value for the message.
     */
    public void sendDeviceToDeviceMessage(@DiagnosticCall.MessageType int message, int value) {
        Log.i(this, "sendDeviceToDeviceMessage; callId=%s, msg=%d/%d", getId(), message, value);
        Bundle extras = new Bundle();
        extras.putInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_TYPE, message);
        extras.putInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE, value);
        // Send to the connection service.
        sendCallEvent(Connection.EVENT_DEVICE_TO_DEVICE_MESSAGE, extras);
    }

    /**
     * Signals to the Dialer app to start displaying a diagnostic message.
     * @param messageId a unique ID for the message to display.
     * @param message the message to display.
     */
    public void displayDiagnosticMessage(int messageId, @NonNull CharSequence message) {
        Bundle extras = new Bundle();
        extras.putInt(android.telecom.Call.EXTRA_DIAGNOSTIC_MESSAGE_ID, messageId);
        extras.putCharSequence(android.telecom.Call.EXTRA_DIAGNOSTIC_MESSAGE, message);
        // Send to the dialer.
        onConnectionEvent(android.telecom.Call.EVENT_DISPLAY_DIAGNOSTIC_MESSAGE, extras);
    }

    /**
     * Signals to the Dialer app to stop displaying a diagnostic message.
     * @param messageId a unique ID for the message to clear.
     */
    public void clearDiagnosticMessage(int messageId) {
        Bundle extras = new Bundle();
        extras.putInt(android.telecom.Call.EXTRA_DIAGNOSTIC_MESSAGE_ID, messageId);
        // Send to the dialer.
        onConnectionEvent(android.telecom.Call.EVENT_CLEAR_DIAGNOSTIC_MESSAGE, extras);
    }

    /**
     * Remaps the call direction as indicated by an {@link android.telecom.Call.Details} direction
     * constant to the constants (e.g. {@link #CALL_DIRECTION_INCOMING}) used in this call class.
@@ -3977,4 +4067,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
            }
        }
    }

    /**
     * @return {@code true} when this call originated from a SIM-based {@link PhoneAccount}.
     * A sim-based {@link PhoneAccount} is one with {@link PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION}
     * set.
     */
    public boolean isSimCall() {
        return mIsSimCall;
    }
}
+132 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.telecom;

import android.annotation.NonNull;
import android.os.Binder;
import android.os.RemoteException;
import android.telecom.CallDiagnosticService;
import android.telecom.DiagnosticCall;
import android.telecom.Log;

import com.android.internal.telecom.ICallDiagnosticServiceAdapter;
import com.android.internal.telecom.IInCallAdapter;

/**
 * Adapter class used to provide a path for messages FROM a {@link CallDiagnosticService} back to
 * the telecom stack.
 */
public class CallDiagnosticServiceAdapter extends ICallDiagnosticServiceAdapter.Stub {
    public interface TelecomAdapter {
        void displayDiagnosticMessage(String callId, int messageId, CharSequence message);
        void clearDiagnosticMessage(String callId, int messageId);
        void sendDeviceToDeviceMessage(String callId, @DiagnosticCall.MessageType int message,
                int value);
        void overrideDisconnectMessage(String callId, CharSequence message);
    }

    private final TelecomAdapter mTelecomAdapter;
    private final String mOwnerPackageName;
    private final String mOwnerPackageAbbreviation;
    private final TelecomSystem.SyncRoot mLock;

    CallDiagnosticServiceAdapter(@NonNull TelecomAdapter telecomAdapter,
            @NonNull String ownerPackageName, @NonNull TelecomSystem.SyncRoot lock) {
        mTelecomAdapter = telecomAdapter;
        mOwnerPackageName = ownerPackageName;
        mOwnerPackageAbbreviation = Log.getPackageAbbreviation(ownerPackageName);
        mLock = lock;
    }

    @Override
    public void displayDiagnosticMessage(String callId, int messageId, CharSequence message)
            throws RemoteException {
        try {
            Log.startSession("CDSA.dDM", mOwnerPackageAbbreviation);
            long token = Binder.clearCallingIdentity();
            try {
                synchronized (mLock) {
                    Log.i(this, "displayDiagnosticMessage; callId=%s, msg=%d/%s", callId, messageId,
                            message);
                    mTelecomAdapter.displayDiagnosticMessage(callId, messageId, message);
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        } finally {
            Log.endSession();
        }
    }

    @Override
    public void clearDiagnosticMessage(String callId, int messageId) throws RemoteException {
        try {
            Log.startSession("CDSA.cDM", mOwnerPackageAbbreviation);
            long token = Binder.clearCallingIdentity();
            try {
                synchronized (mLock) {
                    Log.i(this, "clearDiagnosticMessage; callId=%s, msg=%d", callId, messageId);
                    mTelecomAdapter.clearDiagnosticMessage(callId, messageId);
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        } finally {
            Log.endSession();
        }
    }

    @Override
    public void sendDeviceToDeviceMessage(String callId, @DiagnosticCall.MessageType int message,
            int value)
            throws RemoteException {
        try {
            Log.startSession("CDSA.sDTDM", mOwnerPackageAbbreviation);
            long token = Binder.clearCallingIdentity();
            try {
                synchronized (mLock) {
                    Log.i(this, "sendDeviceToDeviceMessage; callId=%s, msg=%d/%d", callId, message,
                            value);
                    mTelecomAdapter.sendDeviceToDeviceMessage(callId, message, value);
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        } finally {
            Log.endSession();
        }
    }

    @Override
    public void overrideDisconnectMessage(String callId, CharSequence message)
            throws RemoteException {
        try {
            Log.startSession("CDSA.oDM", mOwnerPackageAbbreviation);
            long token = Binder.clearCallingIdentity();
            try {
                synchronized (mLock) {
                    Log.i(this, "overrideDisconnectMessage; callId=%s, msg=%s", callId, message);
                    mTelecomAdapter.overrideDisconnectMessage(callId, message);
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        } finally {
            Log.endSession();
        }
    }
}
+654 −0

File added.

Preview size limit exceeded, changes collapsed.

+34 −15
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ public class CallsManager extends Call.ListenerBase
    private final ConnectionServiceRepository mConnectionServiceRepository;
    private final DtmfLocalTonePlayer mDtmfLocalTonePlayer;
    private final InCallController mInCallController;
    private final CallDiagnosticServiceController mCallDiagnosticServiceController;
    private final CallAudioManager mCallAudioManager;
    private final CallRecordingTonePlayer mCallRecordingTonePlayer;
    private RespondViaSmsManager mRespondViaSmsManager;
@@ -487,6 +488,7 @@ public class CallsManager extends Call.ListenerBase
            CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory,
            CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory,
            InCallControllerFactory inCallControllerFactory,
            CallDiagnosticServiceController callDiagnosticServiceController,
            RoleManagerAdapter roleManagerAdapter,
            ToastFactory toastFactory) {
        mContext = context;
@@ -543,6 +545,7 @@ public class CallsManager extends Call.ListenerBase
        mInCallController = inCallControllerFactory.create(context, mLock, this,
                systemStateHelper, defaultDialerCache, mTimeoutsAdapter,
                emergencyCallHelper);
        mCallDiagnosticServiceController = callDiagnosticServiceController;
        mRinger = new Ringer(playerFactory, context, systemSettingsUtil, asyncRingtonePlayer,
                ringtoneFactory, systemVibrator,
                new Ringer.VibrationEffectProxy(), mInCallController);
@@ -572,6 +575,7 @@ public class CallsManager extends Call.ListenerBase
        mListeners.add(mCallLogManager);
        mListeners.add(mPhoneStateBroadcaster);
        mListeners.add(mInCallController);
        mListeners.add(mCallDiagnosticServiceController);
        mListeners.add(mCallAudioManager);
        mListeners.add(mCallRecordingTonePlayer);
        mListeners.add(missedCallNotifier);
@@ -622,6 +626,10 @@ public class CallsManager extends Call.ListenerBase
        return mRoleManagerAdapter;
    }

    public CallDiagnosticServiceController getCallDiagnosticServiceController() {
        return mCallDiagnosticServiceController;
    }

    @Override
    public void onSuccessfulOutgoingCall(Call call, int callState) {
        Log.v(this, "onSuccessfulOutgoingCall, %s", call);
@@ -3631,7 +3639,16 @@ public class CallsManager extends Call.ListenerBase
                Trace.beginSection("onCallStateChanged");

                maybeHandleHandover(call, newState);
                notifyCallStateChanged(call, oldState, newState);

                Trace.endSection();
            } else {
                Log.i(this, "failed in setting the state to new state");
            }
        }
    }

    private void notifyCallStateChanged(Call call, int oldState, int newState) {
        // Only broadcast state change for calls that are being tracked.
        if (mCalls.contains(call)) {
            updateCanAddCall();
@@ -3647,11 +3664,6 @@ public class CallsManager extends Call.ListenerBase
                }
            }
        }
                Trace.endSection();
            } else {
                Log.i(this, "failed in setting the state to new state");
            }
        }
    }

    /**
@@ -4691,6 +4703,13 @@ public class CallsManager extends Call.ListenerBase
            pw.decreaseIndent();
        }

        if (mCallDiagnosticServiceController != null) {
            pw.println("mCallDiagnosticServiceController:");
            pw.increaseIndent();
            mCallDiagnosticServiceController.dump(pw);
            pw.decreaseIndent();
        }

        if (mDefaultDialerCache != null) {
            pw.println("mDefaultDialerCache:");
            pw.increaseIndent();
Loading