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