/** \brief callback notified when a kad_srvcnx_t receive a packet
 * 
 * - this function only forward the packet to the proper kad_peer_t, the actual
 *   processing is happening in the kad_peer_t itself
 */
bool kad_listener_t::neoip_kad_srvcnx_cb(void *cb_userptr, kad_srvcnx_t &cb_kad_srvcnx
				, pkt_t &pkt, const ipport_addr_t &local_oaddr
				, const ipport_addr_t &remote_oaddr)		throw()
{
	const kad_profile_t &	profile		= peer_db.front()->get_profile();
	pkt_t			orig_pkt	= pkt;
	kad_peer_t *		kad_peer	= NULL;
	kad_pkttype_t		pkttype(profile.pkttype());
	kad_realmid_t		dest_realmid;
	kad_peerid_t		dest_peerid;
	// log to debug
	KLOG_DBG("enter pkt=" << pkt);

	// parse the incoming packet	
	try {
		// read the pkttype
		pkt >> pkttype;
		// read the realm id - if realmid_in_pkt_ok()
		if( profile.rpc().realmid_in_pkt_ok() )		pkt >> dest_realmid;
		// get the destination peerid from the incoming packet - if dest_peerid_in_pkt_ok()
		if( profile.rpc().dest_peerid_in_pkt_ok() )	pkt >> dest_peerid; 
	} catch(serial_except_t &e) {
		KLOG_INFO("Cant parse incoming packet due to " << e.what() );
		goto	error;
	}

	// try to find a kad_peer_t matching this realmid/peerid
	// - it works even if they are null
	kad_peer = get_kad_peer(dest_realmid, dest_peerid);
	// if the realm doesnt exist, log and exit
	if( !kad_peer ){
		// log the event
		KLOG_INFO("Received a packet " << pkttype << " for an unexisting realmid=" << dest_realmid
						<< " peerid=" << dest_peerid);
		// send a kad_pkttype_t::RESET_REPLY, if the packet is not itself a RESET_REPLY
		// - similar to "an icmp error MUST NOT be replied to an icmp error" - rfc1812.4.3.2.7
		if( pkttype != pkttype.RESET_REPLY() ){
			// build the kad_pkttype_t::RESET_REPLY
			pkt	= pkt_t();
			pkt << pkttype.RESET_REPLY();
			pkt.append(orig_pkt.void_ptr(), orig_pkt.length());
			// return now
			return true;
		}
		goto error;
	}
	
	// log to debug
	KLOG_DBG("received a pkttype=" << pkttype << " for realmid=" << dest_realmid 
						<< " peerid=" << dest_peerid);
	// forward the packet to the proper realm
	pkt	= kad_peer->handle_request(orig_pkt, local_oaddr, remote_oaddr);
	return true;
error:;
	// swallow the packet as there is no reply
	pkt	= pkt_t();
	// keep the server running anyway
	return true;
}
/** \brief Launch the bt_oload0_swarm_t based on the totfile_len
 * 
 * - it is required to return the bt_oload0_swarm_t to put back the original 
 *   getlen_sclient in the http_client_pool_t in case it has been used
 *   to discover the totfile_len.
 * 
 * @return a pointer on bt_oload0_swarm_t, NULL if an error occured
 */
bt_oload0_swarm_t *	bt_oload0_stat_itor_t::launch_oload0_swarm(const file_size_t &totfile_len) throw()
{
	bt_oload0_t *		bt_oload0	= oload0_stat->bt_oload0;
	bt_mfile_t		bt_mfile	= build_bt_mfile(totfile_len);
	bt_oload0_swarm_t *	oload0_swarm;
	bt_err_t		bt_err;
	// log to debug
	KLOG_WARN("enter totfile_len=" << totfile_len);	

	// steal the httpo_full_db to pass its ownership to the bt_oload0_swarm_t
	std::list<bt_httpo_full_t *>	stolen_httpo_full_db	= httpo_full_db;
	httpo_full_db	= std::list<bt_httpo_full_t *>();
	
	// create and start the bt_oload0_swarm_t for this nested_uri
	oload0_swarm	= nipmem_new bt_oload0_swarm_t();
	bt_err		= oload0_swarm->start(bt_oload0, nested_uri, bt_mfile, stolen_httpo_full_db);
	if( bt_err.failed() ){
		// log the error
		KLOG_INFO("Failed to launch the bt_swarm_t for " << nested_uri << " due to " << bt_err);
		// delete the just created bt_oload0_swarm_t
		nipmem_zdelete	oload0_swarm;
	}
	// return a pointer on bt_oload0_swarm_t
	return oload0_swarm;
}
/** \brief callback notified by \ref udp_client_t when a connection is established
 */
bool	ntudp_resp_estarelay_t::neoip_udp_client_event_cb(void *userptr, udp_client_t &cb_udp_client
						, const udp_event_t &udp_event)	throw()
{
	// log to debug
	KLOG_DBG("enter event=" << udp_event);
	// sanity check - the event MUST be client_ok
	DBG_ASSERT( udp_event.is_client_ok() );
	
	// handle the fatal events
	if( udp_event.is_fatal() ){
		// log the event
		KLOG_INFO("received fatal event on " << *udp_client );
		// special handling for udp_client_t fatal event - to avoid some network race
		return handle_udp_fatal_event();
	}

	// handle each possible events from its type
	switch( udp_event.get_value() ){
	case udp_event_t::CNX_ESTABLISHED:
			// init delaygen for rxmit of packet
			rxmit_delaygen = delaygen_t(ntudp_resp->profile->itor_pkt_rxmit());
			// start the timer immediatly
			rxmit_timeout.start(rxmit_delaygen.current(), this, NULL);
			break;
	case udp_event_t::RECVED_DATA:
			// handle the received packet
			return handle_recved_data(*udp_event.get_recved_data());
	default:	break;
	}
	// return 'tokeep'
	return true;
}
Beispiel #4
0
static void klog_file_log(void)
{
    klog_file_level = LOG_INFO;
    int result = klog_init_file(LOG_PATH, strlen(LOG_PATH), 256, 1);
    TEST_ASSERT_EQUAL_INT(result, 0);

    KLOG_INFO("test", "123:%d", 456);
    KLOG_WARN("logger", "hi");
    KLOG_ERR("o", "error");
    KLOG_DEBUG("b", "debug");
    klog_cleanup();

    FILE *log_file = fopen(LOG_PATH ".000", "r");
    TEST_ASSERT_NOT_NULL(log_file);

    char buffer[256];
    char lines[4][64];
    int i = 0;
    fread(buffer, 1, 256, log_file);

    for (char *token = strtok(buffer, "\n");
         token;
         token = strtok(NULL, "\n"), i++) {

        strcpy(lines[i], token);
    }

    ASSERT_STRING_STARTS_WITH(&lines[0][14], " test:I 123:456");
    ASSERT_STRING_STARTS_WITH(&lines[1][14], " logger:W hi");
    ASSERT_STRING_STARTS_WITH(&lines[2][14], " o:E error");
    TEST_ASSERT_EQUAL_INT(i, 4);
}
/** \brief callback notified by \ref bt_swarm_t when to notify an event
 */
bool 	bt_oload0_swarm_t::neoip_bt_swarm_cb(void *cb_userptr, bt_swarm_t &cb_bt_swarm
					, const bt_swarm_event_t &swarm_event)	throw()
{
	// log to debug
	KLOG_WARN("enter event=" << swarm_event);
	// handle the fatal bt_swarm_event_t
	if( swarm_event.is_fatal() ){
		// log the event
		KLOG_INFO("Closing the bt_swarm_t for " << nested_uri << " due to " << swarm_event);
		// autodelete
		return autodelete();
	}
	
	// handle the bt_swarm_event_t according to its value
	switch(swarm_event.get_value()){
	case bt_swarm_event_t::PIECE_NEWLY_AVAIL:{
			std::list<bt_httpo_full_t *>::iterator	iter;
			// notify this new data to each bt_httpo_full_t within the httpo_full_db
			for(iter = httpo_full_db.begin(); iter != httpo_full_db.end(); iter++){
				bt_httpo_full_t *httpo_full	= *iter;
				// notify this bt_httpo_full_t of the new data
				httpo_full->notify_newly_avail_piece();
			}
			break;}
	default:	DBG_ASSERT( 0 );
	}	
	// return tokeep
	return true;
}
/** \brief Add a new bt_httpo_full_t to this object
 * 
 * - NOTE: the bt_httpo_full_t ownership is transfered to this object
 */
void	bt_oload0_swarm_t::add_httpo_full(bt_httpo_full_t *httpo_full)	throw()
{
	// sanity check - the bt_swarm_t MUST be already initialized
	DBG_ASSERT( bt_swarm );
	// build the http_rephd_t to reply
	const http_reqhd_t &	http_reqhd	= httpo_full->get_http_reqhd();
	file_range_t		req_range	= http_reqhd.range();
	const bt_mfile_t &	bt_mfile	= bt_swarm->get_mfile();
	file_size_t		totfile_size	= bt_mfile.totfile_size();
	const bt_mfile_subfile_t&mfile_subfile	= bt_mfile.subfile_arr()[0];
	file_range_t		rep_range;
	http_rephd_t		http_rephd;
	
	// sanity check - the bt_mfile MUST have a single subfile
	DBG_ASSERT( bt_mfile.subfile_arr().size() == 1 );

	// handle the case differently depending on presence of req_range in the http_reqhd_t
	if( req_range.is_null() ){
		// compute the range to reply
		rep_range	= file_range_t(0, totfile_size-1);
		// build the reply header
		http_rephd.version(http_version_t::V1_1).status_code(200).reason_phrase("OK");
		http_rephd.content_length(rep_range.len());
	}else{
		// compute the range to reply
		rep_range	= req_range;
		rep_range.clamped_by( file_range_t(0, totfile_size-1) );
		// TODO what if the req_range is out of range ?
		// - this case should be tested before ?
		// - this is clearly an error case
		// - should be passed to bt_oload0_herr_t
		DBG_ASSERT(!rep_range.is_null());
		// build the http_rephd_t
		http_rephd.version(http_version_t::V1_1).status_code(206).reason_phrase("Partial Content");
		http_rephd.content_range(rep_range, totfile_size);
	}
	// notify the http client that this server accept RANGE request
	http_rephd.accept_ranges(true);
	// add the mimetype of the content - rfc2616.14.17
	std::string	mimetype_str	= mimediag_t::from_file_path(mfile_subfile.mfile_path());
	if( !mimetype_str.empty() )	http_rephd.header_db().update("Content-Type", mimetype_str);

	// log to debug
	KLOG_WARN("http_rephd=" << http_rephd);

	// start this bt_httpo_full_t
	bt_err_t bt_err	= httpo_full->start(bt_swarm, http_rephd, rep_range, this, NULL);
	if( bt_err.failed() ){
		// log the event 
		KLOG_INFO("httpo_full failed to start due to " << bt_err);
		// delete the httpo_full
		nipmem_zdelete httpo_full;
		return;
	}
	// link this bt_httpo_full_t to the httpo_full_db
	httpo_full_db.push_back(httpo_full);
}
Beispiel #7
0
bool cnc_daemon_send_result(CNCWrapper * wrapper)
{
    if (wrapper == NULL)
    {
        KLOG_ERR(&log_handle, LOG_COMPONENT_NAME, "%s called with a NULL pointer\n", __func__);
        return false;
    }

    if (wrapper->err) //Thinking of changing the err flag to a state enum or similar multi-state member type
    {
        KLOG_INFO(&log_handle, LOG_COMPONENT_NAME, "Encoding result of type: Processing Error\n");
        cnc_daemon_start_encode_response(RESPONSE_TYPE_PROCESSING_ERROR, wrapper);
    }
    else
    {
        KLOG_INFO(&log_handle, LOG_COMPONENT_NAME, "Encoding result of type: Command Result\n");
        cnc_daemon_start_encode_response(RESPONSE_TYPE_COMMAND_RESULT, wrapper);
    }
}
Beispiel #8
0
bool cnc_daemon_finish_encode_response_and_send(uint8_t * data, CborEncoder *encoder, CborEncoder * container)
{
    if (data == NULL)
    {
        KLOG_ERR(&log_handle, LOG_COMPONENT_NAME, "%s called with a NULL pointer\n", __func__);
        return false;
    }

    cbor_encoder_close_container(encoder, container);
    size_t data_len = cbor_encoder_get_buffer_size(encoder, data);

    KLOG_INFO(&log_handle, LOG_COMPONENT_NAME, "Encoded response buffer size: %lu\n", data_len);

    return cnc_daemon_send_buffer(data, data_len);
}
/** \brief callback notified by \ref socket_full_t when a connection is established
 */
bool	bt_httpo_full_t::neoip_socket_full_event_cb(void *userptr, socket_full_t &cb_socket_full
							, const socket_event_t &socket_event)	throw()
{
	// log to debug
	KLOG_DBG("enter event=" << socket_event);
	// sanity check - the event MUST be full_ok
	DBG_ASSERT( socket_event.is_full_ok() );
	
	// if any socket_event_t occurs before is_started(), delete the socket_full
	// - NOTE: handled the delayed start() feature
	if( !is_started() ){
		KLOG_INFO("an socket_event_t " << socket_event << " occured before start(). closing the socket.");
		nipmem_zdelete	socket_full;
		// sanity check - bt_io_read MUST be NULL at this point
		DBG_ASSERT( !bt_io_read );
		return false;
	}

	// handle the fatal events
	// - TODO cnx_closed is not explicit way to say error. moreover no way to 
	//   know the error. well put a bt_err_t in the cnx_closed
	if( socket_event.is_fatal() )
		return notify_callback( bt_httpo_event_t::build_cnx_closed() );

	// handle each possible events from its type
	switch( socket_event.get_value() ){
	case socket_event_t::RECVED_DATA:
			// this event should not happen as recv_max_len_set is 0
			KLOG_ERR("enter event=" << *socket_event.get_recved_data());
			//DBGNET_ASSERT( 0 );
			// TODO else do what ? auto delete ?
			break;
	case socket_event_t::MAYSEND_ON:
			// if MAYSEND_ON occurs and the maysend_threashold is == sendbuf maxlen, this is
			// the end of the connection, so notify a CNX_CLOSED
			// - this is a kludge to implement a weird linger... to fix
			if( socket_full->maysend_tshold() == socket_full->xmitbuf_maxlen() )
				return notify_callback( bt_httpo_event_t::build_cnx_closed() );
			// try to full the socket_full sendbuf
			try_fill_xmitbuf();
			break;
	default:	DBG_ASSERT(0);
	}
	// return tokeep
	return true;
}
/** \brief Start the operation
 */
flv_err_t	flv2xml_apps_t::start()	throw()
{
	lib_session_t *		lib_session	= lib_session_get();
	lib_apps_t *		lib_apps	= lib_session->lib_apps();
	const strvar_db_t &	arg_option	= lib_apps->arg_option();
	// log to debug
	KLOG_INFO("enter");

	// set all output options to false
	output_tophd	= output_tag_audio	= false;
	output_tag_video= output_tag_meta	= false;
	output_custom_kframe			= false;
	// get the dest_dirpath from the command line option if specified
	if( arg_option.contain_key("tophd") )		output_tophd		= true;
	if( arg_option.contain_key("tag_audio") )	output_tag_audio	= true;
	if( arg_option.contain_key("tag_video") )	output_tag_video	= true;
	if( arg_option.contain_key("tag_meta") )	output_tag_meta		= true;
	if( arg_option.contain_key("custom_kframe") )	output_custom_kframe	= true;
	// if no option has been set, set them all
	if( !output_tophd && !output_tag_audio && !output_tag_video
					&& !output_tag_meta && !output_custom_kframe){
		output_tophd	= output_tag_audio	= true;
		output_tag_video= output_tag_meta	= true;
		output_custom_kframe			= true;
	}

	// start the fdwatch on stdin
	m_fdwatch	= nipmem_new fdwatch_t();
	m_fdwatch->start(0, fdwatch_t::INPUT | fdwatch_t::ERROR, this, NULL);

	// open the flv_parse_t
	flv_err_t	flv_err;
	m_flv_parse	= nipmem_new flv_parse_t();
	flv_err		= m_flv_parse->start(this, NULL);
	if( flv_err.failed() )	return flv_err;

	// output the xml result - here only a standard xml header
	KLOG_STDOUT("<?xml version=\"1.0\" encode=\"UTF-8\"?>\n");
	KLOG_STDOUT("<flv>\n");
	// return no error
	return flv_err_t::OK;
}
/** \brief Parse the flv_parse_event_t::TOPHD
 */
flv_err_t	flv2xml_apps_t::parse_event_tophd(const flv_parse_event_t &parse_event)throw()
{
	flv_tophd_t	flv_tophd	= parse_event.get_tophd();
	// sanity check - the parse_event MUST be a flv_parse_event_t::TOPHD
	DBG_ASSERT( parse_event.is_tophd() );

	// log to debug
	KLOG_INFO("flv_tophd=" << flv_tophd);

	// if flv_tophd_t MUST NOT be displayed, return now
	if( !output_tophd )	return flv_err_t::OK;
	// output the xml result
	KLOG_STDOUT("<tophd>\n");
	KLOG_STDOUT("<version>"		<< int(flv_tophd.version())		<< "</version>\n");
	KLOG_STDOUT("<has_video>"	<< (flv_tophd.flag().is_video()? 1:0)	<< "</has_video>\n");
	KLOG_STDOUT("<has_audio>"	<< (flv_tophd.flag().is_audio()? 1:0)	<< "</has_audio>\n");
	KLOG_STDOUT("</tophd>\n");

	// return no error
	return flv_err_t::OK;
}
static void update_led(int charge_status) {
    FILE *aled, *gled;
    aled = fopen(AMBER_LED, "w");
    if (!aled) {
        KLOG_ERROR(LOG_TAG, "%s: could not open amber LED: %s\n",
            __func__, AMBER_LED);
        return;
    } else {
        gled = fopen(GREEN_LED, "w");
        if (!gled) {
            fclose(aled);
            KLOG_ERROR(LOG_TAG, "%s: could not open green LED: %s\n",
                __func__, GREEN_LED);
            return;
        }
    }

    KLOG_INFO(LOG_TAG, "%s: setting charging status '%d'\n",
            __func__, charge_status);

    switch (charge_status) {
        case BATTERY_STATUS_CHARGING:
            fputs(LED_ON, aled);
            fputs(LED_OFF, gled);
            break;
        case BATTERY_STATUS_FULL:
            fputs(LED_OFF, aled);
            fputs(LED_ON, gled);
            break;
        default:
            fputs(LED_OFF, aled);
            fputs(LED_OFF, gled);
            break;
    }

    fclose(aled);
    fclose(gled);
}
/** \brief Start the operation
 */
rtmp_err_t	rtmp2xml_apps_t::start()	throw()
{
	lib_session_t *		lib_session	= lib_session_get();
	lib_apps_t *		lib_apps	= lib_session->lib_apps();
	const strvar_db_t &	arg_option	= lib_apps->arg_option();
	// log to debug
	KLOG_INFO("enter");

	// set all output options to false
	output_pkthd		= false;
	output_pkt_invoke	= false;
	output_pkt_ping		= false;
	// get the dest_dirpath from the command line option if specified
	if( arg_option.contain_key("pkthd") )		output_pkthd	= true;
	// if no option has been set, set them all
	if( !output_pkthd && !output_pkt_invoke && !output_pkt_ping ){
		output_pkthd		= true;
		output_pkt_invoke	= true;
		output_pkt_ping		= true;
	}

	// start the fdwatch on stdin
	m_fdwatch	= nipmem_new fdwatch_t();
	m_fdwatch->start(0, fdwatch_t::INPUT | fdwatch_t::ERROR, this, NULL);

	// open the rtmp_event_t
	rtmp_err_t	rtmp_err;
	m_rtmp_parse	= nipmem_new rtmp_parse_t();
	rtmp_err	= m_rtmp_parse->start(this, NULL);
	if( rtmp_err.failed() )	return rtmp_err;

	// output the xml result - here only a standard xml header
	KLOG_STDOUT("<?xml version=\"1.0\" encode=\"UTF-8\"?>\n");
	KLOG_STDOUT("<rtmp>\n");
	// return no error
	return rtmp_err_t::OK;
}
Beispiel #14
0
static int __init pcmcom8_init_module(void)
{
        int result, ib,itmp;
        dev_t devno;

        KLOG_NOTICE("version: %s\n", REPO_REVISION);

        for (ib = 0; ib < PCMCOM8_MAX_NR_DEVS; ib++)
          if (ioports[ib] == 0) break;
        pcmcom8_numboards = ib;
        KLOG_DEBUG("numboards=%d\n",pcmcom8_numboards);

        /*
         * Register your major, and accept a dynamic number. This is the
         * first thing to do, in order to avoid releasing other module's
         * fops in pcmcom8_cleanup_module()
         */
        result = alloc_chrdev_region(&pcmcom8_device, 0,
            pcmcom8_numboards,DRIVER_NAME);
        if (result < 0) goto fail;

        /*
         * allocate the board structures
         */
        pcmcom8_boards = kmalloc(pcmcom8_numboards * sizeof(pcmcom8_board), GFP_KERNEL);
        if (!pcmcom8_boards) {
                result = -ENOMEM;
                goto fail;
        }
        memset(pcmcom8_boards, 0, pcmcom8_numboards * sizeof(pcmcom8_board));

        pcmcom8_class = class_create(THIS_MODULE, DRIVER_NAME);
        if (IS_ERR(pcmcom8_class)) {
                result = PTR_ERR(pcmcom8_class);
                goto fail;
        }

        for (ib = 0; ib < pcmcom8_numboards; ib++) {
                pcmcom8_board* brd = pcmcom8_boards + ib;
                if (!request_region(ioports[ib],PCMCOM8_IO_REGION_SIZE,DRIVER_NAME)) {
                    result = -ENODEV;
                    goto fail;
                }
                brd->ioport = ioports[ib];
                brd->addr = brd->ioport + ioport_base;
                brd->region_req = 1;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
                mutex_init(&brd->mutex);
#else
                init_MUTEX(&brd->mutex);
#endif
                /*
                 * Read EEPROM configuration. If it doesn't return
                 * -ETIMEDOUT then it looks like there is a board at
                 * the given address.
                 */
                if (!pcmcom8_read_eeconfig(brd,&brd->config,0)) {
                        pcmcom8_nr_ok = ib + 1;
                        itmp = pcmcom8_check_config(&brd->config);
                        KLOG_INFO("EEPROM config for board %d,ioport %#x=%s\n",
                            ib,brd->ioport,(itmp ? "OK":"looks invalid"));
                }
                else {
                        release_region(brd->ioport, PCMCOM8_IO_REGION_SIZE);
                        brd->ioport = 0;
                        brd->region_req = 0;
                        break;
                }

                cdev_init(&brd->cdev,&pcmcom8_fops);
                brd->cdev.owner = THIS_MODULE;
                devno = MKDEV(MAJOR(pcmcom8_device),ib);
                // after calling cdev_add the device is ready for operations
                result = cdev_add(&brd->cdev,devno,1);
                if (result) goto fail;

                brd->device = device_create_x(pcmcom8_class, NULL,
                         devno, DRIVER_NAME "_%d", ib);
                if (IS_ERR(brd->device)) {
                        result = PTR_ERR(brd->device);
                        goto fail;
                }

        }
        if (pcmcom8_nr_ok == 0) {
                result = -ENODEV;
                goto fail;
        }
  
#ifdef DEBUG /* only when debugging */
        KLOG_DEBUG("create_proc\n");
        pcmcom8_create_proc();
#endif
        return result; /* succeed */

fail:
        pcmcom8_cleanup_module();
        return result;
}
Beispiel #15
0
/** \brief start the action
 */
inet_err_t	tcp_resp_t::start(const ipport_addr_t &p_listen_addr
				, tcp_resp_cb_t *callback, void *userptr)	throw()
{
	struct 	sockaddr_in	addr_in;
	std::string		errstr;
	inet_err_t		inet_err;

	// copy some parameter
	this->m_listen_addr	= p_listen_addr;
	this->callback		= callback;
	this->userptr		= userptr;
	// sanity check - the listen_addr MUST be non null
	DBG_ASSERT( !listen_addr().is_null() );
		
	// create the socket
	int	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	if( sock_fd < 0 ){
		errstr = "Cant create socket. due to " + inet_oswarp_t::sock_strerror();
		goto error;
	}
	// set REUSEADDR
	inet_err	= inet_oswarp_t::set_reuseaddr(sock_fd);
	if( inet_err.failed() ){
		errstr = "setsockopt SO_REUSEADDR failed due to " + inet_err.to_string();
		goto close_socket;
	}

	// bind the socket   	
	addr_in = listen_addr().to_sockaddr_in();
	if( bind(sock_fd, (struct sockaddr *)&addr_in, sizeof(addr_in)) ){
		errstr = "cant bind socket to " + listen_addr().to_string() 
				+ " due to " + inet_oswarp_t::sock_strerror();
		goto close_socket;
	}

	// if the listen port was undefined, read the one assigned by the system
	if( listen_addr().get_port() == 0 ){
		socklen_t	addrlen = sizeof(addr_in);
		if( getsockname(sock_fd, (struct sockaddr *)&addr_in, &addrlen)){
			errstr = "cant getsocketname due to " + inet_oswarp_t::sock_strerror();
			goto close_socket;
		}
		// convert the struct socketaddr_in into a ipport_addr_t
		m_listen_addr = ipport_addr_t(addr_in);
	}

	// set this socket in non blocking for the connection
	inet_err	= inet_oswarp_t::set_nonblock(sock_fd);
	if( inet_err.failed() ){
		errstr = inet_err.to_string();
		goto close_socket;
	}

	// put the socket in listen mode
	if( listen(sock_fd, 64) < 0 ){
		errstr = "cant cant listen on to " + listen_addr().to_string() 
					+ " due to " + inet_oswarp_t::sock_strerror();
		goto close_socket;
	}

	// some logging
	KLOG_DBG("tcp_resp_t created on " << listen_addr);		

	// start the fdwatch
	fdwatch = nipmem_new fdwatch_t();
	fdwatch->start(sock_fd, fdwatch_t::INPUT, this, NULL);
	
	// return no error
	return inet_err_t::OK;
	// handle the error case
close_socket:;	inet_oswarp_t::close_fd( sock_fd );
error:;		KLOG_INFO("errstr=" << errstr);
		return inet_err_t(inet_err_t::SYSTEM_ERR, errstr);
}
void BatteryMonitor::init(struct healthd_config *hc) {
    String8 path;
    char pval[PROPERTY_VALUE_MAX];

    mHealthdConfig = hc;
    DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
    if (dir == NULL) {
        KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
    } else {
        struct dirent* entry;

        while ((entry = readdir(dir))) {
            const char* name = entry->d_name;

            if (!strcmp(name, ".") || !strcmp(name, ".."))
                continue;

            char buf[20];
            // Look for "type" file in each subdirectory
            path.clear();
            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
            switch(readPowerSupplyType(path)) {
            case ANDROID_POWER_SUPPLY_TYPE_AC:
            case ANDROID_POWER_SUPPLY_TYPE_USB:
            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
                path.clear();
                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
                if (access(path.string(), R_OK) == 0)
                    mChargerNames.add(String8(name));
                break;

            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
                mBatteryDevicePresent = true;

                if (mHealthdConfig->batteryStatusPath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
                                      name);
                    if (access(path, R_OK) == 0)
                        mHealthdConfig->batteryStatusPath = path;
                }

                if (mHealthdConfig->batteryHealthPath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
                                      name);
                    if (access(path, R_OK) == 0)
                        mHealthdConfig->batteryHealthPath = path;
                }

                if (mHealthdConfig->batteryPresentPath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
                                      name);
                    if (access(path, R_OK) == 0)
                        mHealthdConfig->batteryPresentPath = path;
                }

                if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
                                      name);
                    if (access(path, R_OK) == 0)
                        mHealthdConfig->batteryCapacityPath = path;
                }

                if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/voltage_now",
                                      POWER_SUPPLY_SYSFS_PATH, name);
                    if (access(path, R_OK) == 0) {
                        mHealthdConfig->batteryVoltagePath = path;
                    } else {
                        path.clear();
                        path.appendFormat("%s/%s/batt_vol",
                                          POWER_SUPPLY_SYSFS_PATH, name);
                        if (access(path, R_OK) == 0)
                            mHealthdConfig->batteryVoltagePath = path;
                    }
                }

                if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/current_now",
                                      POWER_SUPPLY_SYSFS_PATH, name);
                    if (access(path, R_OK) == 0)
                        mHealthdConfig->batteryCurrentNowPath = path;
                }

                if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/current_avg",
                                      POWER_SUPPLY_SYSFS_PATH, name);
                    if (access(path, R_OK) == 0)
                        mHealthdConfig->batteryCurrentAvgPath = path;
                }

                if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/charge_counter",
                                      POWER_SUPPLY_SYSFS_PATH, name);
                    if (access(path, R_OK) == 0)
                        mHealthdConfig->batteryChargeCounterPath = path;
                }

                if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
                                      name);
                    if (access(path, R_OK) == 0) {
                        mHealthdConfig->batteryTemperaturePath = path;
                    } else {
                        path.clear();
                        path.appendFormat("%s/%s/batt_temp",
                                          POWER_SUPPLY_SYSFS_PATH, name);
                        if (access(path, R_OK) == 0)
                            mHealthdConfig->batteryTemperaturePath = path;
                    }
                }

                if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
                    path.clear();
                    path.appendFormat("%s/%s/technology",
                                      POWER_SUPPLY_SYSFS_PATH, name);
                    if (access(path, R_OK) == 0)
                        mHealthdConfig->batteryTechnologyPath = path;
                }

                break;

            case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
                break;
            }
        }
        closedir(dir);
    }

    if (!mChargerNames.size())
        KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
    if (!mBatteryDevicePresent) {
        KLOG_INFO(LOG_TAG, "No battery devices found\n");
        hc->periodic_chores_interval_fast = -1;
        hc->periodic_chores_interval_slow = -1;
    } else {
        if (mHealthdConfig->batteryStatusPath.isEmpty())
            KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
        if (mHealthdConfig->batteryHealthPath.isEmpty())
            KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
        if (mHealthdConfig->batteryPresentPath.isEmpty())
            KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
        if (mHealthdConfig->batteryCapacityPath.isEmpty())
            KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
        if (mHealthdConfig->batteryVoltagePath.isEmpty())
            KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
        if (mHealthdConfig->batteryTemperaturePath.isEmpty())
            KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
        if (mHealthdConfig->batteryTechnologyPath.isEmpty())
            KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
    }

    if (property_get("ro.boot.fake_battery", pval, NULL) > 0
                                               && strtol(pval, NULL, 10) != 0) {
        mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
        mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
    }
}
Beispiel #17
0
/*
 * Allocate a circular buffer of dsm_samples.  If the size of one
 * sample is less than PAGE_SIZE, they are allocated in blocks of
 * size up to PAGE_SIZE.
 * dlen: length in bytes of the data portion of each sample.
 * blen: number of samples in the circular buffer.
 */
int alloc_dsm_circ_buf(struct dsm_sample_circ_buf* c,size_t dlen,int blen)
{
        int isamp = 0;
        int samps_per_page;
        int j,n;
        char *sp;

        /* count number of bits set, which should be one for a
         * power of 2.  Or check if first bit set
         * is the same as the last bit set: ffs(blen) == fls(blen)
         */
        if (blen == 0 || ffs(blen) != fls(blen)) {
                KLOG_ERR("circular buffer size=%d is not a power of 2\n",blen);
                return -EINVAL;
        }

        c->head = c->tail = c->size = c->npages = 0;
        c->pages = 0;

        KLOG_DEBUG("kmalloc %u bytes\n",blen * sizeof(void*));
        if (!(c->buf = kmalloc(blen * sizeof(void*),GFP_KERNEL))) return -ENOMEM;
        memset(c->buf,0,blen * sizeof(void*));

        /* Total size of a sample. Make it a multiple of sizeof(int)
         * so that samples are aligned to an int */
        dlen += SIZEOF_DSM_SAMPLE_HEADER;
        n = dlen % sizeof(int);
        if (n) dlen += sizeof(int) - n;

        samps_per_page = PAGE_SIZE / dlen;
        if (samps_per_page < 1) samps_per_page = 1;

        /* number of pages to allocate */
        n = (blen - 1) / samps_per_page + 1;
        if (!(c->pages = kmalloc(n * sizeof(void*),GFP_KERNEL))) {
                kfree(c->buf);
                c->buf = 0;
                return -ENOMEM;
        }
        memset(c->pages,0,n * sizeof(void*));
        c->npages = n;

        KLOG_INFO("sample len=%zu, buf len=%d, samps_per_page=%d, npages=%d\n",
                        dlen,blen,samps_per_page,n);

        for (n = 0; n < c->npages; n++) {
                j = blen - isamp;       /* left to allocate */
                if (j > samps_per_page) j = samps_per_page;
                sp = kmalloc(dlen * j,GFP_KERNEL);
                if (!sp) {
                        for (j = 0; j < n; j++) kfree(c->pages[j]);
                        kfree(c->pages);
                        c->pages = 0;
                        c->npages = 0;
                        kfree(c->buf);
                        c->buf = 0;
                        return -ENOMEM;
                }
                c->pages[n] = sp;

                for (j = 0; j < samps_per_page && isamp < blen; j++) {
                        c->buf[isamp++] = (struct dsm_sample*) sp;
                        sp += dlen;
                }
        }
        c->size = blen;
        smp_mb();
        return 0;
}
/** \brief get a free udp listen ipport_aview_t from the lib_session_t config (without actually binding it)
 * 
 * @return in case of error, the view.first is a null ipport_addr_t
 */
ipport_aview_t	ipport_aview_helper_t::udp_listen_aview_from_conf()	throw()
{
	const strvar_db_t &session_conf	= lib_session_get()->session_conf();
	ip_addr_t	lview_addr	= session_conf.get_first_value("udp_listen_lview_addr","0.0.0.0");
	ip_addr_t	pview_addr	= session_conf.get_first_value("udp_listen_pview_addr","0.0.0.0");
	uint16_t	lview_port_min	= atoi(session_conf.get_first_value("udp_listen_lview_port_min","0").c_str());
	uint16_t	lview_port_max	= atoi(session_conf.get_first_value("udp_listen_lview_port_max","0").c_str());
	uint16_t	pview_port_min	= atoi(session_conf.get_first_value("udp_listen_pview_port_min","0").c_str());
	uint16_t	pview_port_max	= atoi(session_conf.get_first_value("udp_listen_pview_port_max","0").c_str());
	uint16_t	chosen_lport	= 0;

	// log to debug
	KLOG_ERR("lview_ipaddr=" << lview_addr	<< " lview_port_min="	<< lview_port_min
						<< " lview_port_max="	<< lview_port_max);
	KLOG_ERR("pview_ipaddr=" << pview_addr	<< " pview_port_min="	<< pview_port_min
						<< " pview_port_max="	<< pview_port_max);

	// sanity check - lview_port_min/max MUST be either both configured or none are
	if( (!lview_port_max) != (!lview_port_min) ){
		KLOG_ERR("ERROR in the neoip_session.conf file. either udp_listen_lview_port_min and udp_listen_lview_port_max are BOTH configured, or NONE are.");
		EXP_ASSERT( 0 );
	}
	// sanity check - pview_port_min/max MUST be either both configured or none are
	if( (!pview_port_max) != (!pview_port_min) ){
		KLOG_ERR("ERROR in the neoip_session.conf file. either udp_listen_lview_port_min and udp_listen_pview_port_max are BOTH configured, or NONE are.");
		EXP_ASSERT( 0 );
	}
	// sanity check - pview_port range MUST be as large as lview_port range
	if( pview_port_min && pview_port_min && lview_port_max-lview_port_min != pview_port_max-pview_port_min){
		KLOG_ERR("ERROR in lib_session.conf. udp_listen_pview port range is not the same size as the lview port range.");
		EXP_ASSERT( 0 );
	}

	// if there is a lview_port range, try to bind within this range
	if( lview_port_min ){
		for(uint16_t cur_port = lview_port_min; cur_port <= lview_port_max; cur_port++){
			ipport_addr_t	listen_ipport(lview_addr, cur_port);
			inet_err_t	inet_err;
			udp_resp_t *	udp_resp;
			// try to start a udp_resp_t on the listen_ipport
			udp_resp	= nipmem_new udp_resp_t();
			inet_err	= udp_resp->start(listen_ipport, NULL, NULL);
			nipmem_zdelete	udp_resp;
			// if the start() failed, goto the next
			if( inet_err.failed() )	continue;
			// if the binding succeed, set the cur_port and leave the loop
			chosen_lport	= cur_port;
			break;	
		}
	}
	
	// if there are no lview_port range or if bind within it failed, bind dynamicaly 
	// and return a null pview
	if( !lview_port_min || chosen_lport == 0 ){
		ipport_addr_t	listen_ipport(lview_addr, 0);
		inet_err_t	inet_err;
		udp_resp_t *	udp_resp;
		// try to start a udp_resp_t on listen_ipport
		udp_resp	= nipmem_new udp_resp_t();
		inet_err	= udp_resp->start(listen_ipport, NULL, NULL);
		DBG_ASSERT( !inet_err.failed() );
		// update the listen_ipport with the bound address
		listen_ipport	= udp_resp->get_listen_addr();
		// delete the just created udp_resp_t
		nipmem_zdelete	udp_resp;
		// log to debug
		if( lview_port_min )	KLOG_INFO("unable to bind within configured lview_port_min/max range, falling back on dynamic allocation.");
		// return the result to the caller with a null pview
		return ipport_aview_t().lview(listen_ipport);
	}


	// sanity check - here, chosen_lport has been allocated within configured lview_port range 
	DBG_ASSERT( chosen_lport >= lview_port_min && chosen_lport <= lview_port_max );
	DBG_ASSERT( lview_port_min && lview_port_max );

	// build the result
	ipport_aview_t	listen_aview;
	// set the listen_aview.lview()
	listen_aview.lview	( ipport_addr_t(lview_addr, chosen_lport) );
	// set the listen_aview.pview() IIF there is a configured pview_port range
	if( pview_port_min ) 	listen_aview.pview( ipport_addr_t(pview_addr, pview_port_min+(chosen_lport-lview_port_min)) );
	// return the just built listen_aview
	return listen_aview;
}
int main(int argc, char **argv)
{
    int alarm_time = 5;
    int count = -1;
    bool abort_on_failure = false;

    while (1) {
        const static struct option long_options[] = {
            {"abort", no_argument, 0, 'a'},
            {"count", required_argument, 0, 'c'},
            {"time", required_argument, 0, 't'},
        };
        int c = getopt_long(argc, argv, "ac:t:", long_options, NULL);
        if (c < 0) {
            break;
        }

        switch (c) {
        case 'a':
            abort_on_failure = true;
            break;
        case 'c':
            count = strtoul(optarg, NULL, 0);
            break;
        case 't':
            alarm_time = strtoul(optarg, NULL, 0);
            break;
        case '?':
            usage();
            exit(EXIT_FAILURE);
        default:
            abort();
        }
    }

    klog_init();
    klog_set_level(KLOG_INFO_LEVEL);

    if (optind < argc) {
        fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
        usage();
        exit(EXIT_FAILURE);
    }

    int fd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0);
    if (fd < 0) {
        perror("timerfd_create failed");
        exit(EXIT_FAILURE);
    }

    struct itimerspec delay = itimerspec();
    delay.it_value.tv_sec = alarm_time;
    int i = 0;

    int epoll_fd = epoll_create(1);
    if (epoll_fd < 0) {
        perror("epoll_create failed");
        exit(EXIT_FAILURE);
    }

    struct epoll_event ev = epoll_event();
    ev.events = EPOLLIN | EPOLLWAKEUP;
    int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
    if (ret < 0) {
        perror("epoll_ctl failed");
        exit(EXIT_FAILURE);
    }

    while (count != 0) {
        struct timespec expected_time;
        struct timespec actual_time;
        uint64_t fired = 0;

        ret = timerfd_settime(fd, 0, &delay, NULL);
        if (ret < 0) {
            perror("timerfd_settime failed");
            exit(EXIT_FAILURE);
        }

        ret = clock_gettime(CLOCK_BOOTTIME, &expected_time);
        if (ret < 0) {
            perror("failed to get time");
            exit(EXIT_FAILURE);
        }
        expected_time.tv_sec += alarm_time;

        ret = 0;
        while (ret != 1) {
            struct epoll_event out_ev;
            ret = epoll_wait(epoll_fd, &out_ev, 1, -1);
            if (ret < 0 && errno != EINTR) {
                perror("epoll_wait failed");
                exit(EXIT_FAILURE);
            }
        }

        ssize_t bytes = read(fd, &fired, sizeof(fired));
        if (bytes < 0) {
            perror("read from timer fd failed");
            exit(EXIT_FAILURE);
        } else if (bytes < (ssize_t)sizeof(fired)) {
            fprintf(stderr, "unexpected read from timer fd: %zd\n", bytes);
        }

        if (fired != 1) {
            fprintf(stderr, "unexpected timer fd fired count: %" PRIu64 "\n", fired);
        }

        ret = clock_gettime(CLOCK_BOOTTIME, &actual_time);
        if (ret < 0) {
            perror("failed to get time");
            exit(EXIT_FAILURE);
        }

        long long diff = timediff_ns(&actual_time, &expected_time);
        if (llabs(diff) > NSEC_PER_SEC) {
            fprintf(stderr, "alarm arrived %lld.%03lld seconds %s\n",
                    llabs(diff) / NSEC_PER_SEC,
                    (llabs(diff) / NSEC_PER_MSEC) % MSEC_PER_SEC,
                    diff > 0 ? "late" : "early");
            KLOG_ERROR("suspend_stress", "alarm arrived %lld.%03lld seconds %s\n",
                    llabs(diff) / NSEC_PER_SEC,
                    (llabs(diff) / NSEC_PER_MSEC) % MSEC_PER_SEC,
                    diff > 0 ? "late" : "early");
            if (abort_on_failure) {
                exit(EXIT_FAILURE);
            }
        }

        time_t t = time(NULL);
        i += fired;
        printf("timer fired: %d at boottime %lld.%.3ld, %s", i,
                   (long long)actual_time.tv_sec,
                   actual_time.tv_nsec / NSEC_PER_MSEC,
                   ctime(&t));

        KLOG_INFO("suspend_stress", "timer fired: %d at boottime %lld.%.3ld, %s", i,
                   (long long)actual_time.tv_sec,
                   actual_time.tv_nsec / NSEC_PER_MSEC,
                   ctime(&t));

        if (count > 0)
            count--;
    }
    return 0;
}
bool BatteryMonitor::update(void) {
    bool logthis;

    props.chargerAcOnline = false;
    props.chargerUsbOnline = false;
    props.chargerWirelessOnline = false;
    props.batteryStatus = BATTERY_STATUS_UNKNOWN;
    props.batteryHealth = BATTERY_HEALTH_UNKNOWN;

    if (!mHealthdConfig->batteryPresentPath.isEmpty())
        props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
    else
        props.batteryPresent = mBatteryDevicePresent;

    props.batteryLevel = mBatteryFixedCapacity ?
        mBatteryFixedCapacity :
        getIntField(mHealthdConfig->batteryCapacityPath);
    props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;

    props.batteryTemperature = mBatteryFixedTemperature ?
        mBatteryFixedTemperature :
        getIntField(mHealthdConfig->batteryTemperaturePath);

    const int SIZE = 128;
    char buf[SIZE];
    String8 btech;

    if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)
        props.batteryStatus = getBatteryStatus(buf);

    if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)
        props.batteryHealth = getBatteryHealth(buf);

    if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)
        props.batteryTechnology = String8(buf);

    // reinitialize the mChargerNames vector everytime there is an update
    String8 path;
    DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
    if (dir == NULL) {
        KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
    } else {
        struct dirent* entry;
        // reconstruct the charger strings
        mChargerNames.clear();
        while ((entry = readdir(dir))) {
            const char* name = entry->d_name;

            if (!strcmp(name, ".") || !strcmp(name, ".."))
                continue;

            // Look for "type" file in each subdirectory
            path.clear();
            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
            switch(readPowerSupplyType(path)) {
            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
                break;
            default:
                path.clear();
                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
                if (access(path.string(), R_OK) == 0) {
                    mChargerNames.add(String8(name));
                    if (readFromFile(path, buf, SIZE) > 0) {
                        if (buf[0] != '0') {
                            path.clear();
                            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
                                              name);
                            switch(readPowerSupplyType(path)) {
                            case ANDROID_POWER_SUPPLY_TYPE_AC:
                                props.chargerAcOnline = true;
                                break;
                            case ANDROID_POWER_SUPPLY_TYPE_USB:
                                props.chargerUsbOnline = true;
                                break;
                            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
                                props.chargerWirelessOnline = true;
                                break;
                            default:
                                KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
                                             name);
                            }
                        }
                    }
                }
                break;
            } //switch
        } //while
        closedir(dir);
    }//else

    logthis = !healthd_board_battery_update(&props);

    if (logthis) {
        char dmesgline[256];

        if (props.batteryPresent) {
            snprintf(dmesgline, sizeof(dmesgline),
                 "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
                 props.batteryLevel, props.batteryVoltage,
                 props.batteryTemperature < 0 ? "-" : "",
                 abs(props.batteryTemperature / 10),
                 abs(props.batteryTemperature % 10), props.batteryHealth,
                 props.batteryStatus);

            if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
                int c = getIntField(mHealthdConfig->batteryCurrentNowPath);
                char b[20];

                snprintf(b, sizeof(b), " c=%d", c / 1000);
                strlcat(dmesgline, b, sizeof(dmesgline));
            }
        } else {
            snprintf(dmesgline, sizeof(dmesgline),
                 "battery none");
        }

        KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
                  props.chargerAcOnline ? "a" : "",
                  props.chargerUsbOnline ? "u" : "",
                  props.chargerWirelessOnline ? "w" : "");
    }

    healthd_mode_ops->battery_update(&props);
    return props.chargerAcOnline | props.chargerUsbOnline |
            props.chargerWirelessOnline;
}
bool BatteryMonitor::update(void) {
    struct BatteryProperties props;
    bool logthis;

    props.chargerAcOnline = false;
    props.chargerUsbOnline = false;
    props.chargerWirelessOnline = false;
    props.batteryStatus = BATTERY_STATUS_UNKNOWN;
    props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
    props.batteryCurrentNow = INT_MIN;
    props.batteryChargeCounter = INT_MIN;

    if (!mHealthdConfig->batteryPresentPath.isEmpty())
        props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
    else
        props.batteryPresent = true;

    props.batteryLevel = getIntField(mHealthdConfig->batteryCapacityPath);
    props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;

    if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
        props.batteryCurrentNow = getIntField(mHealthdConfig->batteryCurrentNowPath);

    if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
        props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);

    props.batteryTemperature = getIntField(mHealthdConfig->batteryTemperaturePath);

    const int SIZE = 128;
    char buf[SIZE];
    String8 btech;

    if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)
        props.batteryStatus = getBatteryStatus(buf);

    if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)
        props.batteryHealth = getBatteryHealth(buf);

    if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)
        props.batteryTechnology = String8(buf);

    unsigned int i;

    for (i = 0; i < mChargerNames.size(); i++) {
        String8 path;
        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
                          mChargerNames[i].string());

        if (readFromFile(path, buf, SIZE) > 0) {
            if (buf[0] != '0') {
                path.clear();
                path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
                                  mChargerNames[i].string());
                switch(readPowerSupplyType(path)) {
                case ANDROID_POWER_SUPPLY_TYPE_AC:
                    props.chargerAcOnline = true;
                    break;
                case ANDROID_POWER_SUPPLY_TYPE_USB:
                    props.chargerUsbOnline = true;
                    break;
                case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
                    props.chargerWirelessOnline = true;
                    break;
                default:
                    KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
                                 mChargerNames[i].string());
                }
            }
        }
    }

    logthis = !healthd_board_battery_update(&props);

    if (logthis) {
        char dmesgline[256];
        snprintf(dmesgline, sizeof(dmesgline),
                 "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
                 props.batteryLevel, props.batteryVoltage,
                 props.batteryTemperature < 0 ? "-" : "",
                 abs(props.batteryTemperature / 10),
                 abs(props.batteryTemperature % 10), props.batteryHealth,
                 props.batteryStatus);

        if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
            char b[20];

            snprintf(b, sizeof(b), " c=%d", props.batteryCurrentNow / 1000);
            strlcat(dmesgline, b, sizeof(dmesgline));
        }

        KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
                  props.chargerAcOnline ? "a" : "",
                  props.chargerUsbOnline ? "u" : "",
                  props.chargerWirelessOnline ? "w" : "");
    }

    char prop[PROP_VALUE_MAX];
    // always report AC plug-in and capacity 100% if emulated.battery is set to 1
    property_get("sys.emulated.battery", prop, "0");
    if (!strcmp(prop, "1")) {
        props.chargerAcOnline = true;
        props.batteryLevel = 100;
        props.chargerWirelessOnline = false;
    }

    if (mBatteryPropertiesRegistrar != NULL)
        mBatteryPropertiesRegistrar->notifyListeners(props);

    if (!strcmp(prop, "1")) {
        return false;
    } else {
        if (0 == props.batteryTemperature)
            return false;
        else
            return props.chargerAcOnline | props.chargerUsbOnline |
                   props.chargerWirelessOnline;
    }
}