1 /*
2 * Copyright (C) 2021 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 #include "call_earthquake_alarm_locator.h"
17 #include "call_manager_base.h"
18 #include "ffrt.h"
19
20 using namespace std;
21 using namespace OHOS::Telephony;
22 using namespace OHOS::Location;
23 using namespace OHOS::EventFwk;
24 namespace OHOS {
25 namespace Telephony {
26 using namespace AppExecFwk;
27 const int MyLocationEngine::DISTANCE_INTERVAL = 10000; /** 10 kilometers */
28 const int MyLocationEngine::TIMER_INTERVAL = 0;
29 const std::string MyLocationEngine::EMERGENCY_DEVICE_ID = "";
30 const std::string MyLocationEngine::EMERGENCY_BUNDLE_NAME = "";
31 const std::string MyLocationEngine::EMERGENCY_ABILITY_NAME = "";
32 const std::string MyLocationEngine::EMERGENCY_ABILITY_NAME_ECC = "EccServiceExtAbility";
33 const std::string MyLocationEngine::PARAMETERS_VALUE = "call_manager_earthquake_alarm";
34 const char* MyLocationEngine::PARAMETERS_KEY = "callerName";
35 const char* MyLocationEngine::PARAMETERS_KEY_PHONE_NUMBER = "phoneNumber";
36 const char* MyLocationEngine::PARAMETERS_KEY_SLOTID = "slotId";
37 const std::string MyLocationEngine::PARAMETERS_VALUE_ECC = "call_status_manager";
38 const std::string MyLocationEngine::PARAMETERS_VALUE_OOBE = "call_manager_oobe_earthquake_warning_switch_on";
39 const std::string MyLocationEngine::ALARM_SWITCH_ON = "1";
40 const std::string MyLocationEngine::ALARM_SWITCH_OFF = "0";
41 const std::string MyLocationEngine::INITIAL_FIRST_VALUE = "invalid";
42 std::shared_ptr<MyLocationEngine> MyLocationEngine::mylocator = std::make_shared<MyLocationEngine>();
GetInstance()43 std::shared_ptr<MyLocationEngine> MyLocationEngine::GetInstance()
44 {
45 if (mylocator != nullptr) {
46 return mylocator;
47 }
48 return std::make_shared<MyLocationEngine>();
49 }
50
OnInit()51 void MyLocationEngine::OnInit()
52 {
53 this->requestConfig = nullptr;
54 this->locatorCallback_ = nullptr;
55 this->locatorImpl = nullptr;
56 this->switchCallback_ = nullptr;
57 }
58
MyLocationEngine()59 MyLocationEngine::MyLocationEngine() {}
60
~MyLocationEngine()61 MyLocationEngine::~MyLocationEngine()
62 {
63 UnRegisterSwitchCallback();
64 UnregisterLocationChange();
65 this->OnInit();
66 }
67
SetValue()68 void MyLocationEngine::SetValue()
69 {
70 if (this->locatorImpl == nullptr) {
71 this->locatorImpl = Location::Locator::GetInstance();
72 if (this->locatorImpl == nullptr) {
73 TELEPHONY_LOGE("locatorCallback_ is null");
74 return;
75 }
76 locationEnabled_ = locatorImpl->IsLocationEnabled();
77 TELEPHONY_LOGI("locatorImpl is not nullptr");
78 }
79 if (this->requestConfig == nullptr) {
80 this->requestConfig = std::make_unique<RequestConfig>(Location::SCENE_NO_POWER);
81 this->requestConfig->SetTimeInterval(TIMER_INTERVAL);
82 this->requestConfig->SetDistanceInterval(DISTANCE_INTERVAL);
83 TELEPHONY_LOGI("requestConfig initial");
84 }
85 }
86
RegisterLocationChange()87 void MyLocationEngine::RegisterLocationChange()
88 {
89 if (locatorImpl == nullptr) {
90 TELEPHONY_LOGE("locatorImpl is null");
91 return;
92 }
93 if (locatorCallback_ == nullptr) {
94 locatorCallback_ =
95 sptr<MyLocationEngine::MyLocationCallBack>(new (std::nothrow) MyLocationEngine::MyLocationCallBack());
96 if (locatorCallback_ == nullptr) {
97 TELEPHONY_LOGE("locatorCallback_ is null");
98 return;
99 }
100 }
101 bool IsLocationEnable;
102 locatorImpl->IsLocationEnabledV9(IsLocationEnable);
103 if (IsLocationEnable == false) {
104 return;
105 }
106 auto callback = sptr<Location::ILocatorCallback>(locatorCallback_);
107 int code = this->locatorImpl->StartLocatingV9(this->requestConfig, callback);
108 TELEPHONY_LOGI("start listen location change code = %{public}d.", code);
109 }
110
UnregisterLocationChange()111 void MyLocationEngine::UnregisterLocationChange()
112 {
113 if (locatorImpl == nullptr || locatorCallback_ == nullptr) {
114 return;
115 }
116 auto callback = sptr<Location::ILocatorCallback>(locatorCallback_);
117 auto code = this->locatorImpl->StopLocatingV9(callback);
118 TELEPHONY_LOGI("stopListencdode = %{public}d.", code);
119 }
120
RegisterSwitchCallback()121 void MyLocationEngine::RegisterSwitchCallback()
122 {
123 if (locatorImpl == nullptr) {
124 TELEPHONY_LOGE("locatorImpl is null.");
125 return;
126 }
127 auto engine = MyLocationEngine::GetInstance();
128 if (switchCallback_ == nullptr) {
129 switchCallback_ = sptr<MyLocationEngine::MySwitchCallback>(
130 new (std::nothrow) MyLocationEngine::MySwitchCallback(engine));
131 if (switchCallback_ == nullptr) {
132 TELEPHONY_LOGE("callback is null.");
133 return;
134 }
135 }
136 auto code = locatorImpl->RegisterSwitchCallbackV9(switchCallback_->AsObject());
137 TELEPHONY_LOGI("register switch callback code = %{public}d. success", code);
138 }
139
UnRegisterSwitchCallback()140 void MyLocationEngine::UnRegisterSwitchCallback()
141 {
142 if (locatorImpl == nullptr) {
143 TELEPHONY_LOGE("locatorImpl is null.");
144 return;
145 }
146 if (switchCallback_ != nullptr) {
147 TELEPHONY_LOGE("unregister switch callback");
148 locatorImpl->UnregisterSwitchCallbackV9(switchCallback_->AsObject());
149 }
150 }
151
LocationSwitchChange()152 void MyLocationEngine::LocationSwitchChange()
153 {
154 if (locatorImpl == nullptr) {
155 TELEPHONY_LOGE("locatorImpl is null.");
156 return;
157 }
158 bool locationEnabled = locationEnabled_;
159 locationEnabled_ = locatorImpl->IsLocationEnabled();
160 if (!locationEnabled && locationEnabled_) {
161 TELEPHONY_LOGI("Enable location.[%{public}d][%{public}d]", locationEnabled, locationEnabled_);
162 RegisterLocationChange();
163 } else if (locationEnabled && !locationEnabled_) {
164 TELEPHONY_LOGI("Disable location.[%{public}d][%{public}d]", locationEnabled, locationEnabled_);
165 UnregisterLocationChange();
166 } else {
167 TELEPHONY_LOGI("Location switch not change[%{public}d]", locationEnabled_);
168 }
169 }
170
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)171 int32_t MyLocationEngine::MyLocationCallBack::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
172 MessageOption &option)
173 {
174 if (data.ReadInterfaceToken() != GetDescriptor()) {
175 TELEPHONY_LOGE("invalid token.");
176 return -1;
177 }
178 switch (code) {
179 case RECEIVE_LOCATION_INFO_EVENT: {
180 std::unique_ptr<OHOS::Location::Location> location =
181 OHOS::Location::Location::UnmarshallingMakeUnique(data);
182 OnLocationReport(location);
183 break;
184 }
185 case RECEIVE_ERROR_INFO_EVENT: {
186 int32_t errorCode = data.ReadInt32();
187 OnErrorReport(errorCode);
188 break;
189 }
190 case RECEIVE_LOCATION_STATUS_EVENT: {
191 int32_t status = data.ReadInt32();
192 OnLocatingStatusChange(status);
193 break;
194 }
195 default: {
196 break;
197 }
198 }
199 TELEPHONY_LOGI("locationreport code = %{public}d.", code);
200 return 0;
201 }
202
MyLocationCallBack()203 MyLocationEngine::MyLocationCallBack::MyLocationCallBack() {}
204
OnLocatingStatusChange(const int status)205 void MyLocationEngine::MyLocationCallBack::OnLocatingStatusChange(const int status)
206 {
207 TELEPHONY_LOGI("listen status = %{public}d", status);
208 }
209
OnErrorReport(const int errorCode)210 void MyLocationEngine::MyLocationCallBack::OnErrorReport(const int errorCode) {}
211
OnLocationReport(const std::unique_ptr<Location::Location> & location)212 void MyLocationEngine::MyLocationCallBack::OnLocationReport(const std::unique_ptr<Location::Location>& location)
213 {
214 TELEPHONY_LOGI("location report");
215 if (location == nullptr) {
216 TELEPHONY_LOGE("location is nullptr");
217 return;
218 }
219 AAFwk::Want want;
220 want.SetParam("latitude", std::to_string(location->GetLatitude()));
221 want.SetParam("longitude", std::to_string(location->GetLongitude()));
222 MyLocationEngine::ConnectAbility(MyLocationEngine::PARAMETERS_VALUE,
223 EmergencyCallConnectCallback::connectCallback_, want);
224 }
225
BootComplete(bool switchState)226 void MyLocationEngine::BootComplete(bool switchState)
227 {
228 if (!switchState) {
229 TELEPHONY_LOGE("the alarm switch is close");
230 return;
231 }
232 TELEPHONY_LOGI("the alarm switch is open");
233 MyLocationEngine::GetInstance()->SetValue();
234 MyLocationEngine::GetInstance()->RegisterLocationChange();
235 MyLocationEngine::GetInstance()->RegisterSwitchCallback();
236 }
237
MySwitchCallback(std::shared_ptr<MyLocationEngine> locationUpdate)238 MyLocationEngine::MySwitchCallback::MySwitchCallback(std::shared_ptr<MyLocationEngine> locationUpdate)
239 : locationUpdate_(locationUpdate)
240 {}
241
OnSwitchChange(const int state)242 void MyLocationEngine::MySwitchCallback::OnSwitchChange(const int state)
243 {
244 if (locationUpdate_ == nullptr) {
245 return;
246 }
247 locationUpdate_->LocationSwitchChange();
248 }
249
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)250 int MyLocationEngine::MySwitchCallback::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
251 MessageOption &option)
252 {
253 if (data.ReadInterfaceToken() != GetDescriptor()) {
254 TELEPHONY_LOGE("switchCallback invalid token.");
255 return -1;
256 }
257 switch (code) {
258 case RECEIVE_SWITCH_STATE_EVENT: {
259 int32_t status = data.ReadInt32();
260 OnSwitchChange(status);
261 break;
262 }
263 default: {
264 TELEPHONY_LOGI("receive error code:%{public}u", code);
265 break;
266 }
267 }
268 return 0;
269 }
270
IsSwitchOn(std::string key,std::string & value)271 bool MyLocationEngine::IsSwitchOn(std::string key, std::string& value)
272 {
273 auto datashareHelper = std::make_shared<DataShareSwitchState>();
274 OHOS::Uri uri(datashareHelper->DEFAULT_URI + key);
275 int resp = datashareHelper->QueryData(uri, key, value);
276 TELEPHONY_LOGI("query %{public}s is %{public}s", key.c_str(), value.c_str());
277 if (resp != DataShareSwitchState::TELEPHONY_SUCCESS || value == ALARM_SWITCH_OFF) {
278 return false;
279 }
280 return true;
281 }
282
283 std::map<std::string, sptr<AAFwk::IDataAbilityObserver>> MyLocationEngine::settingsCallbacks = {};
OOBEComplete()284 void MyLocationEngine::OOBEComplete()
285 {
286 std::string stateValue = INITIAL_FIRST_VALUE;
287 for (auto& oobeKey : OOBESwitchObserver::keyStatus) {
288 oobeKey.second = MyLocationEngine::IsSwitchOn(oobeKey.first, stateValue);
289 if (!oobeKey.second) {
290 settingsCallbacks[oobeKey.first] = sptr<OOBESwitchObserver>::MakeSptr(oobeKey.first);
291 auto datashareHelper = std::make_shared<DataShareSwitchState>();
292 datashareHelper->RegisterListenSettingsKey(oobeKey.first, true, settingsCallbacks[oobeKey.first]);
293 }
294 }
295 };
296
297 std::map<std::string, bool> OOBESwitchObserver::keyStatus = {
298 {"device_provisioned", false},
299 {"user_setup_complete", false},
300 {"is_ota_finished", false}
301 };
302
303 std::mutex OOBESwitchObserver::mutex_;
OnChange()304 void OOBESwitchObserver::OnChange()
305 {
306 std::lock_guard<std::mutex> lock(mutex_);
307 if (!keyStatus[mKey]) {
308 keyStatus[mKey] = MyLocationEngine::IsSwitchOn(mKey, mValue);
309 }
310 for (auto& oobeKey : keyStatus) {
311 if (!oobeKey.second) {
312 TELEPHONY_LOGE("%{public}s is trun off", oobeKey.first.c_str());
313 return;
314 }
315 }
316 mValue = MyLocationEngine::INITIAL_FIRST_VALUE;
317 if (MyLocationEngine::IsSwitchOn(LocationSubscriber::SWITCH_STATE_KEY, mValue)) {
318 TELEPHONY_LOGI("the alarm switch is open");
319 AAFwk::Want want;
320 MyLocationEngine::ConnectAbility(MyLocationEngine::PARAMETERS_VALUE_OOBE,
321 EmergencyCallConnectCallback::connectCallback_, want);
322 }
323 ffrt::submit([&]() {
324 for (auto& oobeKey : MyLocationEngine::settingsCallbacks) {
325 auto datashareHelper = std::make_shared<DataShareSwitchState>();
326 datashareHelper->RegisterListenSettingsKey(oobeKey.first, false, oobeKey.second);
327 oobeKey.second = nullptr;
328 }
329 TELEPHONY_LOGI("unregister listen finish");
330 });
331 }
332
333 std::mutex EmergencyCallConnectCallback::mutex_;
334 bool EmergencyCallConnectCallback::isStartEccService = false;
335 int32_t EmergencyCallConnectCallback::nowCallId = -1;
336 sptr<AAFwk::IAbilityConnection> EmergencyCallConnectCallback::connectCallback_ = nullptr;
337 sptr<AAFwk::IAbilityConnection> EmergencyCallConnectCallback::connectCallbackEcc = nullptr;
ConnectAbility(std::string value,sptr<AAFwk::IAbilityConnection> & callback,AAFwk::Want & want)338 void MyLocationEngine::ConnectAbility(std::string value, sptr<AAFwk::IAbilityConnection>& callback,
339 AAFwk::Want& want)
340 {
341 std::string abilityName = EMERGENCY_ABILITY_NAME;
342 want.SetParam(PARAMETERS_KEY, value);
343 if (callback == nullptr) {
344 callback = sptr<EmergencyCallConnectCallback>::MakeSptr();
345 }
346 if (value == PARAMETERS_VALUE_ECC) {
347 abilityName = EMERGENCY_ABILITY_NAME_ECC;
348 }
349 int32_t userId = -1;
350 AppExecFwk::ElementName element(EMERGENCY_DEVICE_ID, EMERGENCY_BUNDLE_NAME, abilityName);
351 want.SetElement(element);
352 auto ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want, callback, userId);
353 TELEPHONY_LOGI("connect emergencycall ability %{public}d", ret);
354 }
355
StartEccService(sptr<CallBase> call,const CallDetailInfo & info)356 void MyLocationEngine::StartEccService(sptr<CallBase> call, const CallDetailInfo &info)
357 {
358 std::lock_guard<std::mutex> lock(EmergencyCallConnectCallback::mutex_);
359 if (call == nullptr) {
360 TELEPHONY_LOGE("call is nullptr");
361 return;
362 }
363 if (EmergencyCallConnectCallback::isStartEccService) {
364 TELEPHONY_LOGE("ecc service already start");
365 return;
366 }
367 CallAttributeInfo attributeInfo;
368 call->GetCallAttributeInfo(attributeInfo);
369 if (!attributeInfo.isEcc) {
370 TELEPHONY_LOGE("ecc state is false");
371 return;
372 }
373 std::string value = "";
374 if (!IsSwitchOn("emergency_post_location_switch", value)) {
375 TELEPHONY_LOGE("ecc switch is close");
376 return;
377 }
378 AAFwk::Want want;
379 want.SetParam(PARAMETERS_KEY_SLOTID, std::to_string(info.accountId));
380 want.SetParam(PARAMETERS_KEY_PHONE_NUMBER, std::string(info.phoneNum));
381 ConnectAbility(PARAMETERS_VALUE_ECC, EmergencyCallConnectCallback::connectCallbackEcc, want);
382 EmergencyCallConnectCallback::nowCallId = call->GetCallID();
383 EmergencyCallConnectCallback::isStartEccService = true;
384 }
385
StopEccService(int32_t callId)386 void MyLocationEngine::StopEccService(int32_t callId)
387 {
388 std::lock_guard<std::mutex> lock(EmergencyCallConnectCallback::mutex_);
389 if (EmergencyCallConnectCallback::connectCallbackEcc == nullptr) {
390 TELEPHONY_LOGE("ecc callback is nullptr");
391 return;
392 }
393 if (EmergencyCallConnectCallback::nowCallId != callId) {
394 TELEPHONY_LOGE("disconnect callId is not equal now dial callId");
395 return;
396 }
397 AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(EmergencyCallConnectCallback::connectCallbackEcc);
398 EmergencyCallConnectCallback::connectCallbackEcc = nullptr;
399 EmergencyCallConnectCallback::nowCallId = -1;
400 EmergencyCallConnectCallback::isStartEccService = false;
401 }
402
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)403 void EmergencyCallConnectCallback::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
404 const sptr<IRemoteObject> &remoteObject, int resultCode)
405 {
406 TELEPHONY_LOGI("connect result code: %{public}d", resultCode);
407 }
408
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)409 void EmergencyCallConnectCallback::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
410 {
411 TELEPHONY_LOGI("disconnect result code: %{public}d", resultCode);
412 }
413 } // namespace Telephony
414 } // namespace OHOS