我想为google贡献源码

我想为google贡献源码

工作过程中发现Android源码也有不健壮的时候,switchWith时候概率性会出现空指针异常。

frameworks\opt\telephony\src\java\com\android\internal\telephony\imsphone\ImsPhoneCallTracker.java

   public void holdActiveCallForWaitingCall() throws CallStateException {
        boolean switchingWithWaitingCall = !mBackgroundCall.getState().isAlive()
                && mRingingCall.getState() == ImsPhoneCall.State.WAITING;
        if (switchingWithWaitingCall) {
            ImsCall callToHold = mForegroundCall.getImsCall();
            HoldSwapState oldHoldState = mHoldSwitchingState;
            mHoldSwitchingState = HoldSwapState.HOLDING_TO_ANSWER_INCOMING;
            //mForegroundCall是ImsPhoneCall的实例,我们可以参考下具体的实现
            mForegroundCall.switchWith(mBackgroundCall);
            logHoldSwapState("holdActiveCallForWaitingCall");
            try {
                callToHold.hold();
                mMetrics.writeOnImsCommand(mPhone.getPhoneId(), callToHold.getSession(),
                        ImsCommand.IMS_CMD_HOLD);
            } catch (ImsException e) {
                mForegroundCall.switchWith(mBackgroundCall);
                mHoldSwitchingState = oldHoldState;
                logHoldSwapState("holdActiveCallForWaitingCall - fail");
                throw new CallStateException(e.getMessage());
            }
        }
    }

frameworks\opt\telephony\src\java\com\android\internal\telephony\imsphone\ImsPhoneCall.java

    public void switchWith(ImsPhoneCall that) {
        if (VDBG) {
            Rlog.v(LOG_TAG, "switchWith : switchCall = " + this + " withCall = " + that);
        }
        synchronized (ImsPhoneCall.class) {
            ImsPhoneCall tmp = new ImsPhoneCall();//这里创建了个临时对象用于交换前后台通话,我们参考下ImsPhoneCall的无参构造方法
            //mForegroundCall现在复制给了tmp,将tmp中的mConnections 指向内存空间中mForegroundCall的mConnections 内存空间地址
            //mState,Connection的mParent都修改了指向。这个时候问题出现了。
            tmp.takeOver(this);
            this.takeOver(that);//
            that.takeOver(tmp);
        }
        mOwner.logState();
    }
    ImsPhoneCall() {
        mCallContext = CONTEXT_UNKNOWN;
        //这里并没有给mOwner进行赋值。
    }
    //修改指向
    private void takeOver(ImsPhoneCall that) {
        mConnections = that.mConnections;
        mState = that.mState;
        for (Connection c : mConnections) {
            ((ImsPhoneConnection) c).changeParent(this);
        }
    }

问题发生场景:
当ImsPhoneConnection的changeParent改变后,原来mForegroundCall的parent现在是指向tmp的
上层创建connection的时候获取当前connection的phone的类型
调用顺序ImsPhoneConnection.getCall().getPhone()

    public ImsPhoneCall getCall() {
        return mParent;
    }
    public Phone
    getPhone() {//getPhone非同步方法,switchWith持锁,并没有影响外部的getPhone(),tmp的mOwner没有初始化,默认状态是null.这时候空指针出来了
        return mOwner.getPhone();
    }

解决方法:
修改switchWith中new ImsPhoneCall(),创建tmp的时候使用有参构造方法即可

    public ImsPhoneCall(ImsPhoneCallTracker owner, String context) {
        mOwner = owner;
        mCallContext = context;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值