android10.0(高通865)通过native层获取ntp时间服务器,并设置系统时间

使用方式

ntp_server ntp1.aliyun.com

目录结构

ntp_server/
   Android.mk  
   long2time.cpp  
   long2time.h  
   main.cpp  
   ntp_server.rc

Android.mk文件内容

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE = ntp_server

LOCAL_SRC_FILES = long2time.cpp \
                  main.cpp

LOCAL_C_INCLUDES := $(LOCAL_PATH)

LOCAL_INIT_RC := ntp_server.rc

LOCAL_CFLAGS += -Wall -Wno-unused-parameter

LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog

LOCAL_SHARED_LIBRARIES := \
            libcutils \
            liblog \
            libandroidfw \
            libutils

include $(BUILD_EXECUTABLE)

long2time.cpp文件内容

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <cutils/properties.h>
#include "long2time.h"

#define UTC_BASE_YEAR 1970
#define MONTH_PER_YEAR 12
#define DAY_PER_YEAR 365
#define SEC_PER_DAY 86400
#define SEC_PER_HOUR 3600
#define SEC_PER_MIN 60

/* 每个月的天数 */
const unsigned char g_day_per_mon[MONTH_PER_YEAR] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

/*
 * 功能:
 *     判断是否是闰年
 * 参数:
 *     year:需要判断的年份数
 *
 * 返回值:
 *     闰年返回1,否则返回0
 */
unsigned char applib_dt_is_leap_year(unsigned short year)
{

    if ((year % 400) == 0)
    {
        return 1;
    }
    else if ((year % 100) == 0)
    {
        return 0;
    }
    else if ((year % 4) == 0)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

/*
 * 功能:
 *     得到每个月有多少天
 * 参数:
 *     month:需要得到天数的月份数
 *     year:该月所对应的年份数
 *
 * 返回值:
 *     该月有多少天
 *
 */
unsigned char applib_dt_last_day_of_mon(unsigned char month, unsigned short year)
{
    if ((month == 0) || (month > 12))
    {
        return g_day_per_mon[1] + applib_dt_is_leap_year(year);
    }

    if (month != 2)
    {
        return g_day_per_mon[month - 1];
    }
    else
    {
        return g_day_per_mon[1] + applib_dt_is_leap_year(year);
    }
}

long getRtcTime()
{
    int fd, size;
    char buffer[50];
    int hour, minunte, second;
    long time;
    fd = open("/sys/class/rtc/rtc0/time", O_RDONLY);
    if (fd < 0)
    {
        INFO("open /sys/class/rtc/rtc0/time failed");
    }
    size = read(fd, buffer, sizeof(buffer));
    close(fd);
    sscanf(buffer, "%d:%d:%d", &hour, &minunte, &second);
    time = hour * 3600 + minunte * 60 + second;
    //INFO("hour = %d minunte = %d second = %d time = %ld",hour,minunte,second,time);
    return time;
}

int setRtcTime(long millis)
{
    char time[25], rtcTime[25];
    sprintf(time, "%ld", millis);
    property_set("persist.sys.time", time);
    long rtcSettings = getRtcTime();
    sprintf(rtcTime, "%ld", rtcSettings);
    property_set("persist.sys.settingsrtc", rtcTime);
    return 0;
}

void change(long ts)
{
    int year = 0;
    int month = 0;
    int day = 0;
    int hour = 0;
    int minute = 0;
    int second = 0;
    char str[80];

    //将时间戳值转化成天数。通过天数可以比较方便地算出年、月、日。
    int days = ts / SEC_PER_DAY;
    //这个时间戳值的年。
    int yearTmp = 0;
    int dayTmp = 0;
    //使用夹逼法计算 days 天中包含的年数。
    for (yearTmp = UTC_BASE_YEAR; days > 0; yearTmp++)
    {
        dayTmp = (DAY_PER_YEAR + applib_dt_is_leap_year(yearTmp)); //这一年有多少天?
        if (days >= dayTmp)                                        //条件成立,则 yearTmp 即是这个时间戳值所代表的年数。
        {
            days -= dayTmp;
        }
        else
        {
            break;
        }
    }
    year = yearTmp;

    //这个时间戳值的月
    int monthTmp = 0;
    for (monthTmp = 1; monthTmp < MONTH_PER_YEAR; monthTmp++)
    {
        dayTmp = applib_dt_last_day_of_mon(monthTmp, year);
        if (days >= dayTmp)
        {
            days -= dayTmp;
        }
        else
        {
            break;
        }
    }
    month = monthTmp;

    day = days + 1;

    //转化成秒。
    int secs = ts % SEC_PER_DAY;
    //这个时间戳值的小时数。
    hour = secs / SEC_PER_HOUR;
    //这个时间戳值的分钟数。
    secs %= SEC_PER_HOUR;
    minute = secs / SEC_PER_MIN;
    //这个时间戳的秒钟数。
    second = secs % SEC_PER_MIN;

    sprintf(str, "date %d%d%d%d%d.%d set", month, day, hour, minute, year, second);
    if (system(str) < 0)
    {
        printf("cmd : %s\t error\n", str);
    }
    // if (system("busybox hwclock -w") < 0) {
    //     printf("cmd : busybox hwclock -w\t error\n");
    // }
}

long2time.h文件内容

#ifndef LONG2TIME_H
#define LONG2TIME_H

#include <utils/Log.h>

#define TAG "vclusters"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

#define debugprintf 1
#ifdef debugprintf
#define debugpri(mesg, args...) fprintf(stderr, "[NetRate print:%s:%d:] " mesg "\n", __FILE__, __LINE__, ##args)
#else
#define debugpri(mesg, args...)
#endif

#define INFO(...)            \
    do                       \
    {                        \
        printf(__VA_ARGS__); \
        printf("\n");        \
        LOGI(__VA_ARGS__);   \
    } while (0)

const char DEFAULT_NTP_SERVER[16] = "ntp1.aliyun.com";
unsigned char applib_dt_is_leap_year(unsigned short year);
unsigned char applib_dt_last_day_of_mon(unsigned char month, unsigned short year);
void change(long ts);
long getRtcTime();
int setRtcTime(long millis);

#endif

ntp_server.rc内容

service ntp_server /system/bin/ntp_server start
        class late_start
        user root
        disabled
        oneshot

on property:sys.boot_completed=1
    start ntp_server

main.cpp内容

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <dirent.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/properties.h>
#include "long2time.h"

#define JAN_1970 0x83aa7e80
#define NTPFRAC(x) (4294 * (x) + ((1981 * (x)) >> 11))
#define USEC(x) (((x) >> 12) - 759 * ((((x) >> 10) + 32768) >> 16))
#define Data(i) ntohl(((unsigned int *)data)[i])
#define LI 0
#define VN 3
#define MODE 3
#define STRATUM 0
#define POLL 4
#define PREC -6

struct NtpTime
{
	unsigned int coarse;
	unsigned int fine;
};

void sendPacket(int fd)
{
	unsigned int data[12];
	struct timeval now;

	if (sizeof(data) != 48)
	{
		fprintf(stderr, "size error\n");
		return;
	}

	memset((char *)data, 0, sizeof(data));
	data[0] = htonl((LI << 30) | (VN << 27) | (MODE << 24) | (STRATUM << 16) | (POLL << 8) | (PREC & 0xff)); //构造协议头部信息
	data[1] = htonl(1 << 16);
	data[2] = htonl(1 << 16);
	gettimeofday(&now, NULL);
	data[10] = htonl(now.tv_sec + JAN_1970); //构造传输时间戳
	data[11] = htonl(NTPFRAC(now.tv_usec));
	send(fd, data, 48, 0);
}
//获取NTP服务器返回的时间
void getNewTime(unsigned int *data, struct timeval *ptimeval)
{
	struct NtpTime trantime;
	trantime.coarse = Data(10);
	trantime.fine = Data(11);

	ptimeval->tv_sec = trantime.coarse - JAN_1970;
	ptimeval->tv_usec = USEC(trantime.fine);
}

int getNtpTime(struct hostent *phost, struct timeval *ptimeval)
{
	if (phost == NULL)
	{
		debugpri("err:host is null!\n");
		return -1;
	}
	int sockfd;
	struct sockaddr_in addr_src, addr_dst;
	fd_set fds;
	int ret;
	int recv_len;
	unsigned int buf[12];
	memset(buf, 0, sizeof(buf));
	int addr_len;
	int count = 0;

	struct timeval timeout;

	addr_len = sizeof(struct sockaddr_in);

	memset(&addr_src, 0, addr_len);
	addr_src.sin_family = AF_INET;
	addr_src.sin_addr.s_addr = htonl(INADDR_ANY);
	addr_src.sin_port = htons(0);

	memset(&addr_dst, 0, addr_len);
	addr_dst.sin_family = AF_INET;
	memcpy(&(addr_dst.sin_addr.s_addr), phost->h_addr_list[0], 4);
	addr_dst.sin_port = htons(123); //ntp默认端口123

	if (-1 == (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))) //创建UDP socket
	{
		debugpri("create socket error!\n");
		return -1;
	}

	ret = bind(sockfd, (struct sockaddr *)&addr_src, addr_len); //bind
	if (-1 == ret)
	{
		debugpri("bind error!\n");
		close(sockfd);
		return -1;
	}

	ret = connect(sockfd, (struct sockaddr *)&addr_dst, addr_len); //连接NTP服务器
	if (-1 == ret)
	{
		debugpri("connect error!\n");
		close(sockfd);
		return -1;
	}
	sendPacket(sockfd); //发送请求包
	while (count < 50)	//轮询请求
	{
		FD_ZERO(&fds);
		FD_SET(sockfd, &fds);

		timeout.tv_sec = 0;
		timeout.tv_usec = 100000;
		ret = select(sockfd + 1, &fds, NULL, NULL, &timeout);
		if (0 == ret)
		{
			count++;
			debugpri("ret == 0\n");
			sendPacket(sockfd);
			usleep(100 * 1000);
			continue;
		}
		if (FD_ISSET(sockfd, &fds))
		{
			recv_len = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&addr_dst, (socklen_t *)&addr_len);
			if (-1 == recv_len)
			{
				debugpri("recvfrom error\n");
				close(sockfd);
				return -1;
			}
			else if (recv_len > 0)
			{
				debugpri("receiv data\n");
				getNewTime(buf, ptimeval);
				debugpri("sec = %ld usec = %ld", ptimeval->tv_sec, ptimeval->tv_usec); //打印输出NTP服务器返回的时间
				change(ptimeval->tv_sec + 8 * 3600);
				setRtcTime(ptimeval->tv_sec * 1000);
				break;
			}
		}
		else
		{
			debugpri("count %d \n", count);
			usleep(50 * 1000);
			count++;
		}
	}
	if (count >= 50)
	{
		debugpri("getNewTime   timeout fail \n");
		close(sockfd);
		return -1;
	}
	close(sockfd);
	return 0;
}

int main(int argc, char **argv)
{
	char noethernet[PROPERTY_VALUE_MAX];
	property_get("persist.ruichi.native_agent", noethernet, NULL);
	if (strcmp("1", noethernet) != 0)
	{
		INFO("persist.ruichi.native_agent = 0");
		return 0;
	}
	struct timeval TimeSet;
	static struct hostent *host = NULL;
	char ntpServer[PROPERTY_VALUE_MAX];

	char CrtcLastTime[PROPERTY_VALUE_MAX];
	char CsettingTime[PROPERTY_VALUE_MAX];
	long rtcNowTime;
	long currentTime;
	long settingTime;
	long rtcLastTime;

	INFO("vclusters argc = %d argv[1] = %s\n", argc, argv[1]);

	if (argc == 2)
	{
		if (strcmp("start", argv[1]) == 0)
		{

			property_get("persist.sys.settingsrtc", CrtcLastTime, NULL);
			property_get("persist.sys.time", CsettingTime, NULL);
			settingTime = atol(CsettingTime);
			rtcLastTime = atol(CrtcLastTime);
			rtcNowTime = getRtcTime();

			currentTime = settingTime + (rtcNowTime - rtcLastTime) * 1000;
			INFO("settingTime = %ld  rtcNowTime = %ld rtcLastTime = %ld currentTime = %ld", settingTime, rtcNowTime, rtcLastTime, currentTime);
			change(currentTime / 1000 + 8 * 3600);
			sleep(10);
			property_get("persist.ruichi.ntpServer", ntpServer, DEFAULT_NTP_SERVER);
			host = gethostbyname(ntpServer);
			//INFO("persist.ruichi.ntpServer = %s",ntpServer);
		}
		else
		{
			host = gethostbyname(argv[1]);
			property_set("persist.ruichi.ntpServer", argv[1]);
		}
		memset(&TimeSet, 0, sizeof(TimeSet));
		getNtpTime(host, &TimeSet);
	}
	return 0;
}

github 源码

gitclone [email protected]:hejiangzhou1/ntp_server.git

参考博客:

NTP协议详解_dosthing的博客-CSDN博客_ntp协议

Guess you like

Origin blog.csdn.net/u014630142/article/details/120673695