1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifdef FEATURE_GNSS_SUPPORT
17 #include "agnss_ni_manager.h"
18
19 #ifdef SMS_MMS_ENABLE
20 #include "call_manager_client.h"
21 #include "sms_service_manager_client.h"
22 #endif
23 #include "gnss_ability.h"
24 #include "idevmgr_hdi.h"
25 #include "iservice_registry.h"
26 #include "location_data_rdb_manager.h"
27 #include "location_log.h"
28 #include "nlohmann/json.hpp"
29 #ifdef NOTIFICATION_ENABLE
30 #include "notification_helper.h"
31 #endif
32 #include "securec.h"
33 #include "string_utils.h"
34 #include "system_ability_definition.h"
35 #include "ui_extension_ability_connection.h"
36 #include "want_agent_helper.h"
37 #include "want_agent_info.h"
38
39 namespace OHOS {
40 namespace Location {
41 using namespace EventFwk;
42 constexpr uint32_t MAX_RETRY_TIMES = 3;
43 constexpr uint32_t TIME_AFTER_EMERGENCY_CALL = 10 * 1000;
44 constexpr int32_t INVALID_SUBID = -1;
45 const std::string URN_APPLICATION_ID = "x-oma-application:ulp.ua";
46 const std::string AGNSS_NI_SERVICE_NAME = "agnss_ni";
47 const std::string LOCATION_DIALOG_BUNDLE_NAME = "com.ohos.locationdialog";
48 const std::string AGNSS_NI_DIALOG_ABILITY_NAME = "ConfirmUIExtAbility";
49 #ifdef NOTIFICATION_ENABLE
50 const int32_t GNSS_AGNSS_NI_NOTIFICATION_ID = LOCATION_GNSS_SA_ID * 100;
51 constexpr uint32_t NOTIFICATION_AUTO_DELETED_TIME = 1000;
52 #endif
53
GetInstance()54 AGnssNiManager* AGnssNiManager::GetInstance()
55 {
56 static AGnssNiManager data;
57 return &data;
58 }
59
AGnssNiManager()60 AGnssNiManager::AGnssNiManager()
61 {}
62
~AGnssNiManager()63 AGnssNiManager::~AGnssNiManager()
64 {}
65
SubscribeSaStatusChangeListerner()66 void AGnssNiManager::SubscribeSaStatusChangeListerner()
67 {
68 LBSLOGI(GNSS, "AGNSS-NI SubscribeSaStatusChangeListerner");
69 sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
70 if (samgrProxy == nullptr) {
71 LBSLOGE(GNSS, "failed to get samgrProxy");
72 return;
73 }
74 statusChangeListener_ = new SystemAbilityStatusChangeListener();
75 if (statusChangeListener_ == nullptr) {
76 LBSLOGE(GNSS, "statusChangeListener_ is nullptr!");
77 return;
78 }
79 int32_t ret = samgrProxy->SubscribeSystemAbility(COMMON_EVENT_SERVICE_ID, statusChangeListener_);
80 if (ret != ERR_OK) {
81 LBSLOGE(GNSS, "subscribe systemAbilityId: call manager service failed!");
82 return;
83 }
84 }
85
RegisterAgnssNiEvent()86 void AGnssNiManager::RegisterAgnssNiEvent()
87 {
88 MatchingSkills matchingSkills;
89 matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_SMS_WAPPUSH_RECEIVE_COMPLETED);
90 matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_SMS_RECEIVE_COMPLETED);
91 matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_CALL_STATE_CHANGED);
92 CommonEventSubscribeInfo subscriberInfo(matchingSkills);
93 subscriber_ = std::make_shared<GnssCommonEventSubscriber>(subscriberInfo);
94
95 uint32_t count = 0;
96 bool result = false;
97 while (!result && count <= MAX_RETRY_TIMES) {
98 result = CommonEventManager::SubscribeCommonEvent(subscriber_);
99 count++;
100 }
101 if (count > MAX_RETRY_TIMES || !result) {
102 LBSLOGE(GNSS, "Failed to subscriber gnss event");
103 } else {
104 LBSLOGI(GNSS, "success to subscriber gnss event");
105 }
106 }
107
RegisterNiResponseEvent()108 void AGnssNiManager::RegisterNiResponseEvent()
109 {
110 MatchingSkills matchingSkills;
111 matchingSkills.AddEvent(AGNSS_NI_ACCEPT_EVENT);
112 matchingSkills.AddEvent(AGNSS_NI_REJECT_EVENT);
113 CommonEventSubscribeInfo subscriberInfo(matchingSkills);
114 subscriberInfo.SetPermission("ohos.permission.PUBLISH_LOCATION_EVENT");
115 niResponseSubscriber_ = std::make_shared<GnssCommonEventSubscriber>(subscriberInfo);
116
117 uint32_t count = 0;
118 bool result = false;
119 while (!result && count <= MAX_RETRY_TIMES) {
120 result = CommonEventManager::SubscribeCommonEvent(niResponseSubscriber_);
121 count++;
122 }
123 if (count > MAX_RETRY_TIMES || !result) {
124 LBSLOGE(GNSS, "Failed to subscriber ni response event");
125 } else {
126 LBSLOGI(GNSS, "success to subscriber ni response event");
127 }
128 }
129
Run()130 void AGnssNiManager::Run()
131 {
132 LBSLOGI(GNSS, "AGNSS-NI: Run");
133 RegisterAgnssNiEvent();
134 RegisterNiResponseEvent();
135 sptr<IGnssInterface> gnssInterface = HDI::Location::Gnss::V2_0::IGnssInterface::Get();
136 if (gnssInterface == nullptr) {
137 auto gnssAbility = GnssAbility::GetInstance();
138 if (!gnssAbility->CheckIfHdiConnected()) {
139 gnssAbility->ConnectHdi();
140 gnssInterface = HDI::Location::Gnss::V2_0::IGnssInterface::Get();
141 }
142 }
143 }
144
UnRegisterAgnssNiEvent()145 void AGnssNiManager::UnRegisterAgnssNiEvent()
146 {
147 if (subscriber_ == nullptr) {
148 LBSLOGE(GNSS, "UnRegisterAgnssNiEvent subscriber_ is null");
149 return;
150 }
151 bool result = CommonEventManager::UnSubscribeCommonEvent(subscriber_);
152 subscriber_ = nullptr;
153 LBSLOGI(GNSS, "unSubscriber gnss event, result = %{public}d", result);
154 }
155
UnRegisterNiResponseEvent()156 void AGnssNiManager::UnRegisterNiResponseEvent()
157 {
158 if (niResponseSubscriber_ == nullptr) {
159 LBSLOGE(GNSS, "UnRegisterAgnssNiEvent subscriber_ is null");
160 return;
161 }
162 bool result = CommonEventManager::UnSubscribeCommonEvent(niResponseSubscriber_);
163 niResponseSubscriber_ = nullptr;
164 LBSLOGI(GNSS, "unSubscriber ni response event, result = %{public}d", result);
165 }
166
AgnssNiSuplInit()167 void AGnssNiManager::AgnssNiSuplInit()
168 {
169 #ifdef HDF_DRIVERS_INTERFACE_AGNSS_ENABLE
170 auto gnssAbility = GnssAbility::GetInstance();
171 if (gnssAbility != nullptr) {
172 gnssAbility->SetAgnssServer();
173 }
174 #endif
175 }
176
177 #ifdef SMS_MMS_ENABLE
IsFromDefaultSubId(const OHOS::EventFwk::Want & want)178 static bool IsFromDefaultSubId(const OHOS::EventFwk::Want &want)
179 {
180 int32_t subId = want.GetIntParam("slotId", INVALID_SUBID);
181 int32_t defaultId = Singleton<Telephony::SmsServiceManagerClient>::GetInstance().GetDefaultSmsSlotId();
182 LBSLOGD(GNSS, "current subId %{public}d, defaultSubId %{public}d", subId, defaultId);
183 if (subId != INVALID_SUBID && subId != defaultId) {
184 return false;
185 }
186 return true;
187 }
188 #endif
189
CheckWapSuplInit(const EventFwk::Want & want)190 void AGnssNiManager::CheckWapSuplInit(const EventFwk::Want &want)
191 {
192 #ifdef SMS_MMS_ENABLE
193 AgnssNiSuplInit();
194 if (!IsFromDefaultSubId(want)) {
195 LBSLOGE(GNSS, "supl init message does not come from default sub");
196 return;
197 }
198
199 std::string applicationId = want.GetStringParam("applicationId");
200 /*
201 * The WAP application id SHALL be as registered with OMNA (URN: x-oma-application:ulp.ua)
202 * and the assigned code value is (0x10).
203 */
204 if (!(applicationId == "16" || applicationId == URN_APPLICATION_ID)) {
205 LBSLOGE(GNSS, "supl init message application Id %{public}s", applicationId.c_str());
206 return;
207 }
208
209 std::string rawData = want.GetStringParam("rawData");
210 sptr<IGnssInterface> gnssInterface = HDI::Location::Gnss::V2_0::IGnssInterface::Get();
211 if (gnssInterface == nullptr) {
212 LBSLOGE(GNSS, "gnssInterfacev1_0 is nullptr");
213 return;
214 }
215 gnssInterface->SendNetworkInitiatedMsg(rawData, rawData.length());
216 #endif
217 }
218
CheckSmsSuplInit(const EventFwk::Want & want)219 void AGnssNiManager::CheckSmsSuplInit(const EventFwk::Want &want)
220 {
221 #ifdef SMS_MMS_ENABLE
222 AgnssNiSuplInit();
223 if (!IsFromDefaultSubId(want)) {
224 LBSLOGE(GNSS, "supl init message does not come from default sub");
225 return;
226 }
227
228 std::vector<std::string> pdus = want.GetStringArrayParam(std::string("pdus"));
229 if (pdus.empty()) {
230 LBSLOGI(GNSS, "pdus is null");
231 return;
232 }
233 bool isCdma = want.GetBoolParam("isCdma", false);
234 std::vector<unsigned char> pdu = StringUtils::HexToByteVector(pdus[0]);
235 auto message = new Telephony::ShortMessage();
236 std::u16string netType = isCdma ? u"3gpp2" : u"3gpp";
237 Telephony::ShortMessage::CreateMessage(pdu, netType, *message);
238
239 if (message != nullptr) {
240 std::string rawUserData = StringUtils::StringToHex(message->GetRawUserData());
241 sptr<IGnssInterface> gnssInterface = HDI::Location::Gnss::V2_0::IGnssInterface::Get();
242 if (gnssInterface == nullptr) {
243 LBSLOGE(GNSS, "gnssInterfacev1_0 is nullptr");
244 delete message;
245 message = nullptr;
246 return;
247 }
248 gnssInterface->SendNetworkInitiatedMsg(rawUserData, rawUserData.length());
249 delete message;
250 message = nullptr;
251 }
252 #endif
253 }
254
IsInEmergency()255 bool AGnssNiManager::IsInEmergency()
256 {
257 std::unique_lock<std::mutex> lock(callStateMutex_);
258 bool isInEmergencyExtension = (emergencyCallEndTime_ > 0) &&
259 ((CommonUtils::GetCurrentTime() - emergencyCallEndTime_) < TIME_AFTER_EMERGENCY_CALL);
260
261 return isInEmergencyCall_ || isInEmergencyExtension;
262 }
263
OnCallStateChanged(const EventFwk::Want & want)264 void AGnssNiManager::OnCallStateChanged(const EventFwk::Want &want)
265 {
266 #ifdef CALL_MANAGER_ENABLE
267 int32_t state = want.GetIntParam("state", (int32_t)Telephony::TelCallState::CALL_STATUS_UNKNOWN);
268 if (state == (int32_t)Telephony::TelCallState::CALL_STATUS_DIALING) {
269 int32_t slotId = want.GetIntParam("slotId", -1);
270 std::string phoneNumber = want.GetStringParam("number");
271 auto tmpPhoneNumber = Str8ToStr16(phoneNumber);
272 std::unique_lock<std::mutex> lock(callStateMutex_);
273 auto clientPtr = DelayedSingleton<Telephony::CallManagerClient>::GetInstance();
274 clientPtr->Init(OHOS::TELEPHONY_CALL_MANAGER_SYS_ABILITY_ID);
275 clientPtr->IsEmergencyPhoneNumber(tmpPhoneNumber, slotId, isInEmergencyCall_);
276 if (isInEmergencyCall_) {
277 emergencyCallEndTime_ = CommonUtils::GetCurrentTime();
278 isInEmergencyCall_ = false;
279 }
280 }
281 return;
282 #endif
283 }
284
BuildStartCommand(const GnssNiNotificationRequest & notif)285 std::string AGnssNiManager::BuildStartCommand(const GnssNiNotificationRequest ¬if)
286 {
287 nlohmann::json param;
288 std::string uiType = "sysDialog/common";
289 param["ability.want.params.uiExtensionType"] = uiType;
290 std::string message = DecodeNiString(notif.supplicantInfo, notif.supplicantInfoEncoding) +
291 DecodeNiString(notif.notificationText, notif.notificationTextEncoding);
292 param["message"] = message;
293 std::string cmdData = param.dump();
294 LBSLOGD(GNSS, "cmdData is: %{public}s.", cmdData.c_str());
295 return cmdData;
296 }
297
ConnectExtensionAbility(const AAFwk::Want & want,const std::string & commandStr)298 static void ConnectExtensionAbility(const AAFwk::Want &want, const std::string &commandStr)
299 {
300 std::string bundleName = LOCATION_DIALOG_BUNDLE_NAME;
301 std::string abilityName = AGNSS_NI_DIALOG_ABILITY_NAME;
302 sptr<UIExtensionAbilityConnection> connection(
303 new (std::nothrow) UIExtensionAbilityConnection(commandStr, bundleName, abilityName));
304 if (connection == nullptr) {
305 LBSLOGE(GNSS, "connect UIExtensionAbilityConnection fail");
306 return;
307 }
308
309 std::string identity = IPCSkeleton::ResetCallingIdentity();
310 auto ret =
311 AAFwk::ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(want, connection, nullptr, -1);
312 LBSLOGI(GNSS, "connect service extension ability result = %{public}d", ret);
313 IPCSkeleton::SetCallingIdentity(identity);
314 return;
315 }
316
OpenNiDialog(const GnssNiNotificationRequest & notif)317 void AGnssNiManager::OpenNiDialog(const GnssNiNotificationRequest ¬if)
318 {
319 LBSLOGI(GNSS, "ConnectExtension");
320 AAFwk::Want want;
321 std::string bundleName = "com.ohos.sceneboard";
322 std::string abilityName = "com.ohos.sceneboard.systemdialog";
323 want.SetElementName(bundleName, abilityName);
324 std::string connectStr = BuildStartCommand(notif);
325 ConnectExtensionAbility(want, connectStr);
326 }
327
DecodeNiString(std::string original,int coding)328 std::string AGnssNiManager::DecodeNiString(std::string original, int coding)
329 {
330 if (coding == GNSS_NI_ENCODING_FORMAT_NULL) {
331 return original;
332 }
333
334 std::string tmp = StringUtils::HexToString(original);
335 switch (coding) {
336 case GNSS_NI_ENCODING_FORMAT_SUPL_GSM_DEFAULT: {
337 return StringUtils::Gsm7Decode(tmp);
338 }
339 case GNSS_NI_ENCODING_FORMAT_SUPL_UCS2: {
340 std::wstring decodedUCS2String = StringUtils::Ucs2ToWstring(tmp);
341 return StringUtils::WstringToString(decodedUCS2String);
342 }
343 case GNSS_NI_ENCODING_FORMAT_SUPL_UTF8: {
344 std::wstring decodedUTF8String = StringUtils::Utf8ToWstring(tmp);
345 return StringUtils::WstringToString(decodedUTF8String);
346 }
347 default: {
348 LBSLOGE(GNSS, "unknow encoding %{public}d for NI text %{public}s", coding, original.c_str());
349 return original;
350 }
351 }
352 }
353
SendNiNotification(const GnssNiNotificationRequest & notif)354 void AGnssNiManager::SendNiNotification(const GnssNiNotificationRequest ¬if)
355 {
356 #ifdef NOTIFICATION_ENABLE
357 std::shared_ptr<Notification::NotificationNormalContent> notificationNormalContent =
358 std::make_shared<Notification::NotificationNormalContent>();
359 std::string title = "Location Request";
360 std::string msgBody = DecodeNiString(notif.supplicantInfo, notif.supplicantInfoEncoding) +
361 DecodeNiString(notif.notificationText, notif.notificationTextEncoding);
362 if (msgBody.empty()) {
363 msgBody = "SUPL Service";
364 }
365 std::string message = "Requested by " + msgBody;
366 notificationNormalContent->SetTitle(title);
367 notificationNormalContent->SetText(message);
368 std::shared_ptr<OHOS::Notification::NotificationContent> notificationContent =
369 std::make_shared<OHOS::Notification::NotificationContent>(notificationNormalContent);
370 Notification::NotificationRequest request;
371 request.SetNotificationId(GNSS_AGNSS_NI_NOTIFICATION_ID);
372 request.SetContent(notificationContent);
373 request.SetCreatorUid(LOCATION_GNSS_SA_ID);
374 request.SetAutoDeletedTime(NOTIFICATION_AUTO_DELETED_TIME);
375 request.SetTapDismissed(true);
376 request.SetCreatorBundleName(AGNSS_NI_SERVICE_NAME);
377 request.SetSlotType(Notification::NotificationConstant::SlotType::SOCIAL_COMMUNICATION);
378
379 int32_t ret = Notification::NotificationHelper::PublishNotification(request);
380 if (ret != 0) {
381 LBSLOGE(GNSS, "Publish Notification errorCode = %{public}d", ret);
382 return;
383 }
384 LBSLOGI(GNSS, "GNSS service publish notification success");
385 #else
386 LBSLOGI(GNSS, "GNSS service publish notification not support");
387 #endif
388 }
389
SendUserResponse(GnssNiResponseCmd responseCmd)390 void AGnssNiManager::SendUserResponse(GnssNiResponseCmd responseCmd)
391 {
392 sptr<IGnssInterface> gnssInterface = HDI::Location::Gnss::V2_0::IGnssInterface::Get();
393 if (gnssInterface == nullptr) {
394 LBSLOGE(GNSS, "gnssInterfacev1_0 is nullptr");
395 return;
396 }
397 gnssInterface->SendNiUserResponse(niNotificationId_.load(), responseCmd);
398 }
399
HandleNiNotification(const GnssNiNotificationRequest & notif)400 void AGnssNiManager::HandleNiNotification(const GnssNiNotificationRequest ¬if)
401 {
402 niNotificationId_.store(notif.gnssNiNotificationId);
403 bool needNotify = (notif.notificationCategory & GNSS_NI_NOTIFICATION_REQUIRE_NOTIFY) != 0;
404 bool needVerify = (notif.notificationCategory & GNSS_NI_NOTIFICATION_REQUIRE_VERIFY) != 0;
405 bool privacyOverride = (notif.notificationCategory & GNSS_NI_NOTIFICATION_REQUIRE_PRIVACY_OVERRIDE) != 0;
406 if (LocationDataRdbManager::QuerySwitchState() != ENABLED && !IsInEmergency()) {
407 SendUserResponse(GNSS_NI_RESPONSE_CMD_NO_RESPONSE);
408 }
409
410 if (needNotify) {
411 if (needVerify) {
412 OpenNiDialog(notif);
413 } else {
414 SendNiNotification(notif);
415 SendUserResponse(GNSS_NI_RESPONSE_CMD_ACCEPT);
416 }
417 }
418
419 if (!needNotify || privacyOverride) {
420 SendUserResponse(GNSS_NI_RESPONSE_CMD_ACCEPT);
421 }
422 }
423
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)424 void SystemAbilityStatusChangeListener::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
425 {
426 LBSLOGI(GNSS, "AGNSS-NI systemAbilityId:%{public}d", systemAbilityId);
427 if (systemAbilityId != COMMON_EVENT_SERVICE_ID) {
428 LBSLOGE(GNSS, "systemAbilityId is not COMMON_EVENT_SERVICE_ID");
429 return;
430 }
431 auto agnssNiManager = AGnssNiManager::GetInstance();
432 agnssNiManager->Run();
433
434 return;
435 }
436
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)437 void SystemAbilityStatusChangeListener::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
438 {
439 LBSLOGI(GNSS, "AGNSS-NI systemAbilityId:%{public}d", systemAbilityId);
440 if (systemAbilityId != COMMON_EVENT_SERVICE_ID) {
441 LBSLOGE(GNSS, "systemAbilityId is not COMMON_EVENT_SERVICE_ID");
442 return;
443 }
444 auto agnssNiManager = AGnssNiManager::GetInstance();
445 agnssNiManager->UnRegisterAgnssNiEvent();
446 agnssNiManager->UnRegisterNiResponseEvent();
447 return;
448 }
449
450 #ifdef NET_MANAGER_ENABLE
NetConnectionPropertiesChange(sptr<NetManagerStandard::NetHandle> & netHandle,const sptr<NetManagerStandard::NetLinkInfo> & info)451 int32_t AGnssNiNetworkCallbackEs::NetConnectionPropertiesChange(
452 sptr<NetManagerStandard::NetHandle> &netHandle, const sptr<NetManagerStandard::NetLinkInfo> &info)
453 {
454 return ERR_OK;
455 }
456
NetLost(sptr<NetManagerStandard::NetHandle> & netHandle)457 int32_t AGnssNiNetworkCallbackEs::NetLost(sptr<NetManagerStandard::NetHandle> &netHandle)
458 {
459 return ERR_OK;
460 }
461
NetUnavailable()462 int32_t AGnssNiNetworkCallbackEs::NetUnavailable()
463 {
464 return ERR_OK;
465 }
466
NetConnectionPropertiesChange(sptr<NetManagerStandard::NetHandle> & netHandle,const sptr<NetManagerStandard::NetLinkInfo> & info)467 int32_t AGnssNiNetworkCallback::NetConnectionPropertiesChange(
468 sptr<NetManagerStandard::NetHandle> &netHandle, const sptr<NetManagerStandard::NetLinkInfo> &info)
469 {
470 return ERR_OK;
471 }
472
NetLost(sptr<NetManagerStandard::NetHandle> & netHandle)473 int32_t AGnssNiNetworkCallback::NetLost(sptr<NetManagerStandard::NetHandle> &netHandle)
474 {
475 return ERR_OK;
476 }
477
NetUnavailable()478 int32_t AGnssNiNetworkCallback::NetUnavailable()
479 {
480 return ERR_OK;
481 }
482 #endif
483 } // namespace Location
484 } // namespace OHOS
485 #endif
486