Mobile native Wearable native

Telephony Information: Handling Phone Call, SIM Card, and Network Information

This tutorial demonstrates how you can get the status of both voice and video calls, get notified when the user makes a voice or video call or hangs up the phone, extract information stored on a SIM card, and get IMEI information.

Warm-up

Become familiar with the Telephony Information API basics by learning about:

Initializing the Telephony Service

To initialize the telephony service:

In a multi-SIM scenario, you must define which subscription (SIM1 or SIM2) you need, in case the application is related to calling, networks, modems, or SIM cards. Telephony provides a function to create handles for different subscriptions.

  1. To use the functions and data types of the Telephony Information API (in mobile and wearable applications), include the <telephony.h> header file in your application:

    #include <telephony.h>
    
  2. To create a telephony handle, use the telephony_handle_list_s structure that holds the handles for all the subscriptions defined in telephony_common.h.

    typedef 
    struct
    {
       unsigned int count;
       telephony_h *handle;
    } telephony_handle_list_s;
    

    Pass the telephony_handle_list_s structure pointer to get the telephony handles for all subscriptions.

    For example, there are 2 handles in a dual SIM device. In this case, handle[0] means the primary SIM and handle[1] means the secondary SIM.

    You can send requests to specific subscriptions using the telephony handle for that subscription.

  3. Get the telephony handle by using the telephony_init() function.

    #include <telephony.h>
    telephony_handle_list_s handle_list;
    
    int 
    main()
    {
       int i;
    
       ret = telephony_init(&handle_list); // In case of single SIM, you get only one handle
       if (ret != TELEPHONY_ERROR_NONE)
       {
          // Error handling
          return -1;
       }
       for (i = 0; i < handle_list.count; i++)
       {
          dlog_print(DLOG_INFO, LOG_TAG, "telephony handle[%p] for subscription[%d]",
                     handle_list.handle[i], i);
       }
    
       return 0;
     }
    
  4. When the telephony handle is no longer needed, free the handle with the telephony_deinit() function.

    void 
    tutorial_telephony_deinit()
    {
       ret = telephony_deinit(&handle_list);
    }
    

Getting Call Information

Getting call information involves:

To get the voice and video call status and be notified when the user makes a voice or video call or hangs up the phone, use the Telephony Call API (in mobile and wearable applications) in call-related actions.

Getting the Current Call List

To get the current call list:

  1. Get the current call handle by using the telephony_call_get_call_list() function:

    unsigned int count;
    telephony_call_h *call_list;
    
    void 
    tutorial_telephony_call_get_call_list()
    {
       telephony_error_e ret;
    
       ret = telephony_call_get_call_list(handle_list.handle[0], &count, &call_list);
       if (ret != TELEPHONY_ERROR_NONE) 
       {
          // Error handling
       } 
       else 
       {
          int i;
          unsigned int handle_id = 0;
          char *number = NULL;
          telephony_call_type_e type = 0;
          telephony_call_status_e status = 0;
          telephony_call_direction_e direction = 0;
          bool conf_status = 0;
    
          if (count == 0) 
          {
             dlog_print(DLOG_INFO, LOG_TAG, "count[%d], No calls", count);
    
             return;
          }
    
          for (i = 0; i < count; i++) 
          {
             telephony_call_get_handle_id(call_list[i], &handle_id);
             telephony_call_get_number(call_list[i], &number);
             telephony_call_get_type(call_list[i], &type);
             telephony_call_get_status(call_list[i], &status);
             telephony_call_get_direction(call_list[i], &direction);
             telephony_call_get_conference_status(call_list[i], &conf_status);
    
             dlog_print(DLOG_INFO, LOG_TAG, "id[%d] number[%s] type[%s] status[%s] direction[%s] conference_status[%s]",
                        handle_id, number,
                        type == TELEPHONY_CALL_TYPE_VOICE ? "VOICE" :
                        type == TELEPHONY_CALL_TYPE_VIDEO ? "VIDEO" : "E911",
                        status == TELEPHONY_CALL_STATUS_IDLE ? "IDLE" :
                        status == TELEPHONY_CALL_STATUS_ACTIVE ? "ACTIVE" :
                        status == TELEPHONY_CALL_STATUS_HELD ? "HELD" :
                        status == TELEPHONY_CALL_STATUS_DIALING ? "DIALING" :
                        status == TELEPHONY_CALL_STATUS_ALERTING ? "ALERTING" :
                        status == TELEPHONY_CALL_STATUS_INCOMING ? "INCOMING" : "UNKNOWN",
                        direction == TELEPHONY_CALL_DIRECTION_MO ? "MO" : "MT",
                        conf_status ? "TRUE" : "FALSE");
             free(number);
          }
          telephony_call_release_call_list(count, &call_list);
       }
    }
    

    After getting the handle, you can use it to retrieve various call information (such as handle ID, number, type, status, direction, conference status).

  2. When the call handle is no longer needed, call the telephony_call_release_call_list() function to free the handle:

    void 
    tutorial_telephony_call_release_call_list()
    {
       telephony_call_release_call_list(count, &call_list);
    }
    

Receiving Change Notifications for the Call Status

Use a callback function to obtain change notifications for the call status asynchronously. The call ID is returned through a callback function, given to the function as one of its parameters.

To be notified when the voice call status changes, implement and register a callback function compatible with the telephony_noti_cb() function typedef:

static int 
voice_call_noti_tbl[] = 
{
   TELEPHONY_NOTI_VOICE_CALL_STATUS_IDLE,
   TELEPHONY_NOTI_VOICE_CALL_STATUS_ACTIVE,
   TELEPHONY_NOTI_VOICE_CALL_STATUS_HELD,
   TELEPHONY_NOTI_VOICE_CALL_STATUS_DIALING,
   TELEPHONY_NOTI_VOICE_CALL_STATUS_ALERTING,
   TELEPHONY_NOTI_VOICE_CALL_STATUS_INCOMING,
};

void 
voice_call_status_noti_cb(telephony_h handle, telephony_noti_e noti_id, void *data, void* user_data)
{
   int ret_value;
   telephony_call_h *call_list;
   unsigned int count = 0;

   switch (noti_id) 
   {
      case TELEPHONY_NOTI_VOICE_CALL_STATUS_IDLE:
         dlog_print(DLOG_INFO, LOG_TAG, "Noti!!! Voice Call Status Idle!!! [%d]", *(int *)data);
         break;

      case TELEPHONY_NOTI_VOICE_CALL_STATUS_ACTIVE:
         dlog_print(DLOG_INFO, LOG_TAG, "Noti!!! Voice Call Status Active!!! [%d]", *(int *)data);
         break;

      case TELEPHONY_NOTI_VOICE_CALL_STATUS_HELD:
         dlog_print(DLOG_INFO, LOG_TAG, "Noti!!! Voice Call Status Held!!! [%d]", *(int *)data);
         break;

      case TELEPHONY_NOTI_VOICE_CALL_STATUS_DIALING:
         dlog_print(DLOG_INFO, LOG_TAG, "Noti!!! Voice Call Status Dialing!!! [%d]", *(int *)data);
         break;

      case TELEPHONY_NOTI_VOICE_CALL_STATUS_ALERTING:
         dlog_print(DLOG_INFO, LOG_TAG, "Noti!!! Voice Call Status Alerting!!! [%d]", *(int *)data);
         break;

      case TELEPHONY_NOTI_VOICE_CALL_STATUS_INCOMING:
         dlog_print(DLOG_INFO, LOG_TAG, "Noti!!! Voice Call Status Incoming!!! [%d]", *(int *)data);
         break;

      default:
         dlog_print(DLOG_INFO, LOG_TAG, "Unknown noti");
         break;
   }

   ret_value = telephony_call_get_call_list(handle_list.handle[0], &count, &call_list);
   if (ret_value != TELEPHONY_ERROR_NONE) 
   {
      dlog_print(DLOG_INFO, LOG_TAG, "telephony_call_get_call_list() failed!!! [0x%x]", ret_value);
   } 
   else 
   {
      int i;
      unsigned int handle_id = 0;
      char *number = NULL;
      telephony_call_type_e type = 0;
      telephony_call_status_e status = 0;
      telephony_call_direction_e direction = 0;
      bool conf_status = 0;

      for (i = 0; i < count; i++) 
      {
         telephony_call_get_handle_id(call_list[i], &handle_id);
         telephony_call_get_number(call_list[i], &number);
         telephony_call_get_type(call_list[i], &type);
         telephony_call_get_status(call_list[i], &status);
         telephony_call_get_direction(call_list[i], &direction);
         telephony_call_get_conference_status(call_list[i], &conf_status);

         dlog_print(DLOG_INFO, LOG_TAG, "id[%d] number[%s] type[%s] status[%s] direction[%s] conference_status[%s]",
                    handle_id, number,
                    type == TELEPHONY_CALL_TYPE_VOICE ? "VOICE" :
                    type == TELEPHONY_CALL_TYPE_VIDEO ? "VIDEO" : "E911",
                    status == TELEPHONY_CALL_STATUS_IDLE ? "IDLE" :
                    status == TELEPHONY_CALL_STATUS_ACTIVE ? "ACTIVE" :
                    status == TELEPHONY_CALL_STATUS_HELD ? "HELD" :
                    status == TELEPHONY_CALL_STATUS_DIALING ? "DIALING" :
                    status == TELEPHONY_CALL_STATUS_ALERTING ? "ALERTING" :
                    status == TELEPHONY_CALL_STATUS_INCOMING ? "INCOMING" : "UNKNOWN",
                    direction == TELEPHONY_CALL_DIRECTION_MO ? "MO" : "MT",
                    conf_status ? "TRUE" : "FALSE");
         free(number);
      }
      telephony_call_release_call_list(count, &call_list);
   }
}

void 
tutorial_telephony_set_noti_cb_voice()
{
   telephony_error_e ret;
   int i;

   for (i = 0; i < (sizeof(voice_call_noti_tbl) / sizeof(int)); i++) 
   {
      ret = telephony_set_noti_cb(handle_list.handle[0], voice_call_noti_tbl[i], voice_call_status_noti_cb, NULL);
      if (ret != TELEPHONY_ERROR_NONE)
      {
         // Error handling
      }
   }
}

After the callback is registered, you are notified of the voice call status until you cancel the registration. To unregister the callback, call the telephony_unset_noti_cb() function for each notification.

Getting SIM Information

Getting SIM information involves:

To extract information stored on a SIM card, use the Telephony SIM API (in mobile and wearable applications).

Getting the State of the SIM

Before retrieving information from the SIM card, retrieve the state of the SIM card. You can get SIM-related information only if the state of the SIM is TELEPHONY_SIM_STATE_AVAILABLE.

You can get the state of the SIM card by calling the telephony_sim_get_state() function. It returns the status of the SIM, which is one of the telephony_sim_state_e values (in mobile and wearable applications), through its output parameters.

void 
tutorial_telephony_sim_get_state()
{
   telephony_sim_state_e state;
   ret = telephony_sim_get_state(handle_list.handle[0], &state);
   if (ret != TELEPHONY_ERROR_NONE)
   {
      // Error handling
      return -1;
   } 
   dlog_print(DLOG_INFO, LOG_TAG, "SIM status: [%d]", status);

   return 0;
}

Receiving Change Notifications for the SIM State

The telephony_noti_cb() callback function can be used to obtain notifications for the changes in the SIM state asynchronously. The SIM status is returned through a callback function, given to the function as one of its parameters.

void 
sim_state_noti_cb(telephony_h handle, telephony_noti_e noti_id, void *data, void* user_data)
{
   telephony_sim_state_e sim_state = *(int *)data;
   dlog_print(DLOG_INFO, LOG_TAG, "SIM state: [%d]", sim_state);
}

void 
tutorial_telephony_set_noti_cb_sim()
{
   telephony_error_e ret;
   ret = telephony_set_noti_cb(handle_list.handle[0], TELEPHONY_NOTI_SIM_STATUS,
         sim_state_noti_cb, NULL);
   if (ret != TELEPHONY_ERROR_NONE) 
   {
         // Error handling
   }

   return 0;
}

The callback function is invoked automatically when the status of the SIM changes, if you register the callback function using the telephony_set_noti_cb() function.

Once the callback function of the SIM state change is registered, this callback function is invoked until it is unregistered with the telephony_unset_noti_cb() function by passing the notification ID.

Getting SIM Information

If you know the current SIM state and, it is for example SIM_STATE_AVAILABLE, call the SIM API to get the following information from the SIM card: ICC-ID, operator (MCC+MNC), MSIN, SPN, subscriber name, subscriber number, subscriber ID, and application list.

If the function returns SIM_ERROR_NONE, the requested SIM information is received and stored in an output parameter. You must free all returned variables once you are done with them.

To get ICC-ID information from a SIM card:

void 
tutorial_telephony_sim_get_icc_id()
{
   telephony_error_e ret;
   char *iccid;
   ret = telephony_sim_get_icc_id(handle_list.handle[0], &iccid);
   if (ret == TELEPHONY_ERROR_NONE) 
      dlog_print(DLOG_INFO, LOG_TAG, "Integrated Circuit Card IDentification: %s", iccid);
   free(iccid);

   return ret;
}

Getting Network Information

Getting network information involves:

To access, but not change, information about the current cellular network and telephony service, use the Telephony Network API (in mobile and wearable applications).

Getting the Network Service State

Determine the state of the service network. The network service state is one of the telephony_network_service_state_e enumeration values (in mobile and wearable applications).

You can only get telephony network information if the state is TELEPHONY_NETWORK_SERVICE_STATE_IN_SERVICE.

void 
tutorial_telephony_network_get_service_state()
{
   telephony_network_service_state_e network_service_state;
   int ret;
   ret = telephony_network_get_service_state(handle_list.handle[0], &network_service_state);
   if (ret != TELEPHONY_ERROR_NONE) 
   {
      // Error handling
      return -1;
   } 
   dlog_print(DLOG_INFO, LOG_TAG, "Network Service State [%d]", network_service_state);

   return 0;
}

Receiving Network Service State Change Notifications

The telephony_noti_cb() callback function can be used to obtain change notifications for a network asynchronously. The network status is returned through a callback function, given to the function as one of its parameters.

The Telephony Network API provides change notifications for the following information:

  • Network service state changes (telephony_set_noti_cb(), TELEPHONY_NOTI_NETWORK_SERVICE_STATE)
  • Cell ID changes (telephony_set_noti_cb(), TELEPHONY_NOTI_NETWORK_CELLID)
  • Roaming state changes (telephony_set_noti_cb(), TELEPHONY_NOTI_NETWORK_ROAMING_STATUS)
  • Signal strength changes (telephony_set_noti_cb(), TELEPHONY_NOTI_NETWORK_SIGNALSTRENGTH_LEVEL)
  • Network name changes (telephony_set_noti_cb(), TELEPHONY_NOTI_NETWORK_NETWORK_NAME)
  • PS (packet-switched) type changes (telephony_set_noti_cb(), TELEPHONY_NOTI_NETWORK_PS_TYPE)
  • Default data subscription changes (telephony_set_noti_cb(), TELEPHONY_NOTI_NETWORK_DEFAULT_DATA_SUBSCRIPTION)
  • Default subscription changes (telephony_set_noti_cb(), TELEPHONY_NOTI_NETWORK_DEFAULT_SUBSCRIPTION)
void 
network_service_state_noti_cb(telephony_h handle, telephony_noti_e noti_id, void *data, void* user_data)
{
   telephony_network_service_state_e network_state = *(int *)data;
   dlog_print(DLOG_INFO, LOG_TAG, "SIM state: [%d]", network_state);
}

void 
tutorial_telephony_set_noti_cb_network()
{
   telephony_error_e ret;
   ret = telephony_set_noti_cb(handle_list.handle[0], TELEPHONY_NOTI_NETWORK_SERVICE_STATE,
         network_service_state_noti_cb, NULL);
   if (ret != TELEPHONY_ERROR_NONE) 
   {
      // Error handling
   }

   return 0;
}

The callback function is invoked automatically when the status of the network changes, if you register the callback function using the telephony_set_noti_cb() function. To get additional notifications when the Cell ID, RSSI level, network name, PS type, default data subscription, default subscription, or roaming state changes, define corresponding callback functions. Register each one of them with their corresponding notification ID.

Once the callback function of the network state change is registered, this callback function is invoked until it is unregistered with the telephony_unset_noti_cb() function by passing the notification ID.

Getting Network Information

If the current network service state is NETWORK_INFO_SERVICE_STATE_IN_SERVICE, use the Telephony Network API to get the network information: LAC, Cell ID, RSSI, roaming state, MCC, MNC, network provider name, PS type, and network type.

You must free all returned variables (strings) once you are done with them.

To get network information:

  • To get the Cell ID:

    void 
    tutorial_telephony_network_get_cell_id()
    {
       telephony_error_e ret;
       int cell_id;
       ret = telephony_network_get_cell_id(handle_list.handle[0], &cell_id);
       if (ret == TELEPHONY_ERROR_NONE) 
          dlog_print(DLOG_INFO, LOG_TAG, "Cell Id: %d", cell_id);
    
       return ret;
    }
    
  • To get the MNC:

    void 
    tutorial_telephony_network_get_mnc()
    {
       telephony_error_e ret;
       char *mnc;
       ret = telephony_network_get_mnc(handle_list.handle[0], &mnc);
       if (ret == TELEPHONY_ERROR_NONE) 
          dlog_print(DLOG_INFO, LOG_TAG, "mnc: %s", mnc);
       free(mnc);
    
       return ret;
    }
    

Getting Modem Information

To access, but not change, information about the modem (IMEI and power status), use the Telephony Modem API (in mobile and wearable applications).

To get modem information, use the telephony_modem_get_imei() function, and free all returned variables (strings) once you are done with them.

void 
tutorial_telephony_modem_get_imei()
{
   telephony_error_e ret;
   char *imei;
   ret = telephony_modem_get_imei(handle_list.handle[0], &imei);
   if (ret == TELEPHONY_ERROR_NONE) 
      dlog_print(DLOG_INFO, LOG_TAG, "imei: %s", imei);
   free(imei);

   return ret;
}
Go to top