• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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