鸿蒙时间组件解析

1 时间组件架构

时间组件提供管理系统时间的能力。

img

2 目录结构

/base/miscservices/time
├── etc                      # 组件包含的进程的配置文件
├── figures                  # 构架图
├── interfaces               # 组件对外提供的接口代码
│   └── kits                 # 对应用提供的接口
├── profile                  # 组件包含的系统服务的配置文件
└── services                 # 时间服务实现

3 接口与用法

3.1 接口

目前OpenHarmony只提供了2个设置时间的接口:

接口名描述
function setTime(time : number) : Promise设置系统时间,Promise方式
function setTime(time : number, callback : AsyncCallback) : voidfunction setTime(time : number, callback : AsyncCallback) : void

3.2 用法

// 导入模块
import systemTime from '@ohos.systemTime';

// Promise方式的异步方法设置时间
var time = 1611081385000;
systemTime.setTime(time)
    .then((value) => {
        console.log(`success to systemTime.setTime: ${value}`);
    }).catch((err) => {
        console.error(`failed to systemTime.setTime because ${err.message}`);
    });

// callback方式的异步方法设置时间
var time = 1611081385000;
systemTime.setTime(time, (err, value) => {
    if (err) {
        console.error(`failed to systemTime.setTime because ${err.message}`);
        return;
    }
    console.log(`success to systemTime.setTime: ${value}`);
});

4 服务启动

//base\miscservices\time\etc\init\timeservice.rc
on boot
    start time_service
service time_service /system/bin/sa_main /system/profile/time_service.xml
    class z_core
    user system
    group system shell
    capabilities SYS_TIME
    seclabel u:r:time_service:s0

time_service是在boot阶段启动的,服务名为time_service,配置的参数为/system/profile/time_service.xml,我们来看看这个文件有啥。

//base\miscservices\time\profile\3702.xml
<info>
    <process>time_service</process>
    <systemability>
        <name>3702</name>
        <libpath>libtime_service.z.so</libpath>
        <run-on-create>true</run-on-create>
        <distributed>false</distributed>
        <dump-level>1</dump-level>
    </systemability>
</info>

在代码中,只看到一个3702.xml。可以按到进程名是time_service,服务的主体是libtime_service.z.so。那么我们就来看看TimeService的启动。

//base\miscservices\time\services\src\time_service.cpp
int32_t TimeService::Init()
{
    bool ret = Publish(TimeService::GetInstance());
    if (!ret) {
        TIME_HILOGE("Publish failed.");
        return E_PUBLISH_FAIL;
    }
    TIME_HILOGI("Publish success.");
    state_ = ServiceRunningState::STATE_RUNNING;
    return SUCCESS;
}

sptr<TimeService> TimeService::GetInstance()
{
    if (instance_ == nullptr) {
        std::lock_guard<std::mutex> autoLock(instanceLock_);
        if (instance_ == nullptr) {
            instance_ = new TimeService;
        }
    }
    return instance_;
}

首先是创建TimeService实例,然后把服务注册到systemAbility。

在服务启动之后,就会

//base\miscservices\time\services\src\time_service.cpp
void TimeService::OnStart()
{
    TIME_HILOGI("Enter OnStart.");
    if (state_ == ServiceRunningState::STATE_RUNNING) {
        TIME_HILOGI("TimeService is already running.");
        return;
    }

    InitServiceHandler();
    if (Init() != SUCCESS) {
        auto callback = [=]() { Init(); };
        serviceHandler_->PostTask(callback, INIT_INTERVAL);
        TIME_HILOGE("Init failed. Try again 10s later");
        return;
    }

    TIME_HILOGI("Start TimeService success.");
    return;
}

在服务启动之后,再初始化ServiceHandler。

//base\miscservices\time\services\src\time_service.cpp
void TimeService::InitServiceHandler()
{
    TIME_HILOGI("InitServiceHandler started.");
    if (serviceHandler_ != nullptr) {
        TIME_HILOGI("InitServiceHandler already init.");
        return;
    }
    std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("TimeService");
    serviceHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);

    TIME_HILOGI("InitServiceHandler succeeded.");
}

5 setTime的调用过程

上层调用setTime时,会调用到TimeServiceManager::GetInstance()->SetTime(time)

struct timeval getTime;
gettimeofday(&getTime, NULL);
int64_t time = (getTime.tv_sec + 100)*1000 + getTime.tv_usec/1000;
bool result = TimeServiceManager::GetInstance()->SetTime(time);

先顺便看下获取TimeServiceManager实例的实现

//base\miscservices\time\services\src\time_service_manager.cpp
sptr<TimeServiceManager> TimeServiceManager::GetInstance()
{
    if (instance_ == nullptr) {
        std::lock_guard<std::mutex> autoLock(instanceLock_);
        if (instance_ == nullptr) {
            instance_ = new TimeServiceManager;
            timeServiceProxy_ = GetTimeServiceProxy();
        }
    }
    return instance_;
}

bool TimeServiceManager::SetTime(const int64_t time)
{
    if (timeServiceProxy_ == nullptr) {
        TIME_HILOGW("Redo GetTimeServiceProxy");
        timeServiceProxy_ = GetTimeServiceProxy();
    }

    if (timeServiceProxy_ == nullptr) {
        TIME_HILOGE("SetTime quit because redoing GetTimeServiceProxy failed.");
        return false;
    }

    return timeServiceProxy_->SetTime(time);
}

SetTime是通过代理来获取 timeService

//base\miscservices\time\services\src\time_service_manager.cpp
sptr<ITimeService> TimeServiceManager::GetTimeServiceProxy()
{
    sptr<ISystemAbilityManager> systemAbilityManager =
        SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (systemAbilityManager == nullptr) {
        TIME_HILOGE("Getting SystemAbilityManager failed.");
        return nullptr;
    }

    auto systemAbility = systemAbilityManager->GetSystemAbility(TIME_SERVICE_ID, "");
    if (systemAbility == nullptr) {
        TIME_HILOGE("Get SystemAbility failed.");
        return nullptr;
    }
    deathRecipient_ = new TimeSaDeathRecipient();
    systemAbility->AddDeathRecipient(deathRecipient_);
    sptr<ITimeService> timeServiceProxy = iface_cast<ITimeService>(systemAbility);
    if (timeServiceProxy == nullptr) {
        TIME_HILOGE("Get TimeServiceProxy from SA failed.");
        return nullptr;
    }

    TIME_HILOGD("Getting TimeServiceProxy succeeded.");
    return timeServiceProxy;
}

这里也就是从SystemAbilityManager从获取timeService服务。

//base\miscservices\time\services\src\time_service.cpp
bool TimeService::SetTime(const int64_t time)
{
    TIME_HILOGI("Setting time of day to milliseconds: %{public}lld", time);
    if (time <= 0 || time / 1000LL >= INT_MAX) {
        TIME_HILOGE("SetTime input param error");
        return false;
    }

    struct timeval tv;
    tv.tv_sec = (time_t) (time / 1000LL);
    tv.tv_usec = (suseconds_t) ((time % 1000LL) * 1000LL);

    int result = settimeofday(&tv, NULL);
    if (result < 0) {
        TIME_HILOGE("settimeofday fail: %{public}s", strerror(errno));
        return false;
    }

    return  true;
}

tv.tv_usec = (suseconds_t) ((time % 1000LL) * 1000LL);

int result = settimeofday(&tv, NULL);
if (result < 0) {
    TIME_HILOGE("settimeofday fail: %{public}s", strerror(errno));
    return false;
}

return  true;

}


可以看到TimeService中SetTime是通过settimeofday来设置时间。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值