Android Open Source - VoLTE_Dialer Dialer Service






From Project

Back to project page VoLTE_Dialer.

License

The source code is released under:

GNU General Public License

If you think the Android project VoLTE_Dialer listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 *  Part of the dialer for testing VoLTE network side KPIs.
 *  /*  w w  w.  ja  v  a  2s  . c  o  m*/
 *   Copyright (C) 2014  Spinlogic
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as 
 *  published by the Free Software Foundation.
 *
 *  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>
 */
package at.a1.volte_dialer.dialer;

import java.util.logging.Level;
import java.util.logging.Logger;

import net.spinlogic.logger.SP_Logger;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import at.a1.volte_dialer.callmonitor.CallMonitorService;

/**
 * This service is used to trigger outgoing calls when
 * the app is acting as a sender.
 * This service binds to the CallMonitorService to get notifications
 * about outgoing calls.
 * 
 * The main activity binds to this service to communicate changes 
 * in dialer configuration, whether the MSISDN, the duration of calls or
 * the time between calls.
 * 
 * @author Juan Noguera
 *
 */
public class DialerService extends Service implements DsHandlerInterface {
  private final String TAG = "DialerService";
  private final static Logger LOGGER = Logger.getLogger(SP_Logger.LOGGER_NAME);
  
  static final public String INTENT_ACTION_ALARM = "at.a1.volte_dialer.alarm";
  
  // Messages to this service from the calling activity
  static final public int MSG_NEW_CONFIG       = 1;
  static final public int MSG_CLIENT_ADDHANDLER   = 2;
  
  // Messages to the activity from this server
  static final public int MSG_DS_NEWCALLATTEMPT   = 100;  // used to increase call counter
  static final public int MSG_DS_CALLENDED     = 101;  // call has been released
  
  // Fields in the binder that the activity passes to this service
  final static public String EXTRA_MSISDN   = "msisdn";    // dial string
  final static public String EXTRA_DURATION  = "duration";  // in seconds
  final static public String EXTRA_WAITTIME  = "waittime";  // in seconds (time between calls)
  final static public String EXTRA_TMAXSETUP  = "maxcallsetuptime";  // in seconds (maximum call setup time)
  final static public String EXTRA_TAVGSETUP  = "avgcallsetuptime";  // in seconds (avarage call setup time)
  
  // default values
  final static private int DEF_TMAXSETUP  = 30;  // disconnect if the call is not connected within this time
  final static private int DEF_TAVGSETUP  = 10;  // add this value to the call duration if no access to precise call events
  
  // local Call States
  final static private int STATE_IDLE    = 1000;
  final static private int STATE_DIALING  = 1001;
  final static private int STATE_ACTIVE  = 1002;

  final Messenger   mCmsClient;    // provided by this service to CallMonitorService
  private Messenger   mCmsServer;    // provided by CallMonitorService to this service
  final Messenger   mDsServer;    // provided by this service to the calling activity
  private Messenger   mDsClient;    // provided by the calling activity to this service
    
  private boolean is_inservice;
  private boolean is_system;      // is CallMonitor running as system process
  private boolean is_dismissed;    // is this service being destroyed?
  
  private int        callstate;
  private String       msisdn;
  private int       duration;    
  private int       waittime;
  private int       maxsetup;
  private int       avgsetup;
  
  /**
     * Handler of incoming messages from CallMonitorService
     */
    @SuppressLint("HandlerLeak")
  class CmsHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
          final String METHOD = "::CmsHandler::handleMessage()  ";
            switch (msg.what) {
                case CallMonitorService.MSG_SERVER_OUTCALL_DIALING:
//                  Logger.Log(TAG + METHOD, "MSG_SERVER_OUTCALL_DIALING received from CallMonitorService.");
                  LOGGER.info(TAG + METHOD + "MSG_SERVER_OUTCALL_DIALING received from CallMonitorService.");
                  callstate = (is_system) ? STATE_DIALING : STATE_ACTIVE;
                  sendMsg(mDsClient, MSG_DS_NEWCALLATTEMPT, null);
                    break;
                case CallMonitorService.MSG_SERVER_CALL_ACTIVE:  // only received if is_system
//                  Logger.Log(TAG + METHOD, "MSG_SERVER_OUTCALL_ACTIVE received from CallMonitorService.");
                  LOGGER.info(TAG + METHOD + "MSG_SERVER_OUTCALL_ACTIVE received from CallMonitorService.");
                    // stop the next call timer
                    stopAlarms();
                    // start the call timer
                    setAlarm((long) duration);
                  break;
                case CallMonitorService.MSG_SERVER_OUTCALL_END:
//                  Logger.Log(TAG + METHOD, "MSG_SERVER_OUTCALL_END received from CallMonitorService.");
                  LOGGER.info(TAG + METHOD + "MSG_SERVER_OUTCALL_END received from CallMonitorService.");
                  callstate = STATE_IDLE;
                  if(!is_dismissed) {
                    sendMsg(mDsClient, MSG_DS_CALLENDED, null);
                    setAlarm((long) waittime);  // set the timer for the next call
                  }
                    break;
                case CallMonitorService.MSG_SERVER_STATE_INSERVICE:
//                  Logger.Log(TAG + METHOD, "MSG_SERVER_STATE_INSERVICE received from CallMonitorService.");
                  LOGGER.info(TAG + METHOD + "MSG_SERVER_STATE_INSERVICE received from CallMonitorService.");
                  if(!is_inservice) {
                    // This is the first message that DialerService gets from CallMonitorService.
                    startDialingLoop();
                  }
                  is_inservice = true;
                    break;
                case CallMonitorService.MSG_SERVER_STATE_OUTSERVICE:
//                  Logger.Log(TAG + METHOD, "MSG_SERVER_STATE_OUTSERVICE received from CallMonitorService.");
                  LOGGER.info(TAG + METHOD + "MSG_SERVER_STATE_OUTSERVICE received from CallMonitorService.");
                  if(is_inservice) {
                    stopDialingLoop();
                  }
                  is_inservice = false;
                    break;
                case CallMonitorService.MSG_SERVER_SYSTEMPROCESS:
//                  Logger.Log(TAG + METHOD, "MSG_SERVER_SYSTEMPROCESS received from CallMonitorService.");
                  LOGGER.info(TAG + METHOD + "MSG_SERVER_SYSTEMPROCESS received from CallMonitorService.");
                  is_system = true;
                  break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
    
    
  /**
     * Handler of incoming messages from client activities.
     */
    @SuppressLint("HandlerLeak")
  class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
          final String METHOD = "::IncomingHandler::handleMessage()  ";
            switch (msg.what) {
                case MSG_NEW_CONFIG:
//                  Logger.Log(TAG + METHOD, "MSG_NEW_PREFIX received from activity.");
                  LOGGER.info(TAG + METHOD + "MSG_NEW_PREFIX received from activity.");
                  Bundle bundle = msg.getData();
                  String newmsisdn = bundle.getString(EXTRA_MSISDN);
                  if(newmsisdn != null) {
                    msisdn = newmsisdn;
                  }
                  Integer newduration = bundle.getInt(EXTRA_DURATION);
                  if(newduration != null) {
                    duration = newduration;
                  }
                  Integer newwt = bundle.getInt(EXTRA_WAITTIME);
                  if(newwt != null) {
                    waittime = newwt;
                  }
                    break;
                case MSG_CLIENT_ADDHANDLER:
//                  Logger.Log(TAG + METHOD, "MSG_CLIENT_ADDHANDLER received from activity.");
                  LOGGER.info(TAG + METHOD + "MSG_CLIENT_ADDHANDLER received from activity.");
                  mDsClient = msg.replyTo;
                  break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
    
  private ServiceConnection mConnection = new ServiceConnection() {
    
        public void onServiceConnected(ComponentName className, IBinder service) {
          final String METHOD = "::ServiceConnection::onServiceConnected()  ";
          mCmsServer = new Messenger(service);
            sendMsg(mCmsServer, CallMonitorService.MSG_CLIENT_ADDHANDLER, mCmsClient);
//            Logger.Log(TAG + METHOD, "Bound to CallMonitorService");
            LOGGER.info(TAG + METHOD + "Bound to CallMonitorService");
        }

        public void onServiceDisconnected(ComponentName className) {
          final String METHOD = "::ServiceConnection::onServiceDisconnected()  ";
          mCmsServer = null;
//            Logger.Log(TAG + METHOD, "Unbound to CallMonitorService");
            LOGGER.info(TAG + METHOD + "Unbound to CallMonitorService");
        }
    };
  
  public DialerService() {
    callstate    = STATE_IDLE;
    is_system    = false;
    is_inservice   = false;
    is_dismissed  = false;
    msisdn      = "";
    duration    = 20;    
    waittime    = 20;
    maxsetup    = DEF_TMAXSETUP;
    avgsetup    = DEF_TAVGSETUP;
    
    mCmsServer    = null;
    mCmsClient     = new Messenger(new CmsHandler());
    mDsClient    = null;
    mDsServer     = new Messenger(new IncomingHandler());
    LOGGER.setLevel(Level.INFO);
    DialerReceiver.initLogger();
  }

    
  @Override
  public void onDestroy() {
    final String METHOD = "::onDestroy()  ";
    is_dismissed = true;
    final Context context = this;
    if(callstate != STATE_IDLE) {
      sendMsg(mCmsServer, CallMonitorService.MSG_CLIENT_ENDCALL, null);
    }
    // Give some time to log the last call. In case there was one ongoing
    stopAlarms();
    DialerReceiver.dsIf = null;
    if(mCmsServer != null) {
            unbindService(mConnection);
            Intent monintent = new Intent(context, CallMonitorService.class);
            stopService(monintent);
            mCmsServer = null;
//            Logger.Log(TAG + METHOD, "Unbound to CallMonitorService");
            LOGGER.info(TAG + METHOD + "Unbound to CallMonitorService");
        }
//    Logger.Log(TAG + METHOD, "service destroyed");
    LOGGER.info(TAG + METHOD + "service destroyed");
/*    h.postDelayed(new Runnable() {
      public void run() {
        // stop dialing loop (MSG_SERVER_OUTCALL_END hopefully processed)
        stopAlarms();
        DialerReceiver.dsIf = null;
        if(mCmsServer != null) {
//                unbindService(mConnection);
                Intent monintent = new Intent(context, CallMonitorService.class);
                stopService(monintent);
                mCmsServer = null;
                Logger.Log(TAG + METHOD, "Unbound to CallMonitorService");
            }
        Logger.Log(TAG + METHOD, "service destroyed");
      }
    }, 1000); */  
    super.onDestroy();
  }

  
  @Override
    public IBinder onBind(Intent intent) {
    final String METHOD = "::onBind()  ";
    
    if(!intent.hasExtra(EXTRA_MSISDN)  || 
       !intent.hasExtra(EXTRA_DURATION)  || 
       !intent.hasExtra(EXTRA_WAITTIME)) {
      return null;  // The three parameters must be provided to bind
    }
      msisdn    = intent.getStringExtra(EXTRA_MSISDN);
      duration  = intent.getIntExtra(EXTRA_DURATION, 20);
      waittime  = intent.getIntExtra(EXTRA_WAITTIME, 20);
      maxsetup  = intent.getIntExtra(EXTRA_TMAXSETUP, DEF_TMAXSETUP);
    avgsetup  = intent.getIntExtra(EXTRA_TAVGSETUP, DEF_TAVGSETUP);
      
    // start the CallMonitorService
    Intent monintent = new Intent(this, CallMonitorService.class);
    monintent.putExtra(CallMonitorService.EXTRA_OPMODE, CallMonitorService.OPMODE_MO);
    bindService(monintent, mConnection, Context.BIND_AUTO_CREATE);
//    Logger.Log(TAG + METHOD, "Binding to CallMonitorService");
    LOGGER.info(TAG + METHOD + "Binding to CallMonitorService");
    DialerReceiver.dsIf = this;
    return mDsServer.getBinder();
  }
  
  
  private void startDialingLoop() {
     // Start dialing loop
    dialCall(msisdn);
  }
  
  private void stopDialingLoop() {
     // Start dialing loop
    stopAlarms();
  }
  
  
  /**
   * Sends a message to the client via the Messenger object provided 
   * by the client, if any.
   * @param what
   */
  public void sendMsg(Messenger toMsgr, int what, Messenger rplyToMsgr) {
    final String METHOD = "::sendMsg()  ";
    
//    Logger.Log(TAG + METHOD, "Sending message to client. What = " + Integer.toString(what));
    LOGGER.info(TAG + METHOD + "Sending message to client. What = " + Integer.toString(what));
    Message msg = Message.obtain(null, what, 0, 0);
    if(rplyToMsgr != null) {
      msg.replyTo = rplyToMsgr;
    }
    try {
      toMsgr.send(msg);
//      Logger.Log(TAG + METHOD, "Message sent to client.");
      LOGGER.info(TAG + METHOD + "Message sent to client.");
    } catch (RemoteException e) {
//      Logger.Log(TAG + METHOD, e.getClass().getName() + e.toString());
      LOGGER.info(TAG + METHOD + e.getClass().getName() + e.toString());
    }
  }
  
  
  // INTERFACE DsHandlerInterface 
  
  public boolean dsIf_isCallOngoing() {
    return (callstate != STATE_IDLE) ? true : false;
  }
  
  public void dsIf_endCall() {
    sendMsg(mCmsServer, CallMonitorService.MSG_CLIENT_ENDCALL, null);
  }
  
  /**
   * sets an Alarm to go off in waittime seconds from current time.
   * 
   * @param waittime    in seconds
   */
  @SuppressLint("NewApi")
  public void setAlarm(long waittime) {
    final String METHOD = "::setAlarm()  ";
    Intent alarmIntent = new Intent(this, DialerReceiver.class);
//    alarmIntent.setAction(INTENT_ACTION_ALARM);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    int currentapiVersion = android.os.Build.VERSION.SDK_INT;
    if (currentapiVersion >= android.os.Build.VERSION_CODES.KITKAT){
      alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (waittime * 1000), pendingIntent);
    } else{
      alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (waittime * 1000), pendingIntent);
    }
//    Logger.Log(TAG + METHOD, "ALARM will go off in " + Long.toString(waittime * 1000));
    LOGGER.info(TAG + METHOD + "ALARM will go off in " + Long.toString(waittime * 1000));
  }
  
  
  public void stopAlarms() {
    final String METHOD = "::stopAlarms()  ";
    Intent alarmIntent = new Intent(this, DialerReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarmManager.cancel(pendingIntent);
//    Logger.Log(TAG + METHOD, "All timers have been stopped.");
    LOGGER.info(TAG + METHOD + "All timers have been stopped.");
  }
  
  public void dsIf_dialCall() {
    dialCall(msisdn);
  }
  
  
  public void dialCall(final String telnum) {
    final String METHOD = "::dialCall()  ";
    
    Handler h = new Handler();
    h.postDelayed(new Runnable() {
      public void run() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        intent.setData(Uri.parse("tel:" + telnum));
        intent.setFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
//        Logger.Log(TAG + METHOD, "Calling " + telnum);
        LOGGER.info(TAG + METHOD + "Calling " + telnum);
        
        // Activate an alarm to end the call
        if(is_system) {
          setAlarm((long) maxsetup);
        }
        else {
          setAlarm((long) (avgsetup + duration));
        }
        callstate = STATE_DIALING;
      }
    }, 500);  // Works better if the call is trigger after some delay
  
  }  
  
}




Java Source Code List

at.a1.volte_dialer.BootUpReceiver.java
at.a1.volte_dialer.Globals.java
at.a1.volte_dialer.SettingsActivity.java
at.a1.volte_dialer.SettingsFragment.java
at.a1.volte_dialer.VDMainActivity.java
at.a1.volte_dialer.VD_Settings.java
at.a1.volte_dialer.callmonitor.CallDescription.java
at.a1.volte_dialer.callmonitor.CallLogger.java
at.a1.volte_dialer.callmonitor.CallMonitorInterface.java
at.a1.volte_dialer.callmonitor.CallMonitorReceiver.java
at.a1.volte_dialer.callmonitor.CallMonitorService.java
at.a1.volte_dialer.callmonitor.OutgoingCallReceiver.java
at.a1.volte_dialer.callmonitor.PreciseCallStateReceiver.java
at.a1.volte_dialer.dialer.DialerReceiver.java
at.a1.volte_dialer.dialer.DialerService.java
at.a1.volte_dialer.dialer.DsHandlerInterface.java
at.a1.volte_dialer.receiver.ReceiverService.java
at.a1.volte_dialer.volte_dialer.java
net.spinlogic.logger.Logger_backup.java
net.spinlogic.logger.SP_Logger.java