打电话phone--framework层(下)

 

首先看下framework的入口函数PhoneUtils.placeCall

public static int placeCall(Context context, Phone phone,
            String number, Uri contactRef, boolean isEmergencyCall,
            Uri gatewayUri) {
final PhoneApp app = PhoneApp.getInstance();
 if (useGateway) {
..
            numberToDial = gatewayUri.getSchemeSpecificPart();
        } else {
            numberToDial = number;
        }
 connection = app.mCM.dial(phone, numberToDial);
...
number = PhoneNumberUtils.extractNetworkPortion(number);
            number = PhoneNumberUtils.convertKeypadLettersToDigits(number);
            number = PhoneNumberUtils.formatNumber(number);
...
connection.setUserData(..)
...
setAudioMode();
activateSpeakerIfDocked(phone);
}

 这里无论怎么样都会将Number转换为numberToDial然后调用CallManager.dial的方法打电话。然后会把number转换为相对应的打电话者的信息存入Connection中。  setAudioMode()设置声音模式,activateSpeakerIfDocked()根据外设情况,是否打开麦克.

看下CallManager.dial的代码

public Connection dial(Phone phone, String dialString) throws CallStateException {
Phone basePhone = getPhoneBase(phone);
 if ( hasActiveFgCall() ) {
            Phone activePhone = getActiveFgCall().getPhone();
            boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());

            if (activePhone != basePhone) {
                if (hasBgCall) {
                    Log.d(LOG_TAG, "Hangup");
                    getActiveFgCall().hangup();
                } else {
                    Log.d(LOG_TAG, "Switch");
                    activePhone.switchHoldingAndActive();
                }
            }
        }

        result = basePhone.dial(dialString);
}

 

这里应该比较好理解,主要看下getPhoneBase的作用就好了。

    private static Phone getPhoneBase(Phone phone) {
        if (phone instanceof PhoneProxy) {
            return phone.getForegroundCall().getPhone();
        }
        return phone;
    }

 

    public Phone
    getPhone() {
        return owner.phone;
    }

 

   GsmCall (GsmCallTracker owner) {
        this.owner = owner;
    }

 主要就是根据当前电话类型,返回不同的电话对象.

 basePhone.dial,则是调用GSMPhone.dial(如果电话为CDMAPhone,则会调用CDMAPhone.dial)

public Connection
    dial (String dialString, UUSInfo uusInfo) throws CallStateException {
String newDialString = PhoneNumberUtils.stripSeparators(dialString);
..
String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this, mUiccApplication);
if (mmi == null) {
            return mCT.dial(newDialString, uusInfo);
        } else if (mmi.isTemporaryModeCLIR()) {
            return mCT.dial(mmi.dialingNumber, mmi.getCLIRMode(), uusInfo);
        } else if (SystemProperties.getBoolean("ro.config.multimode_cdma", false) &&
                   mmi.isGlobalDevMmi()) {
            return mCT.dial(mmi.dialingNumber, uusInfo);
        } else {
            mPendingMMIs.add(mmi);
            mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
            mmi.processCode();
            return null;
        }
}

 

这里好像是对网络电话做了处理,笔者具体也不是很清楚。看下其他电话的流程。

会调用mCT.dial,既是调用GsmCallTracker.dial

dial (String dialString, int clirMode, UUSInfo uusInfo) throws CallStateException {
...
cm.dial(pendingMO.address, clirMode, uusInfo, obtainCompleteMessage());
...
 updatePhoneState();
  phone.notifyPreciseCallStateChanged();
}

 其中cm.dial进入RIL层,调用dial方法.

updatePhoneState方法会更新当前电话的状态。然后调用notifyPreciseCallStateChanged进行通知,因为在InCallScreen的OnCreat()方法中注册了registerForPhoneStates状态改变,所以上层会收到通知做出相对应的改变.

让我们看下RIL.dial

 public void
    dial(String address, int clirMode, UUSInfo uusInfo, Message result) {
        RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);

        rr.mp.writeString(address);
        rr.mp.writeInt(clirMode);
        rr.mp.writeInt(0); // UUS information is absent

        if (uusInfo == null) {
            rr.mp.writeInt(0); // UUS information is absent
        } else {
            rr.mp.writeInt(1); // UUS information is present
            rr.mp.writeInt(uusInfo.getType());
            rr.mp.writeInt(uusInfo.getDcs());
            rr.mp.writeByteArray(uusInfo.getUserData());
        }

        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

        send(rr);
    }

 后面的就比较容易了,我们直接看ril中RILSender的case EVENT_SEND。

 handleMessage(Message msg) {
            RILRequest rr = (RILRequest)(msg.obj);
            RILRequest req = null; 

switch (msg.what) {
                case EVENT_SEND:
..
 LocalSocket s;
 s = mSocket;
..
s.getOutputStream().write(dataLength);
 s.getOutputStream().write(data);

}

 这里会向socket中写信息.而RILReciver那里一开始就建立了socket的连接,与rild通信。

class RILReceiver implements Runnable {
...
 if (mInstanceId == null || mInstanceId == 0 || multiRild == false) {
                    rilSocket = SOCKET_NAME_RIL;
                } else {
                    rilSocket = SOCKET_NAME_RIL1;
                }

                try {
                    s = new LocalSocket();
                    l = new LocalSocketAddress(rilSocket,
                            LocalSocketAddress.Namespace.RESERVED);
                    s.connect(l);
....
}

 static final String SOCKET_NAME_RIL = "rild";
 static final String SOCKET_NAME_RIL1 = "rild1";

至此,framework层结束

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值