<span style="font-size:14px;">private void processHangupCall() {
if (DBG) log("try to processHangupCall");
if (isVirtualCallInProgress()) {
terminateScoUsingVirtualVoiceCall();
} else {
if (mPhoneProxy != null) {
try {
mPhoneProxy.hangupCall();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
} else {
Log.e(TAG, "Handsfree phone proxy null for hanging up call");
}
}
}</span>
这段代码就是执行了挂电话,其中的mPhoneProxy在别的地方被初始化过
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mPhoneProxy = IBluetoothHeadsetPhone.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
mPhoneProxy = null;
}
};
这个挂电话是进来的电话挂机还是出去的电话挂机理论上应该是一样的,因为都是断开链接
下面也是挂电话的部分
static boolean hangup(CallManager cm) {
boolean hungup = false;
Call ringing = cm.getFirstActiveRingingCall();
Call fg = cm.getActiveFgCall();
Call bg = cm.getFirstActiveBgCall();
if (!ringing.isIdle()) {
log("hangup(): hanging up ringing call");
hungup = hangupRingingCall(ringing);
} else if (!fg.isIdle()) {
log("hangup(): hanging up foreground call");
hungup = hangup(fg);
} else if (!bg.isIdle()) {
log("hangup(): hanging up background call");
hungup = hangup(bg);
} else {
// No call to hang up! This is unlikely in normal usage,
// since the UI shouldn't be providing an "End call" button in
// the first place. (But it *can* happen, rarely, if an
// active call happens to disconnect on its own right when the
// user is trying to hang up..)
log("hangup(): no active call to hang up");
}
if (DBG) log("==> hungup = " + hungup);
return hungup;
}
static boolean hangup(Call call) {
try {
CallManager cm = getCallManager();
if (call.getState() == Call.State.ACTIVE && cm.hasActiveBgCall()) {
// handle foreground call hangup while there is background call
log("- hangup(Call): hangupForegroundResumeBackground...");
cm.hangupForegroundResumeBackground(cm.getFirstActiveBgCall());
} else {
log("- hangup(Call): regular hangup()...");
call.hangup();
}
return true;
} catch (CallStateException ex) {
Log.e(LOG_TAG, "Call hangup: caught " + ex, ex);
}
return false;
}
public boolean hangupCall() {
enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
if (mCM.hasActiveFgCall()) {
return PhoneUtils.hangupActiveCall(mCM.getActiveFgCall());
} else if (mCM.hasActiveRingingCall()) {
return PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall());
} else if (mCM.hasActiveBgCall()) {
return PhoneUtils.hangupHoldingCall(mCM.getFirstActiveBgCall());
}
参考这个文章http://blog.csdn.net/guiyu_1985/article/details/7518026
接下来是监听本次通话的状态,比如对方未接听就挂了,对方接听后挂了,没有sim卡电话没有打出,有sim卡没服务电话不通等等。
private void sendClccResponseCdma(int index, Connection connection) {
int state;
PhoneGlobals app = PhoneGlobals.getInstance();
CdmaPhoneCallState.PhoneCallState currCdmaCallState =
app.cdmaPhoneCallState.getCurrentCallState();
CdmaPhoneCallState.PhoneCallState prevCdmaCallState =
app.cdmaPhoneCallState.getPreviousCallState();
if ((prevCdmaCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE)
&& (currCdmaCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL)) {
// If the current state is reached after merging two calls
// we set the state of all the connections as ACTIVE
state = CALL_STATE_ACTIVE;
} else {
Call.State callState = connection.getState();
switch (callState) {
case ACTIVE:
// For CDMA since both the connections are set as active by FW after accepting
// a Call waiting or making a 3 way call, we need to set the state specifically
// to ACTIVE/HOLDING based on the mCdmaIsSecondCallActive flag. This way the
// CLCC result will allow BT devices to enable the swap or merge options
if (index == 0) { // For the 1st active connection
state = mCdmaIsSecondCallActive ? CALL_STATE_HELD : CALL_STATE_ACTIVE;
} else { // for the 2nd active connection
state = mCdmaIsSecondCallActive ? CALL_STATE_ACTIVE : CALL_STATE_HELD;
}
break;
case HOLDING:
state = CALL_STATE_HELD;
break;
case DIALING:
state = CALL_STATE_DIALING;
break;
case ALERTING:
state = CALL_STATE_ALERTING;
break;
case INCOMING:
state = CALL_STATE_INCOMING;
break;
case WAITING:
state = CALL_STATE_WAITING;
break;
default:
Log.e(TAG, "bad call state: " + callState);
return;
}
}
boolean mpty = false;
if (currCdmaCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
if (prevCdmaCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {
// If the current state is reached after merging two calls
// we set the multiparty call true.
mpty = true;
} // else
// CALL_CONF state is not from merging two calls, but from
// accepting the second call. In this case first will be on
// hold in most cases but in some cases its already merged.
// However, we will follow the common case and the test case
// as per Bluetooth SIG PTS
}
int direction = connection.isIncoming() ? 1 : 0;
String number = connection.getAddress();
int type = -1;
if (number != null) {
type = PhoneNumberUtils.toaFromString(number);
} else {
number = "";
}
mBluetoothHeadset.clccResponse(index + 1, direction, state, 0, mpty, number, type);
}
或者
static int convertCallState(Call.State callState) {
switch (callState) {
case IDLE:
case DISCONNECTED:
case DISCONNECTING:
return CALL_STATE_IDLE;
case ACTIVE:
return CALL_STATE_ACTIVE;
case HOLDING:
return CALL_STATE_HELD;
case DIALING:
return CALL_STATE_DIALING;
case ALERTING:
return CALL_STATE_ALERTING;
case INCOMING:
return CALL_STATE_INCOMING;
case WAITING:
return CALL_STATE_WAITING;
default:
Log.e(TAG, "bad call state: " + callState);
return CALL_STATE_IDLE;
}
}
以上两段代码都是针对这个
Call.State callState = connection.getState();
switch (callState) {
所以关键是取得这个callstate,这个connection的来源在
sendClccResponseCdma(i, clccConnections[i]);
这个clccConnections[i]的来源是
Connection[] clccConnections = new Connection[CDMA_MAX_CONNECTIONS];// indexed by CLCC index
这个Connection的class在framework里
初始化是
clccConnections[0] = foregroundCall.getLatestConnection();
继续找初始化
Call foregroundCall = mCM.getActiveFgCall();
private CallManager mCM;
mCM = CallManager.getInstance();
在eclipse中无法导入callmanager的包,这个才是大问题
public Call.State getActiveFgCallState() {
Call fgCall = getActiveFgCall();
if (fgCall != null) {
return fgCall.getState();
}
return Call.State.IDLE;
}
这边可以获取state;而且不需要依赖别的函数和变量;关于fgcall也可以参考http://www.360doc.com/content/13/0222/09/8841214_267189922.shtml