1 /*
2 * Copyright (c) 2023 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 "usb_function_switch_window.h"
17
18 #include <parameters.h>
19 #include <param_wrapper.h>
20 #include <semaphore.h>
21 #include <sys/types.h>
22 #include <thread>
23 #include <unistd.h>
24
25 #include "cJSON.h"
26
27 #include "ability_manager_client.h"
28 #include "bundle_mgr_client.h"
29 #include "common_event_manager.h"
30 #include "common_event_support.h"
31 #include "usb_settings_datashare.h"
32 #include "os_account_manager.h"
33 #include "usb_errors.h"
34 #include "uri.h"
35
36 #define DEFAULT_PARAM_VALUE "charge,mtp,ptp"
37 using namespace OHOS::AppExecFwk;
38 using namespace OHOS::EventFwk;
39
40 namespace OHOS {
41 namespace USB {
42 constexpr int32_t INVALID_USERID = -1;
43 constexpr int32_t MESSAGE_PARCEL_KEY_SIZE = 3;
44 constexpr int32_t MAX_RETRY_TIMES = 30;
45 constexpr int32_t RETRY_INTERVAL_SECONDS = 1;
46 constexpr uint32_t DELAY_CHECK_DIALOG = 1;
47
48 class FuncSwitchSubscriber : public CommonEventSubscriber {
49 public:
FuncSwitchSubscriber(const CommonEventSubscribeInfo & sp)50 explicit FuncSwitchSubscriber(const CommonEventSubscribeInfo &sp) : CommonEventSubscriber(sp) {}
51
OnReceiveEvent(const CommonEventData & data)52 void OnReceiveEvent(const CommonEventData &data) override
53 {
54 auto &want = data.GetWant();
55 std::string wantAction = want.GetAction();
56 if (wantAction == CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED) {
57 UsbFunctionSwitchWindow::GetInstance()->CheckDialogInstallStatus();
58 }
59 }
60 };
61
62 std::shared_ptr<UsbFunctionSwitchWindow> UsbFunctionSwitchWindow::instance_;
63 std::mutex UsbFunctionSwitchWindow::insMutex_;
64
GetInstance()65 std::shared_ptr<UsbFunctionSwitchWindow> UsbFunctionSwitchWindow::GetInstance()
66 {
67 std::lock_guard<std::mutex> guard(insMutex_);
68 if (instance_ == nullptr) {
69 USB_HILOGI(MODULE_USB_SERVICE, "reset to new instance");
70 instance_.reset(new UsbFunctionSwitchWindow());
71 }
72 return instance_;
73 }
74
UsbFunctionSwitchWindow()75 UsbFunctionSwitchWindow::UsbFunctionSwitchWindow() {}
76
~UsbFunctionSwitchWindow()77 UsbFunctionSwitchWindow::~UsbFunctionSwitchWindow()
78 {
79 if (windowAction_ == UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_SHOW) {
80 (void)UnShowFunctionSwitchWindow();
81 }
82 }
83
SubscribeCommonEvent()84 void UsbFunctionSwitchWindow::SubscribeCommonEvent()
85 {
86 USB_HILOGI(MODULE_USB_SERVICE, "subscriber bms scan finished.");
87 MatchingSkills matchingSkills;
88 matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED);
89 CommonEventSubscribeInfo subscriberInfo(matchingSkills);
90 std::shared_ptr<FuncSwitchSubscriber> subscriber = std::make_shared<FuncSwitchSubscriber>(subscriberInfo);
91 bool ret = CommonEventManager::SubscribeCommonEvent(subscriber);
92 if (!ret) {
93 USB_HILOGW(MODULE_USB_SERVICE, "subscriber event failed.");
94 }
95 }
96
Init()97 int32_t UsbFunctionSwitchWindow::Init()
98 {
99 USB_HILOGI(MODULE_USB_SERVICE, "init: window action=%{public}d,%{public}d", windowAction_, isDialogInstalled_);
100 if (isDialogInstalled_) {
101 return UEC_OK;
102 }
103
104 checkDialogTimer_.Unregister(checkDialogTimerId_);
105 checkDialogTimer_.Shutdown();
106 // async check dialog install status
107 auto task = [this]() {
108 bool checkRet = CheckDialogInstallStatus();
109 if (!checkRet) {
110 SubscribeCommonEvent();
111 }
112 checkDialogTimer_.Unregister(checkDialogTimerId_);
113 checkDialogTimer_.Shutdown(false);
114 USB_HILOGI(MODULE_USB_SERVICE, "dialog check end");
115 };
116 auto ret = checkDialogTimer_.Setup();
117 if (ret != UEC_OK) {
118 USB_HILOGE(MODULE_USB_SERVICE, "set up timer failed %{public}u", ret);
119 // fall back to sync
120 bool checkRet = CheckDialogInstallStatus();
121 if (!checkRet) {
122 SubscribeCommonEvent();
123 }
124 return isDialogInstalled_ ? UEC_OK : ret;
125 }
126 checkDialogTimerId_ = checkDialogTimer_.Register(task, DELAY_CHECK_DIALOG, true);
127 return UEC_OK;
128 }
129
PopUpFunctionSwitchWindow()130 bool UsbFunctionSwitchWindow::PopUpFunctionSwitchWindow()
131 {
132 USB_HILOGI(MODULE_USB_SERVICE, "pop up function switch window");
133 bool isPromptEnabled = OHOS::system::GetBoolParameter("persist.usb.setting.gadget_conn_prompt", true);
134 if (!isPromptEnabled) {
135 USB_HILOGE(MODULE_USB_SERVICE, "gadget_conn_prompt is false");
136 return false;
137 }
138 bool isTempDisablePrompt = OHOS::system::GetBoolParameter("usb.setting.gadget_conn_prompt", true);
139 if (!isTempDisablePrompt) {
140 USB_HILOGE(MODULE_USB_SERVICE, "temporarily close the pop up window");
141 if (!OHOS::system::SetParameter("usb.setting.gadget_conn_prompt", "true")) {
142 USB_HILOGE(MODULE_USB_SERVICE, "set parameter failed");
143 }
144 return false;
145 }
146 int32_t supportedFuncs = GetSupportedFunctions();
147 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: supportedFuncs %{public}d", __func__, supportedFuncs);
148 if (supportedFuncs < 0) {
149 USB_HILOGE(MODULE_USB_SERVICE, "no supported functions: %{public}d", supportedFuncs);
150 return false;
151 }
152
153 std::lock_guard<std::mutex> guard(opMutex_);
154 if (windowAction_ == UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_FORBID) {
155 USB_HILOGI(MODULE_USB_SERVICE, "forbid: pop up function switch window");
156 return false;
157 }
158 windowAction_ = UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_SHOW;
159
160 isPromptEnabled = OHOS::system::GetBoolParameter("bootevent.boot.completed", false);
161 if (!isPromptEnabled) {
162 USB_HILOGE(MODULE_USB_SERVICE, "boot.completed is false!");
163 int ret = WatchParameter("bootevent.boot.completed", BootCompletedEventCallback, this);
164 if (ret != 0) {
165 USB_HILOGI(MODULE_USB_SERVICE, "watchParameter is failed!");
166 }
167 return false;
168 }
169 if (ShouldRejectShowWindow()) {
170 USB_HILOGE(MODULE_USB_SERVICE, "OOBE is not ready!");
171 }
172 return ShowFunctionSwitchWindow();
173 }
174
DismissFunctionSwitchWindow()175 bool UsbFunctionSwitchWindow::DismissFunctionSwitchWindow()
176 {
177 USB_HILOGI(MODULE_USB_SERVICE, "dismiss function switch window");
178 std::lock_guard<std::mutex> guard(opMutex_);
179 if (windowAction_ == UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_FORBID) {
180 USB_HILOGI(MODULE_USB_SERVICE, "forbid: dismiss function switch window");
181 return false;
182 }
183 windowAction_ = UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_DISMISS;
184 return UnShowFunctionSwitchWindow();
185 }
186
GetSupportedFunctions()187 int32_t UsbFunctionSwitchWindow::GetSupportedFunctions()
188 {
189 std::string supportedFuncStr = "";
190 (void)OHOS::system::GetStringParameter("const.usb_manager.supported_functions",
191 supportedFuncStr, DEFAULT_PARAM_VALUE);
192 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: supportedFuncStr %{public}s", __func__, supportedFuncStr.c_str());
193
194 if (supportedFuncStr.find("none") != std::string::npos) {
195 return SUPPORTED_FUNC_NONE;
196 }
197 uint32_t mtp = supportedFuncStr.find("mtp") != std::string::npos ? SUPPORTED_FUNC_MTP : 0;
198 uint32_t ptp = supportedFuncStr.find("ptp") != std::string::npos ? SUPPORTED_FUNC_PTP : 0;
199
200 return static_cast<int32_t>(mtp | ptp);
201 }
202
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int32_t resultCode)203 void UsbFunctionSwitchWindow::UsbFuncAbilityConn::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
204 const sptr<IRemoteObject> &remoteObject, int32_t resultCode)
205 {
206 USB_HILOGI(MODULE_USB_SERVICE, "OnAbilityConnectDone");
207 if (remoteObject == nullptr) {
208 USB_HILOGE(MODULE_USB_SERVICE, "remoteObject is nullptr");
209 return;
210 }
211
212 MessageParcel data;
213 MessageParcel reply;
214 MessageOption option;
215 data.WriteInt32(MESSAGE_PARCEL_KEY_SIZE);
216 data.WriteString16(u"bundleName");
217 data.WriteString16(u"com.usb.right");
218 data.WriteString16(u"abilityName");
219 data.WriteString16(u"UsbFunctionSwitchExtAbility");
220 data.WriteString16(u"parameters");
221 cJSON* paramJson = cJSON_CreateObject();
222 int32_t supportedFuncs = GetSupportedFunctions();
223 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: supportedFuncs %{public}d", __func__, supportedFuncs);
224 cJSON_AddStringToObject(paramJson, "supportedFuncs", std::to_string(supportedFuncs).c_str());
225 std::string uiExtensionTypeStr = "sysDialog/common";
226 cJSON_AddStringToObject(paramJson, "ability.want.params.uiExtensionType", uiExtensionTypeStr.c_str());
227 char *pParamJson = cJSON_PrintUnformatted(paramJson);
228 cJSON_Delete(paramJson);
229 paramJson = nullptr;
230 if (!pParamJson) {
231 USB_HILOGE(MODULE_USB_SERVICE, "Print paramJson error");
232 return;
233 }
234 std::string paramStr(pParamJson);
235 data.WriteString16(Str8ToStr16(paramStr));
236 cJSON_free(pParamJson);
237 pParamJson = NULL;
238
239 const uint32_t cmdCode = 1;
240 int32_t ret = remoteObject->SendRequest(cmdCode, data, reply, option);
241 if (ret != ERR_OK) {
242 USB_HILOGE(MODULE_USB_SERVICE, "send request failed: %{public}d", ret);
243 return;
244 }
245 if (!reply.ReadInt32(ret) || ret != ERR_OK) {
246 USB_HILOGE(MODULE_USB_SERVICE, "show dialog failed: %{public}d", ret);
247 return;
248 }
249 std::lock_guard<std::mutex> guard(remoteMutex_);
250 remoteObject_ = remoteObject;
251 return;
252 }
253
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)254 void UsbFunctionSwitchWindow::UsbFuncAbilityConn::OnAbilityDisconnectDone(
255 const AppExecFwk::ElementName& element, int resultCode)
256 {
257 USB_HILOGI(MODULE_USB_SERVICE, "OnAbilityDisconnectDone");
258 std::lock_guard<std::mutex> guard(remoteMutex_);
259 remoteObject_ = nullptr;
260 USB_HILOGI(MODULE_USB_SERVICE, "UsbFuncAbilityConn remoteObject_ freed");
261 return;
262 }
263
CloseDialog()264 void UsbFunctionSwitchWindow::UsbFuncAbilityConn::CloseDialog()
265 {
266 USB_HILOGI(MODULE_USB_SERVICE, "UsbFuncAbilityConn CloseDialog enter");
267 std::lock_guard<std::mutex> guard(remoteMutex_);
268 if (remoteObject_ == nullptr) {
269 USB_HILOGW(MODULE_USB_SERVICE, "CloseDialog: disconnected");
270 return;
271 }
272
273 MessageParcel data;
274 MessageParcel reply;
275 MessageOption option;
276 const uint32_t cmdCode = 3;
277 int32_t ret = remoteObject_->SendRequest(cmdCode, data, reply, option);
278 int32_t replyCode = -1;
279 bool success = false;
280 if (ret == ERR_OK) {
281 success = reply.ReadInt32(replyCode);
282 }
283 USB_HILOGI(MODULE_USB_SERVICE, "CloseDialog: ret=%{public}d, %{public}d, %{public}d", ret, success, replyCode);
284 }
285
ShowFunctionSwitchWindow()286 bool UsbFunctionSwitchWindow::ShowFunctionSwitchWindow()
287 {
288 USB_HILOGI(MODULE_USB_SERVICE, "show function switch window right now, installed: %{public}d", isDialogInstalled_);
289 if (!isDialogInstalled_) {
290 return false;
291 }
292
293 if (usbFuncAbilityConn == nullptr) {
294 usbFuncAbilityConn = sptr<UsbFuncAbilityConn>(new (std::nothrow) UsbFuncAbilityConn());
295 }
296
297 auto abilityManager = AAFwk::AbilityManagerClient::GetInstance();
298 if (abilityManager == nullptr) {
299 USB_HILOGE(MODULE_USB_SERVICE, "AbilityManagerClient is nullptr");
300 return false;
301 }
302
303 AAFwk::Want want;
304 want.SetElementName("com.ohos.sceneboard", "com.ohos.sceneboard.systemdialog");
305 auto ret = abilityManager->ConnectAbility(want, usbFuncAbilityConn, INVALID_USERID);
306 if (ret != ERR_OK) {
307 want.SetElementName("com.ohos.systemui", "com.ohos.systemui.dialog");
308 ret = abilityManager->ConnectAbility(want, usbFuncAbilityConn, INVALID_USERID);
309 if (ret != ERR_OK) {
310 USB_HILOGE(MODULE_USB_SERVICE, "ConnectServiceExtensionAbility systemui failed, ret: %{public}d", ret);
311 usbFuncAbilityConn = nullptr;
312 return false;
313 }
314 }
315 USB_HILOGI(MODULE_SERVICE, "StartAbility success, ret: %{public}d", ret);
316 return true;
317 }
318
UnShowFunctionSwitchWindow()319 bool UsbFunctionSwitchWindow::UnShowFunctionSwitchWindow()
320 {
321 if (usbFuncAbilityConn == nullptr) {
322 return true;
323 }
324
325 auto abmc = AAFwk::AbilityManagerClient::GetInstance();
326 if (abmc == nullptr) {
327 USB_HILOGE(MODULE_USB_SERVICE, "GetInstance failed");
328 return false;
329 }
330 USB_HILOGI(MODULE_USB_SERVICE, "unshow function switch window");
331 usbFuncAbilityConn->CloseDialog();
332
333 auto ret = abmc->DisconnectAbility(usbFuncAbilityConn);
334 if (ret != UEC_OK) {
335 USB_HILOGE(MODULE_SERVICE, "DisconnectAbility failed %{public}d", ret);
336 return false;
337 }
338 USB_HILOGD(MODULE_USB_SERVICE, "unshow function switch window success");
339 return true;
340 }
341
CheckDialogInstallStatus()342 bool UsbFunctionSwitchWindow::CheckDialogInstallStatus()
343 {
344 AppExecFwk::BundleInfo info;
345 AppExecFwk::BundleMgrClient bmc;
346 int32_t retryTimes = 0;
347 while (retryTimes < MAX_RETRY_TIMES) {
348 isDialogInstalled_ = bmc.GetBundleInfo(functionSwitchBundleName_,
349 AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, info, AppExecFwk::Constants::ALL_USERID);
350 USB_HILOGI(MODULE_USB_SERVICE, "check dialog, times=%{public}d,res=%{public}d", retryTimes, isDialogInstalled_);
351 if (!isDialogInstalled_) {
352 retryTimes++;
353 sleep(RETRY_INTERVAL_SECONDS);
354 continue;
355 }
356
357 if (windowAction_ == UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_SHOW) {
358 if (OHOS::system::GetBoolParameter("bootevent.boot.completed", false)) {
359 ShowFunctionSwitchWindow();
360 }
361 }
362 return true;
363 }
364 USB_HILOGE(MODULE_USB_SERVICE, "dialog is not installed");
365 return false;
366 }
367
BootCompletedEventCallback(const char * key,const char * value,void * context)368 void UsbFunctionSwitchWindow::BootCompletedEventCallback(const char *key, const char *value, void *context)
369 {
370 USB_HILOGI(MODULE_USB_SERVICE, "testParameterChange key: %{public}s, value: %{public}s!", key, value);
371 if (!OHOS::system::GetBoolParameter("bootevent.boot.completed", false)) {
372 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: boot.completed is false!", __func__);
373 return;
374 }
375 if (context == nullptr) {
376 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: context is null!", __func__);
377 return;
378 }
379 auto eventSwitchWindow = reinterpret_cast<UsbFunctionSwitchWindow*>(context);
380 if (eventSwitchWindow == nullptr) {
381 USB_HILOGE(MODULE_USB_SERVICE, "get eventSwitchWindow is null!");
382 return;
383 }
384
385 if (eventSwitchWindow->ShouldRejectShowWindow()) {
386 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: OOBE is not ready!", __func__);
387 }
388 bool ret = eventSwitchWindow->ShowFunctionSwitchWindow();
389 if (!ret) {
390 USB_HILOGE(MODULE_USB_SERVICE, "watchParameter to ShowFunctionSwitchWindow is failed!");
391 }
392 }
393
ShouldRejectShowWindow()394 bool UsbFunctionSwitchWindow::ShouldRejectShowWindow()
395 {
396 auto datashareHelper = std::make_shared<UsbSettingDataShare>();
397 std::string device_provisioned {"0"};
398 OHOS::Uri uri(
399 "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true&key=device_provisioned");
400 bool resp = datashareHelper->Query(uri, "device_provisioned", device_provisioned);
401 if (resp && device_provisioned != "1") {
402 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: device_provisioned is = 0", __func__);
403 return true;
404 }
405
406 std::string user_setup_complete {"0"};
407 std::vector<int> activedOsAccountIds;
408 OHOS::AccountSA::OsAccountManager::QueryActiveOsAccountIds(activedOsAccountIds);
409 if (activedOsAccountIds.empty()) {
410 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: activedOsAccountIds is empty", __func__);
411 return true;
412 }
413 int userId = activedOsAccountIds[0];
414 OHOS::Uri uri_setup(
415 "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_"
416 + std::to_string(userId) + "?Proxy=true&key=user_setup_complete");
417 bool resp_userSetup = datashareHelper->Query(uri_setup, "user_setup_complete", user_setup_complete);
418 if (resp_userSetup && user_setup_complete != "1") {
419 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: user_setup_complete is = 0", __func__);
420 return true;
421 }
422
423 std::string is_ota_finished {"0"};
424 OHOS::Uri uri_ota(
425 "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_"
426 + std::to_string(userId) + "?Proxy=true&key=is_ota_finished");
427 bool resp_ota = datashareHelper->Query(uri_ota, "is_ota_finished", is_ota_finished);
428 if (resp_ota && is_ota_finished == "0") {
429 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: is_ota_finished is = 0", __func__);
430 return true;
431 }
432 return false;
433 }
434 } // namespace USB
435 } // namespace OHOS
436