Search in sources :

Example 41 with ImsCall

use of com.android.ims.ImsCall in project android_frameworks_opt_telephony by LineageOS.

the class ImsPhoneCallTracker method resumeForegroundCall.

private void resumeForegroundCall() throws ImsException {
    // resume foreground call after holding background call
    // they were switched before holding
    ImsCall imsCall = mForegroundCall.getImsCall();
    if (imsCall != null) {
        imsCall.resume();
        mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(), ImsCommand.IMS_CMD_RESUME);
    }
}
Also used : ImsCall(com.android.ims.ImsCall)

Example 42 with ImsCall

use of com.android.ims.ImsCall 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 43 with ImsCall

use of com.android.ims.ImsCall in project android_frameworks_opt_telephony by LineageOS.

the class ImsPhoneCallTracker method onDataEnabledChanged.

/**
 * Handler of data enabled changed event
 * @param enabled True if data is enabled, otherwise disabled.
 * @param reason Reason for data enabled/disabled. See {@link DataEnabledChangedReason}.
 */
private void onDataEnabledChanged(boolean enabled, @DataEnabledChangedReason int reason) {
    log("onDataEnabledChanged: enabled=" + enabled + ", reason=" + reason);
    mIsDataEnabled = enabled;
    if (!mIsViLteDataMetered) {
        log("Ignore data " + ((enabled) ? "enabled" : "disabled") + " - carrier policy " + "indicates that data is not metered for ViLTE calls.");
        return;
    }
    // if this is an LTE call.
    for (ImsPhoneConnection conn : mConnections) {
        ImsCall imsCall = conn.getImsCall();
        boolean isLocalVideoCapable = enabled || (imsCall != null && imsCall.isWifiCall());
        conn.setLocalVideoCapable(isLocalVideoCapable);
    }
    int reasonCode;
    if (reason == DataEnabledSettings.REASON_POLICY_DATA_ENABLED) {
        reasonCode = ImsReasonInfo.CODE_DATA_LIMIT_REACHED;
    } else if (reason == DataEnabledSettings.REASON_USER_DATA_ENABLED) {
        reasonCode = ImsReasonInfo.CODE_DATA_DISABLED;
    } else {
        // Unexpected code, default to data disabled.
        reasonCode = ImsReasonInfo.CODE_DATA_DISABLED;
    }
    // Potentially send connection events so the InCall UI knows that video calls are being
    // downgraded due to data being enabled/disabled.
    maybeNotifyDataDisabled(enabled, reasonCode);
    // Handle video state changes required as a result of data being enabled/disabled.
    handleDataEnabledChange(enabled, reasonCode);
    // the carrier config has loaded and will deregister IMS.
    if (!mShouldUpdateImsConfigOnDisconnect && reason != DataEnabledSettings.REASON_REGISTERED && mCarrierConfigLoaded) {
        // asynchronously notified that the availability of VT over LTE has changed.
        if (mImsManager != null) {
            mImsManager.updateImsServiceConfig(true);
        }
    }
}
Also used : ImsCall(com.android.ims.ImsCall) ImsMultiEndpoint(com.android.ims.ImsMultiEndpoint)

Example 44 with ImsCall

use of com.android.ims.ImsCall in project android_frameworks_opt_telephony by LineageOS.

the class ImsPhoneCallTracker method unholdHeldCall.

/**
 * Unhold the currently held call.
 */
public void unholdHeldCall() throws CallStateException {
    ImsCall imsCall = mBackgroundCall.getImsCall();
    if (mHoldSwitchingState == HoldSwapState.PENDING_SINGLE_CALL_UNHOLD || mHoldSwitchingState == HoldSwapState.SWAPPING_ACTIVE_AND_HELD) {
        logi("Ignoring unhold request while already unholding or swapping");
        return;
    }
    if (imsCall != null) {
        mCallExpectedToResume = imsCall;
        HoldSwapState oldHoldState = mHoldSwitchingState;
        mHoldSwitchingState = HoldSwapState.PENDING_SINGLE_CALL_UNHOLD;
        mForegroundCall.switchWith(mBackgroundCall);
        logHoldSwapState("unholdCurrentCall");
        try {
            imsCall.resume();
            mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(), ImsCommand.IMS_CMD_RESUME);
        } catch (ImsException e) {
            mForegroundCall.switchWith(mBackgroundCall);
            mHoldSwitchingState = oldHoldState;
            logHoldSwapState("unholdCurrentCall - fail");
            throw new CallStateException(e.getMessage());
        }
    }
}
Also used : CallStateException(com.android.internal.telephony.CallStateException) ImsCall(com.android.ims.ImsCall) ImsException(com.android.ims.ImsException)

Example 45 with ImsCall

use of com.android.ims.ImsCall in project android_frameworks_opt_telephony by LineageOS.

the class ImsPhoneCallTracker method acceptCall.

/**
 * Accepts a call with the specified video state.  The video state is the video state that the
 * user has agreed upon in the InCall UI.
 *
 * @param videoState The video State
 * @throws CallStateException
 */
public void acceptCall(int videoState) throws CallStateException {
    if (DBG)
        log("acceptCall");
    mOperationLocalLog.log("accepted incoming call");
    if (mForegroundCall.getState().isAlive() && mBackgroundCall.getState().isAlive()) {
        throw new CallStateException("cannot accept call");
    }
    if ((mRingingCall.getState() == ImsPhoneCall.State.WAITING) && mForegroundCall.getState().isAlive()) {
        setMute(false);
        boolean answeringWillDisconnect = false;
        ImsCall activeCall = mForegroundCall.getImsCall();
        ImsCall ringingCall = mRingingCall.getImsCall();
        if (mForegroundCall.hasConnections() && mRingingCall.hasConnections()) {
            answeringWillDisconnect = shouldDisconnectActiveCallOnAnswer(activeCall, ringingCall);
        }
        // Cache video state for pending MT call.
        mPendingCallVideoState = videoState;
        if (answeringWillDisconnect) {
            // We need to disconnect the foreground call before answering the background call.
            mForegroundCall.hangup();
            mPhone.getVoiceCallSessionStats().onImsAcceptCall(mRingingCall.getConnections());
            try {
                ringingCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
            } catch (ImsException e) {
                throw new CallStateException("cannot accept call");
            }
        } else {
            holdActiveCallForWaitingCall();
        }
    } else if (mRingingCall.getState().isRinging()) {
        if (DBG)
            log("acceptCall: incoming...");
        // Always unmute when answering a new call
        setMute(false);
        try {
            ImsCall imsCall = mRingingCall.getImsCall();
            if (imsCall != null) {
                mPhone.getVoiceCallSessionStats().onImsAcceptCall(mRingingCall.getConnections());
                imsCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
                mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(), ImsCommand.IMS_CMD_ACCEPT);
            } else {
                throw new CallStateException("no valid ims call");
            }
        } catch (ImsException e) {
            throw new CallStateException("cannot accept call");
        }
    } else {
        throw new CallStateException("phone not ringing");
    }
}
Also used : CallStateException(com.android.internal.telephony.CallStateException) ImsCall(com.android.ims.ImsCall) ImsException(com.android.ims.ImsException)

Aggregations

ImsCall (com.android.ims.ImsCall)48 ImsException (com.android.ims.ImsException)19 SmallTest (android.test.suitebuilder.annotation.SmallTest)16 CallStateException (com.android.internal.telephony.CallStateException)16 TelephonyTest (com.android.internal.telephony.TelephonyTest)16 Test (org.junit.Test)16 ImsCallProfile (android.telephony.ims.ImsCallProfile)8 FlakyTest (androidx.test.filters.FlakyTest)8 RemoteException (android.os.RemoteException)6 Connection (com.android.internal.telephony.Connection)5 ImsPhoneCall (com.android.internal.telephony.imsphone.ImsPhoneCall)5 ImsPhone (com.android.internal.telephony.imsphone.ImsPhone)4 ImsReasonInfo (android.telephony.ims.ImsReasonInfo)3 ImsMultiEndpoint (com.android.ims.ImsMultiEndpoint)3 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)3 Bundle (android.os.Bundle)2 PersistableBundle (android.os.PersistableBundle)2 TestConferenceEventPackageParser (com.android.internal.telephony.test.TestConferenceEventPackageParser)2 File (java.io.File)2 FileInputStream (java.io.FileInputStream)2