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 = OHOS::Location::Location::Unmarshalling(data);
181 OnLocationReport(location);
182 break;
183 }
184 case RECEIVE_ERROR_INFO_EVENT: {
185 int32_t errorCode = data.ReadInt32();
186 OnErrorReport(errorCode);
187 break;
188 }
189 case RECEIVE_LOCATION_STATUS_EVENT: {
190 int32_t status = data.ReadInt32();
191 OnLocatingStatusChange(status);
192 break;
193 }
194 default: {
195 break;
196 }
197 }
198 TELEPHONY_LOGI("locationreport code = %{public}d.", code);
199 return 0;
200 }
201
MyLocationCallBack()202 MyLocationEngine::MyLocationCallBack::MyLocationCallBack() {}
203
OnLocatingStatusChange(const int status)204 void MyLocationEngine::MyLocationCallBack::OnLocatingStatusChange(const int status)
205 {
206 TELEPHONY_LOGI("listen status = %{public}d", status);
207 }
208
OnErrorReport(const int errorCode)209 void MyLocationEngine::MyLocationCallBack::OnErrorReport(const int errorCode) {}
210
OnLocationReport(const std::unique_ptr<Location::Location> & location)211 void MyLocationEngine::MyLocationCallBack::OnLocationReport(const std::unique_ptr<Location::Location>& location)
212 {
213 TELEPHONY_LOGI("location report");
214 if (location == nullptr) {
215 TELEPHONY_LOGE("location is nullptr");
216 return;
217 }
218 AAFwk::Want want;
219 want.SetParam("latitude", std::to_string(location->GetLatitude()));
220 want.SetParam("longitude", std::to_string(location->GetLongitude()));
221 MyLocationEngine::ConnectAbility(MyLocationEngine::PARAMETERS_VALUE,
222 EmergencyCallConnectCallback::connectCallback_, want);
223 }
224
BootComplete(bool switchState)225 void MyLocationEngine::BootComplete(bool switchState)
226 {
227 if (!switchState) {
228 TELEPHONY_LOGE("the alarm switch is close");
229 return;
230 }
231 TELEPHONY_LOGI("the alarm switch is open");
232 MyLocationEngine::GetInstance()->SetValue();
233 MyLocationEngine::GetInstance()->RegisterLocationChange();
234 MyLocationEngine::GetInstance()->RegisterSwitchCallback();
235 }
236
MySwitchCallback(std::shared_ptr<MyLocationEngine> locationUpdate)237 MyLocationEngine::MySwitchCallback::MySwitchCallback(std::shared_ptr<MyLocationEngine> locationUpdate)
238 : locationUpdate_(locationUpdate)
239 {}
240
OnSwitchChange(const int state)241 void MyLocationEngine::MySwitchCallback::OnSwitchChange(const int state)
242 {
243 if (locationUpdate_ == nullptr) {
244 return;
245 }
246 locationUpdate_->LocationSwitchChange();
247 }
248
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)249 int MyLocationEngine::MySwitchCallback::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
250 MessageOption &option)
251 {
252 if (data.ReadInterfaceToken() != GetDescriptor()) {
253 TELEPHONY_LOGE("switchCallback invalid token.");
254 return -1;
255 }
256 switch (code) {
257 case RECEIVE_SWITCH_STATE_EVENT: {
258 int32_t status = data.ReadInt32();
259 OnSwitchChange(status);
260 break;
261 }
262 default: {
263 TELEPHONY_LOGI("receive error code:%{public}u", code);
264 break;
265 }
266 }
267 return 0;
268 }
269
IsSwitchOn(std::string key,std::string & value)270 bool MyLocationEngine::IsSwitchOn(std::string key, std::string& value)
271 {
272 auto datashareHelper = std::make_shared<DataShareSwitchState>();
273 OHOS::Uri uri(datashareHelper->DEFAULT_URI + key);
274 int resp = datashareHelper->QueryData(uri, key, value);
275 TELEPHONY_LOGI("query %{public}s is %{public}s", key.c_str(), value.c_str());
276 if (resp != DataShareSwitchState::TELEPHONY_SUCCESS || value == ALARM_SWITCH_OFF) {
277 return false;
278 }
279 return true;
280 }
281
282 std::map<std::string, sptr<AAFwk::IDataAbilityObserver>> MyLocationEngine::settingsCallbacks = {};
OOBEComplete()283 void MyLocationEngine::OOBEComplete()
284 {
285 std::string stateValue = INITIAL_FIRST_VALUE;
286 for (auto& oobeKey : OOBESwitchObserver::keyStatus) {
287 oobeKey.second = MyLocationEngine::IsSwitchOn(oobeKey.first, stateValue);
288 if (!oobeKey.second) {
289 settingsCallbacks[oobeKey.first] = sptr<OOBESwitchObserver>::MakeSptr(oobeKey.first);
290 auto datashareHelper = std::make_shared<DataShareSwitchState>();
291 datashareHelper->RegisterListenSettingsKey(oobeKey.first, true, settingsCallbacks[oobeKey.first]);
292 }
293 }
294 };
295
296 std::map<std::string, bool> OOBESwitchObserver::keyStatus = {
297 {"device_provisioned", false},
298 {"user_setup_complete", false},
299 {"is_ota_finished", false}
300 };
301
302 std::mutex OOBESwitchObserver::mutex_;
OnChange()303 void OOBESwitchObserver::OnChange()
304 {
305 std::lock_guard<std::mutex> lock(mutex_);
306 if (!keyStatus[mKey]) {
307 keyStatus[mKey] = MyLocationEngine::IsSwitchOn(mKey, mValue);
308 }
309 for (auto& oobeKey : keyStatus) {
310 if (!oobeKey.second) {
311 TELEPHONY_LOGE("%{public}s is trun off", oobeKey.first.c_str());
312 return;
313 }
314 }
315 mValue = MyLocationEngine::INITIAL_FIRST_VALUE;
316 if (MyLocationEngine::IsSwitchOn(LocationSubscriber::SWITCH_STATE_KEY, mValue)) {
317 TELEPHONY_LOGI("the alarm switch is open");
318 AAFwk::Want want;
319 MyLocationEngine::ConnectAbility(MyLocationEngine::PARAMETERS_VALUE_OOBE,
320 EmergencyCallConnectCallback::connectCallback_, want);
321 }
322 ffrt::submit([&]() {
323 for (auto& oobeKey : MyLocationEngine::settingsCallbacks) {
324 auto datashareHelper = std::make_shared<DataShareSwitchState>();
325 datashareHelper->RegisterListenSettingsKey(oobeKey.first, false, oobeKey.second);
326 oobeKey.second = nullptr;
327 }
328 TELEPHONY_LOGI("unregister listen finish");
329 });
330 }
331
332 std::mutex EmergencyCallConnectCallback::mutex_;
333 bool EmergencyCallConnectCallback::isStartEccService = false;
334 int32_t EmergencyCallConnectCallback::nowCallId = -1;
335 sptr<AAFwk::IAbilityConnection> EmergencyCallConnectCallback::connectCallback_ = nullptr;
336 sptr<AAFwk::IAbilityConnection> EmergencyCallConnectCallback::connectCallbackEcc = nullptr;
ConnectAbility(std::string value,sptr<AAFwk::IAbilityConnection> & callback,AAFwk::Want & want)337 void MyLocationEngine::ConnectAbility(std::string value, sptr<AAFwk::IAbilityConnection>& callback,
338 AAFwk::Want& want)
339 {
340 std::string abilityName = EMERGENCY_ABILITY_NAME;
341 want.SetParam(PARAMETERS_KEY, value);
342 if (callback == nullptr) {
343 callback = sptr<EmergencyCallConnectCallback>::MakeSptr();
344 }
345 if (value == PARAMETERS_VALUE_ECC) {
346 abilityName = EMERGENCY_ABILITY_NAME_ECC;
347 }
348 int32_t userId = -1;
349 AppExecFwk::ElementName element(EMERGENCY_DEVICE_ID, EMERGENCY_BUNDLE_NAME, abilityName);
350 want.SetElement(element);
351 auto ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want, callback, userId);
352 TELEPHONY_LOGI("connect emergencycall ability %{public}d", ret);
353 }
354
StartEccService(sptr<CallBase> call,const CallDetailInfo & info)355 void MyLocationEngine::StartEccService(sptr<CallBase> call, const CallDetailInfo &info)
356 {
357 std::lock_guard<std::mutex> lock(EmergencyCallConnectCallback::mutex_);
358 if (call == nullptr) {
359 TELEPHONY_LOGE("call is nullptr");
360 return;
361 }
362 if (EmergencyCallConnectCallback::isStartEccService) {
363 TELEPHONY_LOGE("ecc service already start");
364 return;
365 }
366 CallAttributeInfo attributeInfo;
367 call->GetCallAttributeInfo(attributeInfo);
368 if (!attributeInfo.isEcc) {
369 TELEPHONY_LOGE("ecc state is false");
370 return;
371 }
372 std::string value = "";
373 if (!IsSwitchOn("emergency_post_location_switch", value)) {
374 TELEPHONY_LOGE("ecc switch is close");
375 return;
376 }
377 AAFwk::Want want;
378 want.SetParam(PARAMETERS_KEY_SLOTID, std::to_string(info.accountId));
379 want.SetParam(PARAMETERS_KEY_PHONE_NUMBER, std::string(info.phoneNum));
380 ConnectAbility(PARAMETERS_VALUE_ECC, EmergencyCallConnectCallback::connectCallbackEcc, want);
381 EmergencyCallConnectCallback::nowCallId = call->GetCallID();
382 EmergencyCallConnectCallback::isStartEccService = true;
383 }
384
StopEccService(int32_t callId)385 void MyLocationEngine::StopEccService(int32_t callId)
386 {
387 std::lock_guard<std::mutex> lock(EmergencyCallConnectCallback::mutex_);
388 if (EmergencyCallConnectCallback::connectCallbackEcc == nullptr) {
389 TELEPHONY_LOGE("ecc callback is nullptr");
390 return;
391 }
392 if (EmergencyCallConnectCallback::nowCallId != callId) {
393 TELEPHONY_LOGE("disconnect callId is not equal now dial callId");
394 return;
395 }
396 AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(EmergencyCallConnectCallback::connectCallbackEcc);
397 EmergencyCallConnectCallback::connectCallbackEcc = nullptr;
398 EmergencyCallConnectCallback::nowCallId = -1;
399 EmergencyCallConnectCallback::isStartEccService = false;
400 }
401
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)402 void EmergencyCallConnectCallback::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
403 const sptr<IRemoteObject> &remoteObject, int resultCode)
404 {
405 TELEPHONY_LOGI("connect result code: %{public}d", resultCode);
406 }
407
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)408 void EmergencyCallConnectCallback::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
409 {
410 TELEPHONY_LOGI("disconnect result code: %{public}d", resultCode);
411 }
412 } // namespace Telephony
413 } // namespace OHOS