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