/**
* Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
* This file is part of CSipSimple.
*
* CSipSimple is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* If you own a pjsip commercial license you can also redistribute it
* and/or modify it under the terms of the GNU Lesser General Public License
* as an android library.
*
* CSipSimple is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CSipSimple. If not, see <http://www.gnu.org/licenses/>.
*/
package com.csipsimple.ui.incall;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Chronometer;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.actionbarsherlock.internal.utils.UtilityWrapper;
import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter;
import com.actionbarsherlock.internal.view.menu.ActionMenuView;
import com.actionbarsherlock.internal.view.menu.MenuBuilder;
import com.actionbarsherlock.internal.view.menu.MenuBuilder.Callback;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.csipsimple.R;
import com.csipsimple.api.SipCallSession;
import com.csipsimple.api.SipCallSession.MediaState;
import com.csipsimple.api.SipConfigManager;
import com.csipsimple.api.SipManager;
import com.csipsimple.api.SipProfile;
import com.csipsimple.api.SipUri;
import com.csipsimple.api.SipUri.ParsedSipContactInfos;
import com.csipsimple.models.CallerInfo;
import com.csipsimple.service.SipService;
import com.csipsimple.utils.ContactsAsyncHelper;
import com.csipsimple.utils.CustomDistribution;
import com.csipsimple.utils.ExtraPlugins;
import com.csipsimple.utils.ExtraPlugins.DynActivityPlugin;
import com.csipsimple.utils.Log;
import com.csipsimple.utils.PreferencesProviderWrapper;
import org.webrtc.videoengine.ViERenderer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class InCallCard extends FrameLayout implements OnClickListener, Callback {
private static final String THIS_FILE = "InCallCard";
private SipCallSession callInfo;
private String cachedRemoteUri = "";
private int cachedInvState = SipCallSession.InvState.INVALID;
private int cachedMediaState = SipCallSession.MediaState.ERROR;
private boolean cachedCanRecord = false;
private boolean cachedIsRecording = false;
private boolean cachedIsHold = false;
private boolean cachedVideo = false;
private ImageView photo;
private TextView remoteName, remoteSipAddress, callStatusText, callSecureText;
private ViewGroup callSecureBar;
private Chronometer elapsedTime;
private SurfaceView renderView;
private PreferencesProviderWrapper prefs;
private ViewGroup endCallBar;
private MenuBuilder btnMenuBuilder;
private boolean hasVideo = false;
private boolean canVideo = false;
private boolean cachedZrtpVerified;
private boolean cachedZrtpActive;
private ActionMenuPresenter mActionMenuPresenter;
private Map<String, DynActivityPlugin> incallPlugins;
public InCallCard(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.in_call_card, this, true);
prefs = new PreferencesProviderWrapper(context);
canVideo = prefs.getPreferenceBooleanValue(SipConfigManager.USE_VIDEO);
initControllerView();
incallPlugins = ExtraPlugins.getDynActivityPlugins(context, SipManager.ACTION_INCALL_PLUGIN);
}
private void initControllerView() {
photo = (ImageView) findViewById(R.id.contact_photo);
remoteName = (TextView) findViewById(R.id.contact_name_display_name);
remoteSipAddress = (TextView) findViewById(R.id.contact_name_sip_address);
elapsedTime = (Chronometer) findViewById(R.id.elapsedTime);
callStatusText = (TextView) findViewById(R.id.call_status_text);
callSecureBar = (ViewGroup) findViewById(R.id.call_secure_bar);
callSecureText = (TextView) findViewById(R.id.call_secure_text);
endCallBar = (ViewGroup) findViewById(R.id.end_call_bar);
View btn;
btn = findViewById(R.id.endButton);
btn.setOnClickListener(this);
btnMenuBuilder = new MenuBuilder(getContext());
btnMenuBuilder.setCallback(this);
MenuInflater inflater = new MenuInflater(getContext());
inflater.inflate(R.menu.in_call_card_menu, btnMenuBuilder);
mActionMenuPresenter = new ActionMenuPresenter(getContext());
mActionMenuPresenter.setReserveOverflow(true);
btnMenuBuilder.addMenuPresenter(mActionMenuPresenter);
updateMenuView();
}
private boolean added = false;
private void updateMenuView() {
int w = getWidth();
if(w <= 0) {
w = getResources().getDisplayMetrics().widthPixels;
}
w -= 100;
if(!added) {
final FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
ViewGroup menuViewWrapper = (ViewGroup) findViewById(R.id.call_action_bar);
mActionMenuPresenter.setReserveOverflow(true);
mActionMenuPresenter.setWidthLimit(w, true);
// Use width limit (this means we don't care item limits
mActionMenuPresenter.setItemLimit(20);
ActionMenuView menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(menuViewWrapper);
UtilityWrapper.getInstance().setBackgroundDrawable(menuView, null);
menuViewWrapper.addView(menuView, layoutParams);
added = true;
}else {
mActionMenuPresenter.setWidthLimit(w, true);
mActionMenuPresenter.updateMenuView(true);
}
}
public synchronized void setCallState(SipCallSession aCallInfo) {
callInfo = aCallInfo;
if (callInfo == null) {
updateElapsedTimer();
cachedInvState = SipCallSession.InvState.INVALID;
cachedMediaState = SipCallSession.MediaState.ERROR;
cachedCanRecord = false;
cachedIsRecording = false;
cachedIsHold = false;
cachedVideo = false;
cachedZrtpActive = false;
cachedZrtpVerified = false;
return;
}
Log.d(THIS_FILE, "Set call state : " + callInfo.getCallState());
updateRemoteName();
updateCallStateBar();
updateQuickActions();
updateElapsedTimer();
cachedInvState = callInfo.getCallState();
cachedMediaState = callInfo.getMediaStatus();
cachedCanRecord = callInfo.canRecord();
cachedIsRecording = callInfo.isRecording();
cachedIsHold = callInfo.isLocalHeld();
cachedVideo = callInfo.mediaHasVideo();
cachedZrtpActive = callInfo.getHasZrtp();
cachedZrtpVerified = callInfo.isZrtpSASVerified();
// VIDEO STUFF -- EXPERIMENTAL
if(canVideo) {
if (callInfo.getCallId() >= 0 && cachedVideo) {
if (renderView == null) {
renderView = ViERenderer.CreateRenderer(getContext(), true);
photo.setVisibility(View.GONE);
RelativeLayout container = (RelativeLayout) findViewById(R.id.call_card_container);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
lp.addRule(RelativeLayout.ALIGN_LEFT, RelativeLayout.TRUE);
lp.addRule(RelativeLayout.ALIGN_RIGHT, RelativeLayout.TRUE);
lp.addRule(RelativeLayout.ALIGN_TOP, RelativeLayout.TRUE);
lp.addRule(RelativeLayout.ABOVE, R.id.call_action_bar);
renderView.setLayoutParams(lp);
container.addView(renderView, 0);
Log.d(THIS_FILE, "Render window added");
SipService.setVideoWindow(callInfo.getCallId(), renderView, false);
View v = findViewById(R.id.end_call_bar);
ViewGroup.LayoutParams lp2 = v.getLayoutParams();
lp2.height = ViewGroup.LayoutParams.WRAP_CONTENT;
v.setLayoutParams(lp2);
}
hasVideo = true;
}else {
if(renderView != null) {
renderView.setVisibility(View.GONE);
photo.setVisibility(View.VISIBLE);
}
hasVideo = false;
}
}
if (onTriggerListener != null) {
onTriggerListener.onDisplayVideo(hasVideo && canVideo);
}
// End of video stuff
//requestLayout();
/*
if(dragListener != null) {
dragListener.setCallState(callInfo);
}
*/
}
/* We accept height twice than width */
private static float minRatio = 0.5f;
/* We accept width 1/4 bigger than height */
private static float maxRatio = 1.25f;
private static float minButtonRation = 0.75f;
private final Handler handler = new Handler();
private final Runnable postLayout = new Runnable() {
@Override
public void run() {
float w = getWidth();
float h = getHeight();
if(w > 0 && h > 0) {
float currentRatio = w/h;
float newWidth = w;
float newHeight = h;
Log.d(THIS_FILE, "Current ratio is " + currentRatio);
if(currentRatio < minRatio) {
newHeight = w / minRatio;
int padding = (int) FloatMath.floor((h - newHeight) /2);
setPadding(0, padding, 0, padding);
}else if(currentRatio > maxRatio) {
newWidth = h * maxRatio;
int padding = (int) FloatMath.floor((w - newWidth) /2);
setPadding(padding, 0, padding, 0);
}else {
setPadding(0, 0, 0, 0);
}
View v = findViewById(R.id.end_call_bar);
ViewGroup.LayoutParams lp = v.getLayoutParams();
if(currentRatio < minButtonRation && !hasVideo) {
lp.height = (int) ((1.0f - minButtonRation) * newHeight);
}else {
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
}
v.setLayoutParams(lp);
updateMenuView();
}
}
};
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if(changed) {
handler.postDelayed(postLayout, 100);
}
super.onLayout(changed, left, top, right, bottom);
}
private void updateQuickActions() {
// Useless to process that
if (cachedInvState == callInfo.getCallState() &&
cachedMediaState == callInfo.getMediaStatus() &&
cachedIsRecording == callInfo.isRecording() &&
cachedCanRecord == callInfo.canRecord() &&
cachedIsHold == callInfo.isLocalHeld() &&
cachedVideo == callInfo.mediaHasVideo() &&
cachedZrtpActive == callInfo.getHasZrtp() &&
cachedZrtpVerified == callInfo.isZrtpSASVerified()
) {
Log.d(THIS_FILE, "Nothing changed, ignore this update");
return;
}
boolean active = callInfo.isBeforeConfirmed() && callInfo.isIncoming();
btnMenuBuilder.findItem(R.id.takeCallButton).setVisible(active);
btnMenuBuilder.findItem(R.id.dontTakeCallButton).setVisible(active);
btnMenuBuilder.findItem(R.id.declineCallButton).setVisible(active);
active = !callInfo.isAfterEnded()
&& (!callInfo.isBeforeConfirmed() || (!callInfo.isIncoming() && callInfo
.isBeforeConfirmed()));
btnMenuBuilder.findItem(R.id.terminateCallButton).setVisible(active);
active = (!callInfo.isAfterEnded() && !callInfo.isBeforeConfirmed());
btnMenuBuilder.findItem(R.id.xferCallButton).setVisible(active);
btnMenuBuilder.findItem(R.id.transferCallButton).setVisible(active);
btnMenuBuilder.findItem(R.id.holdCallButton).setVisible(active)
.setTitle(callInfo.isLocalHeld() ? R.string.resume_call : R.string.hold_call);
btnMenuBuilder.findItem(R.id.videoCallButton).setVisible(active && canVideo && !callInfo.mediaHasVideo());
// DTMF
active = callInfo.isActive() ;
active &= ( (callInfo.getMediaStatus() == MediaState.ACTIVE) || (callInfo.getMediaStatus() == MediaState.REMOTE_HOLD));
btnMenuBuilder.findItem(R.id.dtmfCallButton).setVisible(active);
// Info
active = !callInfo.isAfterEnded();
btnMenuBuilder.findItem(R.id.detailedDisplayCallButton).setVisible(active);
// Record
active = CustomDistribution.supportCallRecord();
if(!callInfo.isRecording() && !callInfo.canRecord()) {
active = false;
}
if(callInfo.isAfterEnded()) {
active = false;
}
btnMenuBuilder.findItem(R.id.recordCallButton).setVisible(active).setTitle(
callInfo.isRecording() ? R.string.stop_recording : R.string.record);
// ZRTP
active = callInfo.getHasZrtp() && !callInfo.isAfterEnded();
btnMenuBuilder.findItem(R.id.zrtpAcceptance).setVisible(active).setTitle(
callInfo.isZrtpSASVerified() ? R.string.zrtp_revoke_trusted_remote : R.string.zrtp_trust_remote);
// Expand plugins
btnMenuBuilder.removeGroup(R.id.controls);
for(DynActivityPlugin callPlugin : incallPlugins.values()) {
int minState = callPlugin.getMetaDataInt(SipManager.EXTRA_SIP_CALL_MIN_STATE, SipCallSession.InvState.EARLY);
int maxState = callPlugin.getMetaDataInt(SipManager.EXTRA_SIP_CALL_MAX_STATE, SipCallSession.InvState.CONFIRMED);
int way = callPlugin.getMetaDataInt(SipManager.EXTRA_SIP_CALL_CALL_WAY, (1 << 0 | 1 << 1));
Log.d(THIS_FILE, "Can add plugin ? " + minState + ", " + maxState + ", "+ way);
if(callInfo.getCallState() < minState) {
continue;
}
if(callInfo.getCallState() > maxState) {
continue;
}
if(callInfo.isIncoming() && ((way & (1 << 0)) == 0) ) {
continue;
}
if(!callInfo.isIncoming() && ((way & (1 << 1)) == 0) ) {
continue;
}
MenuItem pluginMenu = btnMenuBuilder.add(R.id.controls, MenuBuilder.NONE, MenuBuilder.NONE, callPlugin.getName());
Intent it = callPlugin.getIntent();
it.putExtra(SipManager.EXTRA_CALL_INFO, new SipCallSession(callInfo));
pluginMenu.setIntent(it);
}
}
/**
* Bind the main visible view with data from call info
*/
private void updateCallStateBar() {
int stateText = -1;
//int stateIcon = R.drawable.ic_incall_ongoing;
if (callInfo.isAfterEnded()) {
//stateIcon = R.drawable.ic_incall_end;
stateText = R.string.call_state_disconnected;
} else if (callInfo.isLocalHeld() || callInfo.isRemoteHeld()) {
//stateIcon = R.drawable.ic_incall_onhold;
stateText = R.string.on_hold;
} else if (callInfo.isBeforeConfirmed()) {
if (callInfo.isIncoming()) {
//stateIcon = R.drawable.ic_call_log_header_incoming_call;
stateText = R.string.call_state_incoming;
} else {
//stateIcon = R.drawable.ic_call_log_header_outgoing_call;
stateText = R.string.call_state_calling;
}
}
if( (callInfo.isBeforeConfirmed() && callInfo.isIncoming()) /* Before call is established we have the slider */ ||
callInfo.isAfterEnded() /*Once ended, just wait for the call finalization*/) {
endCallBar.setVisibility(GONE);
}else {
endCallBar.setVisibility(VISIBLE);
}
if(stateText != -1) {
callStatusText.setText(stateText);
setVisibleWithFade(callStatusText, true);
} else {
setVisibleWithFade(callStatusText, false);
}
//callIcon.setContentDescription(CallsUtils.getStringCallState(callInfo, getContext()));
}
private void updateRemoteName() {
final String aRemoteUri = callInfo.getRemoteContact();
// If not already set with the same value, just ignore it
if (aRemoteUri != null && !aRemoteUri.equalsIgnoreCase(cachedRemoteUri)) {
cachedRemoteUri = aRemoteUri;
ParsedSipContactInfos uriInfos = SipUri.parseSipContact(cachedRemoteUri);
String text = SipUri.getDisplayedSimpleContact(aRemoteUri);
StringBuffer statusTextBuffer = new StringBuffer();
remoteName.setText(text);
if (callInfo.getAccId() != SipProfile.INVALID_ID) {
SipProfile acc = SipProfile.getProfileFromDbId(getContext(), callInfo.getAccId(),
new String[] {
SipProfile.FIELD_ID, SipProfile.FIELD_DISPLAY_NAME
});
if (acc != null && acc.display_name != null) {
statusTextBuffer.append("SIP/" + acc.display_name + " : ");
}
} else {
statusTextBuffer.append("SIP : ");
}
statusTextBuffer.append(uriInfos.userName);
remoteSipAddress.setText(statusTextBuffer.toString());
Thread t = new Thread() {
public void run() {
// Looks like a phone number so search the contact throw
// contacts
CallerInfo callerInfo = CallerInfo.getCallerInfoFromSipUri(getContext(),
cachedRemoteUri);
if (callerInfo != null && callerInfo.contactExists) {
LoadCallerInfoMessage lci = new LoadCallerInfoMessage(InCallCard.this, callerInfo);
userHandler.sendMessage(userHandler.obtainMessage(LOAD_CALLER_INFO,
lci));
}
};
};
t.start();
}
// Useless to process that
if (cachedInvState == callInfo.getCallState() &&
cachedMediaState == callInfo.getMediaStatus()) {
return;
}
}
private void updateElapsedTimer() {
if (callInfo == null) {
elapsedTime.stop();
elapsedTime.setVisibility(VISIBLE);
return;
}
elapsedTime.setBase(callInfo.getConnectStart());
int sigSecureLevel = callInfo.getTransportSecureLevel();
boolean isSecure = (callInfo.isMediaSecure() || sigSecureLevel > 0);
setVisibleWithFade(callSecureBar, isSecure);
String secureMsg = "";
if (isSecure) {
List<String> secureTxtList = new ArrayList<String>();
if(sigSecureLevel == SipCallSession.TRANSPORT_SECURE_TO_SERVER) {
secureTxtList.add(getContext().getString(R.string.transport_secure_to_server));
}else if(sigSecureLevel == SipCallSession.TRANSPORT_SECURE_FULL) {
secureTxtList.add(getContext().getString(R.string.transport_secure_full));
}
if(callInfo.isMediaSecure()) {
secureTxtList.add(callInfo.getMediaSecureInfo());
}
secureMsg = TextUtils.join("\r\n", secureTxtList);
}
callSecureText.setText(secureMsg);
int state = callInfo.getCallState();
switch (state) {
case SipCallSession.InvState.INCOMING:
case SipCallSession.InvState.CALLING:
case SipCallSession.InvState.EARLY:
case SipCallSession.InvState.CONNECTING:
elapsedTime.setVisibility(GONE);
break;
case SipCallSession.InvState.CONFIRMED:
Log.v(THIS_FILE, "we start the timer now ");
if(callInfo.isLocalHeld()) {
elapsedTime.stop();
elapsedTime.setVisibility(View.GONE);
}else {
elapsedTime.start();
elapsedTime.setVisibility(View.VISIBLE);
}
break;
case SipCallSession.InvState.NULL:
case SipCallSession.InvState.DISCONNECTED:
elapsedTime.stop();
elapsedTime.setVisibility(VISIBLE);
break;
default:
break;
}
}
private static final int LOAD_CALLER_INFO = 0;
private class LoadCallerInfoMessage {
LoadCallerInfoMessage(InCallCard callCard, CallerInfo ci){
callerInfo = ci;
target = callCard;
}
CallerInfo callerInfo;
InCallCard target;
}
private final static Handler userHandler = new ContactLoadedHandler();
private static class ContactLoadedHandler extends Handler {
@Override
public void handleMessage(Message msg) {
if (msg.arg1 == LOAD_CALLER_INFO) {
LoadCallerInfoMessage lci = (LoadCallerInfoMessage) msg.obj;
if(lci.callerInfo != null && lci.callerInfo.contactContentUri != null) {
// Flag we'd like high res loading
lci.callerInfo.contactContentUri = lci.callerInfo.contactContentUri.buildUpon().appendQueryParameter(ContactsAsyncHelper.HIGH_RES_URI_PARAM, "1").build();
}
ContactsAsyncHelper.updateImageViewWithContactPhotoAsync(
lci.target.getContext(),
lci.target.photo,
lci.callerInfo,
R.drawable.ic_contact_picture_180_holo_light);
lci.target.remoteName.setText(lci.callerInfo.name);
lci.target.photo.setContentDescription(lci.callerInfo.name);
}
}
};
/*
private OnBadgeTouchListener dragListener;
public void setOnTouchListener(OnBadgeTouchListener l) {
dragListener = l;
super.setOnTouchListener(l);
}
*/
private IOnCallActionTrigger onTriggerListener;
/*
* Registers a callback to be invoked when the user triggers an event.
* @param listener the OnTriggerListener to attach to this view
*/
public void setOnTriggerListener(IOnCallActionTrigger listener) {
onTriggerListener = listener;
}
private void dispatchTriggerEvent(int whichHandle) {
if (onTriggerListener != null) {
onTriggerListener.onTrigger(whichHandle, callInfo);
}
}
public void terminate() {
if(callInfo != null && renderView != null) {
SipService.setVideoWindow(callInfo.getCallId(), null, false);
}
}
private void setVisibleWithFade(View v, boolean in) {
if(v.getVisibility() == View.VISIBLE && in) {
// Already visible and ask to show, ignore
return;
}
if(v.getVisibility() == View.GONE && !in) {
// Already gone and ask to hide, ignore
return;
}
Animation anim = AnimationUtils.loadAnimation(getContext(), in ? android.R.anim.fade_in : android.R.anim.fade_out);
anim.setDuration(1000);
v.startAnimation(anim);
v.setVisibility(in ? View.VISIBLE : View.GONE);
}
@Override
public void onClick(View v) {
int id = v.getId();
if(id == R.id.endButton) {
if (callInfo.isBeforeConfirmed() && callInfo.isIncoming()) {
dispatchTriggerEvent(IOnCallActionTrigger.REJECT_CALL);
}else if (!callInfo.isAfterEnded()) {
dispatchTriggerEvent(IOnCallActionTrigger.TERMINATE_CALL);
}
}
}
@Override
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
int itemId = item.getItemId();
if(itemId == R.id.takeCallButton) {
dispatchTriggerEvent(IOnCallActionTrigger.TAKE_CALL);
return true;
}else if(itemId == R.id.terminateCallButton) {
dispatchTriggerEvent(IOnCallActionTrigger.TERMINATE_CALL);
return true;
}else if(itemId == R.id.dontTakeCallButton) {
dispatchTriggerEvent(IOnCallActionTrigger.DONT_TAKE_CALL);
return true;
}else if(itemId == R.id.declineCallButton) {
dispatchTriggerEvent(IOnCallActionTrigger.REJECT_CALL);
return true;
}else if(itemId == R.id.detailedDisplayCallButton) {
dispatchTriggerEvent(IOnCallActionTrigger.DETAILED_DISPLAY);
return true;
}else if(itemId == R.id.holdCallButton) {
dispatchTriggerEvent(IOnCallActionTrigger.TOGGLE_HOLD);
return true;
}else if(itemId == R.id.recordCallButton) {
dispatchTriggerEvent(callInfo.isRecording() ? IOnCallActionTrigger.STOP_RECORDING : IOnCallActionTrigger.START_RECORDING);
return true;
}else if(itemId == R.id.dtmfCallButton) {
dispatchTriggerEvent(IOnCallActionTrigger.DTMF_DISPLAY);
return true;
}else if(itemId == R.id.videoCallButton) {
dispatchTriggerEvent(callInfo.mediaHasVideo() ? IOnCallActionTrigger.STOP_VIDEO : IOnCallActionTrigger.START_VIDEO);
return true;
}else if(itemId == R.id.xferCallButton) {
dispatchTriggerEvent(IOnCallActionTrigger.XFER_CALL);
return true;
}else if(itemId == R.id.transferCallButton) {
dispatchTriggerEvent(IOnCallActionTrigger.TRANSFER_CALL);
return true;
}else if(itemId == R.id.zrtpAcceptance) {
dispatchTriggerEvent(callInfo.isZrtpSASVerified()? IOnCallActionTrigger.ZRTP_REVOKE : IOnCallActionTrigger.ZRTP_TRUST);
return true;
}
return false;
}
@Override
public void onMenuModeChange(MenuBuilder menu) {
// Nothing to do.
}
}