1 时间组件架构
时间组件提供管理系统时间的能力。
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) : void | function 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来设置时间。