代码还是选取开源鸿蒙HarmonyOS 4.0的代码基线。
这里我们直接看调用发起定位:
// base/location/frameworks/native/source/locator_impl.cpp
void LocatorImpl::StartLocating(std::unique_ptr<RequestConfig>& requestConfig, sptr<ILocatorCallback>& callback)
{
if (!Init()) {
return;
}
sptr<LocatorProxy> proxy = GetProxy();
if (proxy == nullptr) {
LBSLOGE(LOCATOR_STANDARD, "%{public}s get proxy failed.", __func__);
return;
}
proxy->StartLocating(requestConfig, callback, "location.ILocator", 0, 0);
}
// base/location/frameworks/native/source/locator_proxy.cpp
int LocatorProxy::StartLocating(std::unique_ptr<RequestConfig>& requestConfig,
sptr<ILocatorCallback>& callback, std::string bundleName, pid_t pid, pid_t uid)
{
LBSLOGD(LOCATOR_STANDARD, "uid is: %{public}d, pid is: %{public}d", uid, pid);
MessageParcel data;
if (!data.WriteInterfaceToken(GetDescriptor())) {
return REPLY_CODE_EXCEPTION;
}
if (requestConfig != nullptr) {
requestConfig->Marshalling(data);
}
if (callback != nullptr) {
data.WriteObject<IRemoteObject>(callback->AsObject());
}
data.WriteString16(Str8ToStr16(bundleName));
MessageParcel reply;
int error = SendMsgWithDataReply(static_cast<int>(LocatorInterfaceCode::START_LOCATING), data, reply);
LBSLOGD(LOCATOR_STANDARD, "Proxy::StartLocating Transact ErrCodes = %{public}d", error);
return error;
}
// 处理这个消息 START_LOCATING
// base/location/services/location_locator/locator/source/locator_skeleton.cpp
int LocatorAbilityStub::PreStartLocating(MessageParcel &data, MessageParcel &reply, AppIdentity &identity)
{ // 是否打开location 开关
if (!CheckLocationSwitchState(reply)) {
return ERRCODE_SWITCH_OFF;
}
if (!CheckLocationPermission(reply, identity)) {
return ERRCODE_PERMISSION_DENIED;
}
auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
if (locatorAbility == nullptr) {
LBSLOGE(LOCATOR, "PreStartLocating: LocatorAbility is nullptr.");
reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
return ERRCODE_SERVICE_UNAVAILABLE;
}
std::unique_ptr<RequestConfig> requestConfig = RequestConfig::Unmarshalling(data);
sptr<IRemoteObject> remoteObject = data.ReadRemoteObject();
if (remoteObject == nullptr) {
LBSLOGE(LOCATOR, "StartLocating remote object nullptr");
reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
return ERRCODE_SERVICE_UNAVAILABLE;
}
sptr<IRemoteObject::DeathRecipient> death(new (std::nothrow) LocatorCallbackDeathRecipient());
remoteObject->AddDeathRecipient(death);
sptr<ILocatorCallback> callback = iface_cast<ILocatorCallback>(remoteObject);
reply.WriteInt32(locatorAbility->StartLocating(requestConfig, callback, identity));
return ERRCODE_SUCCESS;
}
// base/location/services/location_locator/locator/source/locator_ability.cpp
LocationErrCode LocatorAbility::StartLocating(std::unique_ptr<RequestConfig>& requestConfig,
sptr<ILocatorCallback>& callback, AppIdentity &identity)
{
#if !defined(FEATURE_GNSS_SUPPORT) && !defined(FEATURE_NETWORK_SUPPORT) && !defined(FEATURE_PASSIVE_SUPPORT)
LBSLOGE(LOCATOR, "%{public}s: service unavailable", __func__);
return ERRCODE_NOT_SUPPORTED;
#endif
if (QuerySwitchState() == DISABLED) {
ReportErrorStatus(callback, ERROR_SWITCH_UNOPEN);
}
if (!CheckSaValid()) {
UpdateSaAbilityHandler();
}
// update offset before add request
if (reportManager_ == nullptr || requestManager_ == nullptr) {
return ERRCODE_SERVICE_UNAVAILABLE;
}
reportManager_->UpdateRandom();
// generate request object according to input params
std::shared_ptr<Request> request = std::make_shared<Request>();
request->SetUid(identity.GetUid());
request->SetPid(identity.GetPid());
request->SetTokenId(identity.GetTokenId());
request->SetFirstTokenId(identity.GetFirstTokenId());
request->SetPackageName(identity.GetBundleName());
request->SetRequestConfig(*requestConfig);
request->SetLocatorCallBack(callback);
request->SetUuid(std::to_string(CommonUtils::IntRandom(MIN_INT_RANDOM, MAX_INT_RANDOM)));
LBSLOGI(LOCATOR, "start locating");
requestManager_->HandleStartLocating(request);
ReportLocationStatus(callback, SESSION_START);
return ERRCODE_SUCCESS;
}
// base/location/services/location_locator/locator/source/request_manager.cpp
void RequestManager::HandleStartLocating(std::shared_ptr<Request> request)
{
auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
auto locatorDftManager = DelayedSingleton<LocatorDftManager>::GetInstance();
if (locatorAbility == nullptr || locatorDftManager == nullptr) {
return;
}
// restore request to all request list
bool isNewRequest = RestorRequest(request); ---> 不存在就添加,存在一样的则更新覆盖旧的
// update request map
if (isNewRequest) { // 新的需要做一些更新操作
locatorAbility->RegisterPermissionCallback(request->GetTokenId(),
{ACCESS_APPROXIMATELY_LOCATION, ACCESS_LOCATION, ACCESS_BACKGROUND_LOCATION});
UpdateRequestRecord(request, true);
UpdateUsingPermission(request);
locatorDftManager->LocationSessionStart(request);
}
// process location request
HandleRequest(); ---> 继续看位置请求
}
void RequestManager::HandleRequest()
{
auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
if (locatorAbility == nullptr) {
LBSLOGE(REQUEST_MANAGER, "locatorAbility is null");
return;
}
std::unique_lock<std::mutex> lock(requestMutex_, std::defer_lock);
lock.lock();
auto requests = locatorAbility->GetRequests();
lock.unlock();
if (requests == nullptr) {
LBSLOGE(REQUEST_MANAGER, "requests map is empty");
return;
}
std::map<std::string, std::list<std::shared_ptr<Request>>>::iterator iter;
for (iter = requests->begin(); iter != requests->end(); ++iter) {
std::string abilityName = iter->first;
std::list<std::shared_ptr<Request>> requestList = iter->second;
HandleRequest(abilityName, requestList);
}
}
// abilityName 是请求定位的类型,比如gnss、网络 ……等
void RequestManager::HandleRequest(std::string abilityName, std::list<std::shared_ptr<Request>> list)
{
// generate work record, and calculate interval
std::shared_ptr<WorkRecord> workRecord = std::make_shared<WorkRecord>();
for (auto iter = list.begin(); iter != list.end(); iter++) {
auto request = *iter;
if (!AddRequestToWorkRecord(request, workRecord)) {
continue;
}
if (!ActiveLocatingStrategies(request)) {
continue;
}
LBSLOGD(REQUEST_MANAGER, "add pid:%{public}d uid:%{public}d %{public}s", request->GetPid(), request->GetUid(),
request->GetPackageName().c_str());
}
LBSLOGD(REQUEST_MANAGER, "detect %{public}s ability requests(size:%{public}s) work record:%{public}s",
abilityName.c_str(), std::to_string(list.size()).c_str(), workRecord->ToString().c_str());
ProxySendLocationRequest(abilityName, *workRecord); ---> 继续看代码
}
void RequestManager::ProxySendLocationRequest(std::string abilityName, WorkRecord& workRecord)
{
auto locationSaLoadManager = DelayedSingleton<LocationSaLoadManager>::GetInstance();
if (locationSaLoadManager == nullptr) {
return;
}
int systemAbilityId = CommonUtils::AbilityConvertToId(abilityName);
locationSaLoadManager->LoadLocationSa(systemAbilityId);
sptr<IRemoteObject> remoteObject = CommonUtils::GetRemoteObject(systemAbilityId, CommonUtils::InitDeviceId());
if (remoteObject == nullptr) {
LBSLOGE(LOCATOR, "%{public}s: remote obj is nullptr", __func__);
return;
}
workRecord.SetDeviceId(CommonUtils::InitDeviceId());
if (abilityName == GNSS_ABILITY) {
#ifdef FEATURE_GNSS_SUPPORT
std::unique_ptr<GnssAbilityProxy> gnssProxy = std::make_unique<GnssAbilityProxy>(remoteObject);
gnssProxy->SendLocationRequest(workRecord);
#endif
} else if (abilityName == NETWORK_ABILITY) {
#ifdef FEATURE_NETWORK_SUPPORT
std::unique_ptr<NetworkAbilityProxy> networkProxy = std::make_unique<NetworkAbilityProxy>(remoteObject);
networkProxy->SendLocationRequest(workRecord);
#endif
} else if (abilityName == PASSIVE_ABILITY) {
#ifdef FEATURE_PASSIVE_SUPPORT
std::unique_ptr<PassiveAbilityProxy> passiveProxy = std::make_unique<PassiveAbilityProxy>(remoteObject);
passiveProxy->SendLocationRequest(workRecord);
#endif
}
auto fusionController = DelayedSingleton<FusionController>::GetInstance();
if (fusionController != nullptr) {
fusionController->Process(abilityName);
}
}
上面的代码可以看到,会根据 abilityName 来确定走的是哪一个,这里假设我们是 gps,所以就会走到
gnssProxy->SendLocationRequest(workRecord);
对应看gnss里面的方法:
// base/location/services/location_locator/locator/source/gnss_ability_proxy.cpp
LocationErrCode GnssAbilityProxy::SendLocationRequest(WorkRecord &workrecord)
{
MessageParcel data;
MessageParcel reply;
MessageOption option;
if (!data.WriteInterfaceToken(GetDescriptor())) {
LBSLOGE(GNSS, "write interfaceToken fail!");
return ERRCODE_SERVICE_UNAVAILABLE;
}
workrecord.Marshalling(data);
int error = Remote()->SendRequest(static_cast<uint32_t>(GnssInterfaceCode::SEND_LOCATION_REQUEST),
data,
reply,
option);
LBSLOGD(GNSS, "%{public}s Transact Error = %{public}d", __func__, error);
return LocationErrCode(reply.ReadInt32());
}
这里其实就是把数据和参数封装,然后发送 SEND_LOCATION_REQUEST 消息给对应的SA stub 处理。
// base/location/services/location_gnss/gnss/source/gnss_ability_skeleton.cpp
int GnssAbilityStub::OnRemoteRequest(uint32_t code,
MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
pid_t callingPid = IPCSkeleton::GetCallingPid();
pid_t callingUid = IPCSkeleton::GetCallingUid();
LBSLOGI(GNSS, "OnRemoteRequest cmd = %{public}u, flags= %{public}d, pid= %{public}d, uid= %{public}d",
code, option.GetFlags(), callingPid, callingUid);
if (data.ReadInterfaceToken() != GetDescriptor()) {
LBSLOGE(GNSS, "invalid token.");
reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
return ERRCODE_SERVICE_UNAVAILABLE;
}
int ret = ERRCODE_SUCCESS;
bool isMessageRequest = false;
switch (code) {
case static_cast<uint32_t>(GnssInterfaceCode::SEND_LOCATION_REQUEST): // 处理 SEND_LOCATION_REQUEST 消息的地方
case static_cast<uint32_t>(GnssInterfaceCode::SET_MOCKED_LOCATIONS): {
if (!CommonUtils::CheckCallingPermission(callingUid, callingPid, reply)) {
return ERRCODE_PERMISSION_DENIED;
}
SendMessage(code, data, reply);
isMessageRequest = true;
break;
}
// base/location/services/location_gnss/gnss/source/gnss_ability.cpp
void GnssAbility::SendMessage(uint32_t code, MessageParcel &data, MessageParcel &reply)
{
if (gnssHandler_ == nullptr) {
reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
return;
}
switch (code) {
case static_cast<uint32_t>(GnssInterfaceCode::SEND_LOCATION_REQUEST): {
std::unique_ptr<WorkRecord> workrecord = WorkRecord::Unmarshalling(data);
AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent:: Get(code, workrecord);
if (gnssHandler_->SendEvent(event)) { ---> 处理这个事件
reply.WriteInt32(ERRCODE_SUCCESS);
} else {
reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
}
break;
}
…… …… …… …… …… …… …… …… …… …… …… …… …… …… …… …… …… ……
// 处理 SEND_LOCATION_REQUEST
void GnssHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer& event)
{
auto gnssAbility = DelayedSingleton<GnssAbility>::GetInstance();
if (gnssAbility == nullptr) {
LBSLOGE(GNSS, "ProcessEvent: gnss ability is nullptr");
return;
}
uint32_t eventId = event->GetInnerEventId();
LBSLOGI(GNSS, "ProcessEvent event:%{public}d", eventId);
switch (eventId) {
case EVENT_REPORT_LOCATION: {
gnssAbility->ProcessReportLocationMock();
break;
}
case static_cast<uint32_t>(GnssInterfaceCode::SEND_LOCATION_REQUEST): {
std::unique_ptr<WorkRecord> workrecord = event->GetUniqueObject<WorkRecord>();
if (workrecord != nullptr) {
gnssAbility->LocationRequest(*workrecord); ---> 发送给gnss SA 处理
}
break;
}
其实我们通过代码可以看到,再往下,就是通过 HDI 到驱动了,驱动再去打开硬件做相应的操作,需要看对应的平台代码。