cdma拨号的细节记录

cdma拨号是没有alerting状态的,即接通基站后就是active状态。所以即使对方没有接通,手机也会开始通话计时。


通话时间重置问题

针对这种问题,运营商后续加入了接通的上报事件,这样接通后手机的计时会重置。

google原生是没有这个功能的,这就导致后续各个厂商各种不同的实现。

mtk的实现

packages/services/Telephony/src/com/android/services/telephony/TelephonyConnection.java

                case EVENT_CDMA_CALL_ACCEPTED:
                    Log.v(TelephonyConnection.this, "EVENT_CDMA_CALL_ACCEPTED");
                    updateConnectionCapabilities();
                    fireOnCdmaCallAccepted();
EVENT_CDMA_CALL_ACCEPTED消息处理

frameworks/base/telecomm/java/android/telecom/Connection.java

    protected void fireOnCdmaCallAccepted() {
        Log.d(this, "fireOnCdmaCallAccepted: %s", stateToString(mState));
        for (Listener l : mListeners) {
            l.onCdmaCallAccepted(this);
        }
    }
中间的具体流程不再赘述,Telephony,Telecomm.InCallUI三个app之间的数据传递之前有文章讲过,见 短信拒接流程

packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java

    void notifyCdmaCallAccepted(Call call) {
        /// M: ALPS02445100. Update addCall capapility when cdma call accepted.  @{
        updateCanAddCall();
        /// @}
        call.setConnectTimeMillis(System.currentTimeMillis());
        Log.d(this, "notifyCdmaCallAccepted, call:%s", call);
        for (CallsManagerListener listener : mListeners) {
            listener.onCdmaCallAccepted(call);
        }
    }
这里是关键,call重新设置连接时间为当前。

packages/services/Telecomm/src/com/android/server/telecom/InCallController.java

    public void onCdmaCallAccepted(Call call) {
        Log.d(this, "onCdmaCallAccepted %s", call);
        updateCall(call);
    }
    private void updateCall(Call call, boolean videoProviderChanged) {
        if (!mInCallServices.isEmpty()) {
            ParcelableCall parcelableCall = toParcelableCall(call,
                    videoProviderChanged /* includeVideoProvider */);
            Log.i(this, "Sending updateCall %s ==> %s", call, parcelableCall);
            List<ComponentName> componentsUpdated = new ArrayList<>();
            for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
                ComponentName componentName = entry.getKey();
                IInCallService inCallService = entry.getValue();
                componentsUpdated.add(componentName);
                try {
                    inCallService.updateCall(parcelableCall);
                } catch (RemoteException ignored) {
                }
            }
            Log.i(this, "Components updated: %s", componentsUpdated);
        }
    }
然后InCallService就会传递Call数据到InCallUI

高通的实现

app层面是从Telephony开始的

packages/service/Telephony/src/com/android/services/telephony/CdmaConnection.java

    private void onCdmaLineControlInfoRec() {
        if (mOriginalConnection != null && mOriginalConnection.getState() == Call.State.ACTIVE) {
            if (mOriginalConnection.getDurationMillis() > 0 &&
                    !mOriginalConnection.isIncoming() && !mConnectionTimeReset) {
                Bundle extras = getExtras();
                if (extras != null && !extras.getBoolean("isNeedReset", false)) {
                    extras.putBoolean("isNeedReset", true);
                    putExtras(extras);
                    mOriginalConnection.resetConnectionTime();
                }
            }
        }
    }

接下来就会上报到Telecomm

packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java

    @Override
    public void onExtrasChanged(Call c, int source, Bundle extras) {
        if (source != Call.SOURCE_CONNECTION_SERVICE) {
            return;
        }

        handleCallTechnologyChange(c);
        handleChildAddressChange(c);

        if (extras != null) {
            boolean isNeedReset = extras.getBoolean("isNeedReset", false);
            handleCdmaConnectionTimeReset(c, isNeedReset);
        }
        updateCanAddCall();
    }

    void handleCdmaConnectionTimeReset(Call call, boolean isNeedReset) {
        if (isNeedReset && call != null) {
            call.setConnectTimeMillis(System.currentTimeMillis());
            if (mCalls.contains(call)) {
                for (CallsManagerListener listener : mListeners) {
                    listener.onCallStateChanged(call, CallState.ACTIVE, CallState.ACTIVE);
                }
            }
            call.removeExtras(Call.SOURCE_INCALL_SERVICE,
                    new ArrayList<String>(Arrays.asList("isNeedReset")));
        }
        updateCanAddCall();
    }

重置了通话时间

这里也可看出高通的实现还是高明一点,利用了现有的借口,不用在framework中再加一堆方法。


接通振动问题

与重置时间类似的就是接通振动问题,同样有各种实现

mtk的实现

frameworks/opt/telephony/src/java/com/android/internal/telephony/cdma/CdmaConnection.java
    boolean onCdmaCallAccept() {
        Rlog.d(LOG_TAG, "onCdmaCallAccept, mIsRealConnected:" + mIsRealConnected
                + ", state:" + getState());
        if (getState() != CdmaCall.State.ACTIVE) {
            mReceivedAccepted = true;
            return false;
        }
        mConnectTimeReal = SystemClock.elapsedRealtime();
        mDuration = 0;
        mConnectTime = System.currentTimeMillis();
        if (!mIsRealConnected) {
            mIsRealConnected = true;
            // send DTMF when the CDMA call is really accepted.
            processNextPostDialChar();
            vibrateForAccepted();
        }
        return true;
    }

    private void vibrateForAccepted() {
        //if CDMA phone accepted, start a Vibrator
        Vibrator vibrator = (Vibrator) mOwner.mPhone.getContext().getSystemService(
                Context.VIBRATOR_SERVICE);
        vibrator.vibrate(MO_CALL_VIBRATE_TIME);
    }
mtk的实现是大多数产品想要实现的效果,真正接通后振动,但是有个特殊的问题,就是mtk只针对cdma特殊处理,gsm就不管了...

高通的实现

vendor/qcom/proprietary/qrdplus/Extension/apps/PhoneFeatures/src/com/qualcomm/qti/phonefeature/FeatureService.java
   protected void onPhoneStateChanged() {
        Call.State state = CallManager.getInstance().getActiveFgCallState();
        if (mLastFgCallState.isDialing() && state == Call.State.ACTIVE) {
            vibrateAfterCallConnected();
        }
        mLastFgCallState = state;
    }

    private void vibrateAfterCallConnected() {
        int defaultVibrateEnabled = getResources()
                    .getInteger(R.integer.config_default_vibrate_after_connected);
        if (Settings.System.getInt(getContentResolver(), "vibrate_on_accepted",
                defaultVibrateEnabled) == 1) {
            Vibrator mSystemVibrator = new SystemVibrator();
            int nVibratorLength = 100;
            mSystemVibrator.vibrate(nVibratorLength);
            SystemClock.sleep(nVibratorLength);
            mSystemVibrator.cancel();
        }
    }
高通实现在app层次,但是也看出并没有针对cdma做特殊处理,会在active状态后就马上振动。

可见最终还是要自己写代码处理这个问题



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值