Search in sources :

Example 11 with ImsCallProfile

use of android.telephony.ims.ImsCallProfile in project android_frameworks_opt_telephony by LineageOS.

the class ImsPhoneConnection method updateMediaCapabilities.

/**
 * Check for a change in the video capabilities and audio quality for the {@link ImsCall}, and
 * update the {@link ImsPhoneConnection} with this information.
 *
 * @param imsCall The call to check for changes in media capabilities.
 * @return Whether the media capabilities have been changed.
 */
public boolean updateMediaCapabilities(ImsCall imsCall) {
    if (imsCall == null) {
        return false;
    }
    boolean changed = false;
    try {
        // The actual call profile (negotiated between local and peer).
        ImsCallProfile negotiatedCallProfile = imsCall.getCallProfile();
        if (negotiatedCallProfile != null) {
            int oldVideoState = getVideoState();
            int newVideoState = ImsCallProfile.getVideoStateFromImsCallProfile(negotiatedCallProfile);
            if (oldVideoState != newVideoState) {
                // unpaused state, we will resume passing the video states from the modem as is.
                if (VideoProfile.isPaused(oldVideoState) && !VideoProfile.isPaused(newVideoState)) {
                    // Video entered un-paused state; recognize updates from now on; we want to
                    // ensure that the new un-paused state is propagated to Telecom, so change
                    // this now.
                    mShouldIgnoreVideoStateChanges = false;
                }
                if (!mShouldIgnoreVideoStateChanges) {
                    updateVideoState(newVideoState);
                    changed = true;
                } else {
                    Rlog.d(LOG_TAG, "updateMediaCapabilities - ignoring video state change " + "due to paused state.");
                }
                if (!VideoProfile.isPaused(oldVideoState) && VideoProfile.isPaused(newVideoState)) {
                    // Video entered pause state; ignore updates until un-paused.  We do this
                    // after setVideoState is called above to ensure Telecom is notified that
                    // the device has entered paused state.
                    mShouldIgnoreVideoStateChanges = true;
                }
            }
            if (negotiatedCallProfile.mMediaProfile != null) {
                mIsRttEnabledForCall = negotiatedCallProfile.mMediaProfile.isRttCall();
                if (mIsRttEnabledForCall && mRttTextHandler == null) {
                    Rlog.d(LOG_TAG, "updateMediaCapabilities -- turning RTT on, profile=" + negotiatedCallProfile);
                    startRttTextProcessing();
                    onRttInitiated();
                    changed = true;
                    mOwner.getPhone().getVoiceCallSessionStats().onRttStarted(this);
                } else if (!mIsRttEnabledForCall && mRttTextHandler != null) {
                    Rlog.d(LOG_TAG, "updateMediaCapabilities -- turning RTT off, profile=" + negotiatedCallProfile);
                    mRttTextHandler.tearDown();
                    mRttTextHandler = null;
                    mRttTextStream = null;
                    onRttTerminated();
                    changed = true;
                }
            }
        }
        // Check for a change in the capabilities for the call and update
        // {@link ImsPhoneConnection} with this information.
        int capabilities = getConnectionCapabilities();
        // Use carrier config to determine if downgrading directly to audio-only is supported.
        if (mOwner.isCarrierDowngradeOfVtCallSupported()) {
            capabilities = addCapability(capabilities, Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE | Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
        } else {
            capabilities = removeCapability(capabilities, Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE | Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
        }
        // Get the current local call capabilities which might be voice or video or both.
        ImsCallProfile localCallProfile = imsCall.getLocalCallProfile();
        Rlog.v(LOG_TAG, "update localCallProfile=" + localCallProfile);
        if (localCallProfile != null) {
            capabilities = applyLocalCallCapabilities(localCallProfile, capabilities);
        }
        // Get the current remote call capabilities which might be voice or video or both.
        ImsCallProfile remoteCallProfile = imsCall.getRemoteCallProfile();
        Rlog.v(LOG_TAG, "update remoteCallProfile=" + remoteCallProfile);
        if (remoteCallProfile != null) {
            capabilities = applyRemoteCallCapabilities(remoteCallProfile, capabilities);
        }
        if (getConnectionCapabilities() != capabilities) {
            setConnectionCapabilities(capabilities);
            changed = true;
        }
        if (!mOwner.isViLteDataMetered()) {
            Rlog.v(LOG_TAG, "data is not metered");
        } else {
            if (mImsVideoCallProviderWrapper != null) {
                mImsVideoCallProviderWrapper.setIsVideoEnabled(hasCapabilities(Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
            }
        }
        // Metrics for audio codec
        if (localCallProfile != null && localCallProfile.mMediaProfile.mAudioQuality != mAudioCodec) {
            mAudioCodec = localCallProfile.mMediaProfile.mAudioQuality;
            mMetrics.writeAudioCodecIms(mOwner.mPhone.getPhoneId(), imsCall.getCallSession());
            mOwner.getPhone().getVoiceCallSessionStats().onAudioCodecChanged(this, mAudioCodec);
        }
        int newAudioQuality = getAudioQualityFromCallProfile(localCallProfile, remoteCallProfile);
        if (getAudioQuality() != newAudioQuality) {
            setAudioQuality(newAudioQuality);
            changed = true;
        }
    } catch (ImsException e) {
    // No session in place -- no change
    }
    return changed;
}
Also used : ImsCallProfile(android.telephony.ims.ImsCallProfile) ImsException(com.android.ims.ImsException)

Example 12 with ImsCallProfile

use of android.telephony.ims.ImsCallProfile in project android_frameworks_opt_telephony by LineageOS.

the class ImsPhoneConnection method updateAddressDisplay.

/**
 * Check for a change in the address display related fields for the {@link ImsCall}, and
 * update the {@link ImsPhoneConnection} with this information.
 *
 * @param imsCall The call to check for changes in address display fields.
 * @return Whether the address display fields have been changed.
 */
public boolean updateAddressDisplay(ImsCall imsCall) {
    if (imsCall == null) {
        return false;
    }
    boolean changed = false;
    ImsCallProfile callProfile = imsCall.getCallProfile();
    if (callProfile != null && isIncoming()) {
        // Only look for changes to the address for incoming calls.  The originating identity
        // can change for outgoing calls due to, for example, a call being forwarded to
        // voicemail.  This address change does not need to be presented to the user.
        String address = callProfile.getCallExtra(ImsCallProfile.EXTRA_OI);
        String name = callProfile.getCallExtra(ImsCallProfile.EXTRA_CNA);
        int nump = ImsCallProfile.OIRToPresentation(callProfile.getCallExtraInt(ImsCallProfile.EXTRA_OIR));
        int namep = ImsCallProfile.OIRToPresentation(callProfile.getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
        if (Phone.DEBUG_PHONE) {
            Rlog.d(LOG_TAG, "updateAddressDisplay: callId = " + getTelecomCallId() + " address = " + Rlog.pii(LOG_TAG, address) + " name = " + Rlog.pii(LOG_TAG, name) + " nump = " + nump + " namep = " + namep);
        }
        if (!mIsMergeInProcess) {
            // to the call address while a merge is in process.
            if (!equalsBaseDialString(mAddress, address)) {
                mAddress = address;
                changed = true;
            }
            if (TextUtils.isEmpty(name)) {
                if (!TextUtils.isEmpty(mCnapName)) {
                    mCnapName = "";
                    changed = true;
                }
            } else if (!name.equals(mCnapName)) {
                mCnapName = name;
                changed = true;
            }
            if (mNumberPresentation != nump) {
                mNumberPresentation = nump;
                changed = true;
            }
            if (mCnapNamePresentation != namep) {
                mCnapNamePresentation = namep;
                changed = true;
            }
        }
    }
    return changed;
}
Also used : ImsCallProfile(android.telephony.ims.ImsCallProfile)

Example 13 with ImsCallProfile

use of android.telephony.ims.ImsCallProfile in project android_frameworks_opt_telephony by LineageOS.

the class ImsPhoneConnection method updateExtras.

/**
 * Check for a change in call extras of {@link ImsCall}, and
 * update the {@link ImsPhoneConnection} accordingly.
 *
 * @param imsCall The call to check for changes in extras.
 * @return Whether the extras fields have been changed.
 */
boolean updateExtras(ImsCall imsCall) {
    if (imsCall == null) {
        return false;
    }
    final ImsCallProfile callProfile = imsCall.getCallProfile();
    final Bundle extras = callProfile != null ? callProfile.mCallExtras : null;
    if (extras == null && DBG) {
        Rlog.d(LOG_TAG, "Call profile extras are null.");
    }
    final boolean changed = !areBundlesEqual(extras, mExtras);
    if (changed) {
        updateImsCallRatFromExtras(extras);
        updateEmergencyCallFromExtras(extras);
        mExtras.clear();
        mExtras.putAll(extras);
        setConnectionExtras(mExtras);
    }
    return changed;
}
Also used : ImsCallProfile(android.telephony.ims.ImsCallProfile) Bundle(android.os.Bundle) PersistableBundle(android.os.PersistableBundle)

Example 14 with ImsCallProfile

use of android.telephony.ims.ImsCallProfile in project android_frameworks_opt_telephony by LineageOS.

the class ImsPhoneCallTracker method handleMessage.

// ****** Overridden from Handler
@Override
public void handleMessage(Message msg) {
    AsyncResult ar;
    if (DBG)
        log("handleMessage what=" + msg.what);
    switch(msg.what) {
        case EVENT_HANGUP_PENDINGMO:
            if (mPendingMO != null) {
                mPendingMO.onDisconnect();
                removeConnection(mPendingMO);
                mPendingMO = null;
            }
            mPendingIntentExtras = null;
            updatePhoneState();
            mPhone.notifyPreciseCallStateChanged();
            break;
        case EVENT_RESUME_NOW_FOREGROUND_CALL:
            try {
                resumeForegroundCall();
            } catch (ImsException e) {
                if (Phone.DEBUG_PHONE) {
                    loge("handleMessage EVENT_RESUME_NOW_FOREGROUND_CALL exception=" + e);
                }
            }
            break;
        case EVENT_ANSWER_WAITING_CALL:
            try {
                answerWaitingCall();
            } catch (ImsException e) {
                if (Phone.DEBUG_PHONE) {
                    loge("handleMessage EVENT_ANSWER_WAITING_CALL exception=" + e);
                }
            }
            break;
        case EVENT_DIAL_PENDINGMO:
            dialInternal(mPendingMO, mClirMode, mPendingCallVideoState, mPendingIntentExtras);
            mPendingIntentExtras = null;
            break;
        case EVENT_EXIT_ECBM_BEFORE_PENDINGMO:
            if (mPendingMO != null) {
                // Send ECBM exit request
                try {
                    getEcbmInterface().exitEmergencyCallbackMode();
                    mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
                    pendingCallClirMode = mClirMode;
                    pendingCallInEcm = true;
                } catch (ImsException e) {
                    e.printStackTrace();
                    mPendingMO.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
                    sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
                }
            }
            break;
        case EVENT_EXIT_ECM_RESPONSE_CDMA:
            // no matter the result, we still do the same here
            if (pendingCallInEcm) {
                dialInternal(mPendingMO, pendingCallClirMode, mPendingCallVideoState, mPendingIntentExtras);
                mPendingIntentExtras = null;
                pendingCallInEcm = false;
            }
            mPhone.unsetOnEcbModeExitResponse(this);
            break;
        case EVENT_VT_DATA_USAGE_UPDATE:
            ar = (AsyncResult) msg.obj;
            ImsCall call = (ImsCall) ar.userObj;
            Long usage = (long) ar.result;
            log("VT data usage update. usage = " + usage + ", imsCall = " + call);
            if (usage > 0) {
                updateVtDataUsage(call, usage);
            }
            break;
        case EVENT_DATA_ENABLED_CHANGED:
            ar = (AsyncResult) msg.obj;
            if (ar.result instanceof Pair) {
                Pair<Boolean, Integer> p = (Pair<Boolean, Integer>) ar.result;
                onDataEnabledChanged(p.first, p.second);
            }
            break;
        case EVENT_CHECK_FOR_WIFI_HANDOVER:
            if (msg.obj instanceof ImsCall) {
                ImsCall imsCall = (ImsCall) msg.obj;
                if (imsCall != mForegroundCall.getImsCall()) {
                    Rlog.i(LOG_TAG, "handoverCheck: no longer FG; check skipped.");
                    unregisterForConnectivityChanges();
                    // Handover check and its not the foreground call any more.
                    return;
                }
                if (!mHasAttemptedStartOfCallHandover) {
                    mHasAttemptedStartOfCallHandover = true;
                }
                if (!imsCall.isWifiCall()) {
                    // Call did not handover to wifi, notify of handover failure.
                    ImsPhoneConnection conn = findConnection(imsCall);
                    if (conn != null) {
                        Rlog.i(LOG_TAG, "handoverCheck: handover failed.");
                        conn.onHandoverToWifiFailed();
                    }
                    if (imsCall.isVideoCall() && conn.getDisconnectCause() == DisconnectCause.NOT_DISCONNECTED) {
                        registerForConnectivityChanges();
                    }
                }
            }
            break;
        case EVENT_ON_FEATURE_CAPABILITY_CHANGED:
            {
                SomeArgs args = (SomeArgs) msg.obj;
                try {
                    ImsFeature.Capabilities capabilities = (ImsFeature.Capabilities) args.arg1;
                    handleFeatureCapabilityChanged(capabilities);
                } finally {
                    args.recycle();
                }
                break;
            }
        case EVENT_SUPP_SERVICE_INDICATION:
            {
                ar = (AsyncResult) msg.obj;
                ImsPhoneMmiCode mmiCode = new ImsPhoneMmiCode(mPhone);
                try {
                    mmiCode.setIsSsInfo(true);
                    mmiCode.processImsSsData(ar);
                } catch (ImsException e) {
                    Rlog.e(LOG_TAG, "Exception in parsing SS Data: " + e);
                }
                break;
            }
        case EVENT_REDIAL_WIFI_E911_CALL:
            {
                Pair<ImsCall, ImsReasonInfo> callInfo = (Pair<ImsCall, ImsReasonInfo>) ((AsyncResult) msg.obj).userObj;
                removeMessages(EVENT_REDIAL_WIFI_E911_TIMEOUT);
                mPhone.getDefaultPhone().mCi.unregisterForOn(this);
                ImsPhoneConnection oldConnection = findConnection(callInfo.first);
                if (oldConnection == null) {
                    sendCallStartFailedDisconnect(callInfo.first, callInfo.second);
                    break;
                }
                mForegroundCall.detach(oldConnection);
                removeConnection(oldConnection);
                try {
                    Connection newConnection = mPhone.getDefaultPhone().dial(mLastDialString, mLastDialArgs);
                    oldConnection.onOriginalConnectionReplaced(newConnection);
                    final ImsCall imsCall = mForegroundCall.getImsCall();
                    final ImsCallProfile callProfile = imsCall.getCallProfile();
                    /* update EXTRA_EMERGENCY_CALL for clients to infer
                       from this extra that the call is emergency call */
                    callProfile.setCallExtraBoolean(ImsCallProfile.EXTRA_EMERGENCY_CALL, true);
                    ImsPhoneConnection conn = findConnection(imsCall);
                    conn.updateExtras(imsCall);
                } catch (CallStateException e) {
                    sendCallStartFailedDisconnect(callInfo.first, callInfo.second);
                }
                break;
            }
        case EVENT_REDIAL_WIFI_E911_TIMEOUT:
            {
                Pair<ImsCall, ImsReasonInfo> callInfo = (Pair<ImsCall, ImsReasonInfo>) msg.obj;
                mPhone.getDefaultPhone().mCi.unregisterForOn(this);
                removeMessages(EVENT_REDIAL_WIFI_E911_CALL);
                sendCallStartFailedDisconnect(callInfo.first, callInfo.second);
                break;
            }
        case EVENT_REDIAL_WITHOUT_RTT:
            {
                Pair<ImsCall, ImsReasonInfo> callInfo = (Pair<ImsCall, ImsReasonInfo>) msg.obj;
                removeMessages(EVENT_REDIAL_WITHOUT_RTT);
                ImsPhoneConnection oldConnection = findConnection(callInfo.first);
                if (oldConnection == null) {
                    sendCallStartFailedDisconnect(callInfo.first, callInfo.second);
                    break;
                }
                mForegroundCall.detach(oldConnection);
                removeConnection(oldConnection);
                try {
                    mPendingMO = null;
                    ImsDialArgs newDialArgs = ImsDialArgs.Builder.from(mLastDialArgs).setRttTextStream(null).setRetryCallFailCause(ImsReasonInfo.CODE_RETRY_ON_IMS_WITHOUT_RTT).setRetryCallFailNetworkType(ServiceState.rilRadioTechnologyToNetworkType(oldConnection.getCallRadioTech())).build();
                    Connection newConnection = mPhone.getDefaultPhone().dial(mLastDialString, newDialArgs);
                    oldConnection.onOriginalConnectionReplaced(newConnection);
                } catch (CallStateException e) {
                    sendCallStartFailedDisconnect(callInfo.first, callInfo.second);
                }
                break;
            }
    }
}
Also used : CallStateException(com.android.internal.telephony.CallStateException) ImsException(com.android.ims.ImsException) Connection(com.android.internal.telephony.Connection) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ImsFeature(android.telephony.ims.feature.ImsFeature) ImsDialArgs(com.android.internal.telephony.imsphone.ImsPhone.ImsDialArgs) SomeArgs(com.android.internal.os.SomeArgs) ImsCallProfile(android.telephony.ims.ImsCallProfile) ImsCall(com.android.ims.ImsCall) NetworkCapabilities(android.net.NetworkCapabilities) AsyncResult(android.os.AsyncResult) ImsReasonInfo(android.telephony.ims.ImsReasonInfo) Pair(android.util.Pair)

Example 15 with ImsCallProfile

use of android.telephony.ims.ImsCallProfile in project android_frameworks_opt_telephony by LineageOS.

the class TelephonyTester method testImsECall.

void testImsECall() {
    // Attempt to get the active IMS call before parsing the test XML file.
    ImsPhone imsPhone = (ImsPhone) mPhone;
    if (imsPhone == null) {
        return;
    }
    ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall();
    if (imsPhoneCall == null) {
        return;
    }
    ImsCall imsCall = imsPhoneCall.getImsCall();
    if (imsCall == null) {
        return;
    }
    ImsCallProfile callProfile = imsCall.getCallProfile();
    Bundle extras = callProfile.getCallExtras();
    if (extras == null) {
        extras = new Bundle();
    }
    extras.putBoolean(ImsCallProfile.EXTRA_EMERGENCY_CALL, true);
    callProfile.mCallExtras = extras;
    imsCall.getImsCallSessionListenerProxy().callSessionUpdated(imsCall.getSession(), callProfile);
}
Also used : ImsCallProfile(android.telephony.ims.ImsCallProfile) ImsCall(com.android.ims.ImsCall) Bundle(android.os.Bundle) ImsPhoneCall(com.android.internal.telephony.imsphone.ImsPhoneCall) ImsPhone(com.android.internal.telephony.imsphone.ImsPhone)

Aggregations

ImsCallProfile (android.telephony.ims.ImsCallProfile)16 ImsCall (com.android.ims.ImsCall)8 ImsException (com.android.ims.ImsException)8 RemoteException (android.os.RemoteException)5 SmallTest (android.test.suitebuilder.annotation.SmallTest)5 CallStateException (com.android.internal.telephony.CallStateException)5 Test (org.junit.Test)5 Connection (com.android.internal.telephony.Connection)4 TelephonyTest (com.android.internal.telephony.TelephonyTest)4 Bundle (android.os.Bundle)3 FlakyTest (androidx.test.filters.FlakyTest)3 ImsPhone (com.android.internal.telephony.imsphone.ImsPhone)2 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)2 InvocationOnMock (org.mockito.invocation.InvocationOnMock)2 ContentResolver (android.content.ContentResolver)1 Context (android.content.Context)1 NetworkCapabilities (android.net.NetworkCapabilities)1 AsyncResult (android.os.AsyncResult)1 Handler (android.os.Handler)1 IBinder (android.os.IBinder)1