• 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         return false;
142     }
143     int32_t supportedFuncs = GetSupportedFunctions();
144     USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: supportedFuncs %{public}d", __func__, supportedFuncs);
145     if (supportedFuncs < 0) {
146         USB_HILOGE(MODULE_USB_SERVICE, "no supported functions: %{public}d", supportedFuncs);
147         return false;
148     }
149 
150     std::lock_guard<std::mutex> guard(opMutex_);
151     if (windowAction_ == UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_FORBID) {
152         USB_HILOGI(MODULE_USB_SERVICE, "forbid: pop up function switch window");
153         return false;
154     }
155     windowAction_ = UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_SHOW;
156 
157     isPromptEnabled = OHOS::system::GetBoolParameter("bootevent.boot.completed", false);
158     if (!isPromptEnabled) {
159         USB_HILOGE(MODULE_USB_SERVICE, "boot.completed is false!");
160         int ret = WatchParameter("bootevent.boot.completed", BootCompletedEventCallback, this);
161         if (ret != 0) {
162             USB_HILOGI(MODULE_USB_SERVICE, "watchParameter is failed!");
163         }
164         return false;
165     }
166     if (ShouldRejectShowWindow()) {
167         USB_HILOGE(MODULE_USB_SERVICE, "OOBE is not ready!");
168         return false;
169     }
170     return ShowFunctionSwitchWindow();
171 }
172 
DismissFunctionSwitchWindow()173 bool UsbFunctionSwitchWindow::DismissFunctionSwitchWindow()
174 {
175     USB_HILOGI(MODULE_USB_SERVICE, "dismiss function switch window");
176     std::lock_guard<std::mutex> guard(opMutex_);
177     if (windowAction_ == UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_FORBID) {
178         USB_HILOGI(MODULE_USB_SERVICE, "forbid: dismiss function switch window");
179         return false;
180     }
181     windowAction_ = UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_DISMISS;
182     return UnShowFunctionSwitchWindow();
183 }
184 
GetSupportedFunctions()185 int32_t UsbFunctionSwitchWindow::GetSupportedFunctions()
186 {
187     std::string supportedFuncStr = "";
188     (void)OHOS::system::GetStringParameter("const.usb_manager.supported_functions",
189         supportedFuncStr, DEFAULT_PARAM_VALUE);
190     USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: supportedFuncStr %{public}s", __func__, supportedFuncStr.c_str());
191 
192     if (supportedFuncStr.find("none") != std::string::npos) {
193         return SUPPORTED_FUNC_NONE;
194     }
195     uint32_t mtp = supportedFuncStr.find("mtp") != std::string::npos ? SUPPORTED_FUNC_MTP : 0;
196     uint32_t ptp = supportedFuncStr.find("ptp") != std::string::npos ? SUPPORTED_FUNC_PTP : 0;
197 
198     return static_cast<int32_t>(mtp | ptp);
199 }
200 
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int32_t resultCode)201 void UsbFunctionSwitchWindow::UsbFuncAbilityConn::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
202     const sptr<IRemoteObject> &remoteObject, int32_t resultCode)
203 {
204     USB_HILOGI(MODULE_USB_SERVICE, "OnAbilityConnectDone");
205     if (remoteObject == nullptr) {
206         USB_HILOGE(MODULE_USB_SERVICE, "remoteObject is nullptr");
207         return;
208     }
209 
210     MessageParcel data;
211     MessageParcel reply;
212     MessageOption option;
213     data.WriteInt32(MESSAGE_PARCEL_KEY_SIZE);
214     data.WriteString16(u"bundleName");
215     data.WriteString16(u"com.usb.right");
216     data.WriteString16(u"abilityName");
217     data.WriteString16(u"UsbFunctionSwitchExtAbility");
218     data.WriteString16(u"parameters");
219     cJSON* paramJson = cJSON_CreateObject();
220     int32_t supportedFuncs = GetSupportedFunctions();
221     USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: supportedFuncs %{public}d", __func__, supportedFuncs);
222     cJSON_AddStringToObject(paramJson, "supportedFuncs", std::to_string(supportedFuncs).c_str());
223     std::string uiExtensionTypeStr = "sysDialog/common";
224     cJSON_AddStringToObject(paramJson, "ability.want.params.uiExtensionType", uiExtensionTypeStr.c_str());
225     char *pParamJson = cJSON_PrintUnformatted(paramJson);
226     cJSON_Delete(paramJson);
227     paramJson = nullptr;
228     if (!pParamJson) {
229         USB_HILOGE(MODULE_USB_SERVICE, "Print paramJson error");
230         return;
231     }
232     std::string paramStr(pParamJson);
233     data.WriteString16(Str8ToStr16(paramStr));
234     cJSON_free(pParamJson);
235     pParamJson = NULL;
236 
237     const uint32_t cmdCode = 1;
238     int32_t ret = remoteObject->SendRequest(cmdCode, data, reply, option);
239     if (ret != ERR_OK) {
240         USB_HILOGE(MODULE_USB_SERVICE, "send request failed: %{public}d", ret);
241         return;
242     }
243     if (!reply.ReadInt32(ret) || ret != ERR_OK) {
244         USB_HILOGE(MODULE_USB_SERVICE, "show dialog failed: %{public}d", ret);
245         return;
246     }
247     remoteObject_ = remoteObject;
248     return;
249 }
250 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)251 void UsbFunctionSwitchWindow::UsbFuncAbilityConn::OnAbilityDisconnectDone(
252     const AppExecFwk::ElementName& element, int resultCode)
253 {
254     USB_HILOGI(MODULE_USB_SERVICE, "OnAbilityDisconnectDone");
255     remoteObject_ = nullptr;
256     return;
257 }
258 
CloseDialog()259 void UsbFunctionSwitchWindow::UsbFuncAbilityConn::CloseDialog()
260 {
261     if (remoteObject_ == nullptr) {
262         USB_HILOGW(MODULE_USB_SERVICE, "CloseDialog: disconnected");
263         return;
264     }
265 
266     MessageParcel data;
267     MessageParcel reply;
268     MessageOption option;
269     const uint32_t cmdCode = 3;
270     int32_t ret = remoteObject_->SendRequest(cmdCode, data, reply, option);
271     int32_t replyCode = -1;
272     bool success = false;
273     if (ret == ERR_OK) {
274         success = reply.ReadInt32(replyCode);
275     }
276     USB_HILOGI(MODULE_USB_SERVICE, "CloseDialog: ret=%{public}d, %{public}d, %{public}d", ret, success, replyCode);
277 }
278 
ShowFunctionSwitchWindow()279 bool UsbFunctionSwitchWindow::ShowFunctionSwitchWindow()
280 {
281     USB_HILOGI(MODULE_USB_SERVICE, "show function switch window right now, installed: %{public}d", isDialogInstalled_);
282     if (!isDialogInstalled_) {
283         return false;
284     }
285 
286     if (usbFuncAbilityConn == nullptr) {
287         usbFuncAbilityConn = sptr<UsbFuncAbilityConn>(new (std::nothrow) UsbFuncAbilityConn());
288     }
289 
290     auto abilityManager = AAFwk::AbilityManagerClient::GetInstance();
291     if (abilityManager == nullptr) {
292         USB_HILOGE(MODULE_USB_SERVICE, "AbilityManagerClient is nullptr");
293         return false;
294     }
295 
296     AAFwk::Want want;
297     want.SetElementName("com.ohos.sceneboard", "com.ohos.sceneboard.systemdialog");
298     auto ret = abilityManager->ConnectAbility(want, usbFuncAbilityConn, INVALID_USERID);
299     if (ret != ERR_OK) {
300         want.SetElementName("com.ohos.systemui", "com.ohos.systemui.dialog");
301         ret = abilityManager->ConnectAbility(want, usbFuncAbilityConn, INVALID_USERID);
302         if (ret != ERR_OK) {
303             USB_HILOGE(MODULE_USB_SERVICE, "ConnectServiceExtensionAbility systemui failed, ret: %{public}d", ret);
304             usbFuncAbilityConn = nullptr;
305             return false;
306         }
307     }
308     USB_HILOGI(MODULE_SERVICE, "StartAbility success, ret: %{public}d", ret);
309     return true;
310 }
311 
UnShowFunctionSwitchWindow()312 bool UsbFunctionSwitchWindow::UnShowFunctionSwitchWindow()
313 {
314     if (usbFuncAbilityConn == nullptr) {
315         return true;
316     }
317 
318     auto abmc = AAFwk::AbilityManagerClient::GetInstance();
319     if (abmc == nullptr) {
320         USB_HILOGE(MODULE_USB_SERVICE, "GetInstance failed");
321         return false;
322     }
323     USB_HILOGI(MODULE_USB_SERVICE, "unshow function switch window");
324     usbFuncAbilityConn->CloseDialog();
325 
326     auto ret = abmc->DisconnectAbility(usbFuncAbilityConn);
327     if (ret != UEC_OK) {
328         USB_HILOGE(MODULE_SERVICE, "DisconnectAbility failed %{public}d", ret);
329         return false;
330     }
331     USB_HILOGD(MODULE_USB_SERVICE, "unshow function switch window success");
332     return true;
333 }
334 
CheckDialogInstallStatus()335 bool UsbFunctionSwitchWindow::CheckDialogInstallStatus()
336 {
337     AppExecFwk::BundleInfo info;
338     AppExecFwk::BundleMgrClient bmc;
339     int32_t retryTimes = 0;
340     while (retryTimes < MAX_RETRY_TIMES) {
341         isDialogInstalled_ = bmc.GetBundleInfo(functionSwitchBundleName_,
342             AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, info, AppExecFwk::Constants::ALL_USERID);
343         USB_HILOGI(MODULE_USB_SERVICE, "check dialog, times=%{public}d,res=%{public}d", retryTimes, isDialogInstalled_);
344         if (!isDialogInstalled_) {
345             retryTimes++;
346             sleep(RETRY_INTERVAL_SECONDS);
347             continue;
348         }
349 
350         if (windowAction_ == UsbFunctionSwitchWindowAction::FUNCTION_SWITCH_WINDOW_ACTION_SHOW) {
351             if (OHOS::system::GetBoolParameter("bootevent.boot.completed", false)) {
352                 ShowFunctionSwitchWindow();
353             }
354         }
355         return true;
356     }
357     USB_HILOGE(MODULE_USB_SERVICE, "dialog is not installed");
358     return false;
359 }
360 
BootCompletedEventCallback(const char * key,const char * value,void * context)361 void UsbFunctionSwitchWindow::BootCompletedEventCallback(const char *key, const char *value, void *context)
362 {
363     USB_HILOGI(MODULE_USB_SERVICE, "testParameterChange key: %{public}s, value: %{public}s!", key, value);
364     if (!OHOS::system::GetBoolParameter("bootevent.boot.completed", false)) {
365         USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: boot.completed is false!", __func__);
366         return;
367     }
368     if (context == nullptr) {
369         USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: context is null!", __func__);
370         return;
371     }
372     auto eventSwitchWindow = reinterpret_cast<UsbFunctionSwitchWindow*>(context);
373     if (eventSwitchWindow == nullptr) {
374         USB_HILOGE(MODULE_USB_SERVICE, "get eventSwitchWindow is null!");
375         return;
376     }
377 
378     if (eventSwitchWindow->ShouldRejectShowWindow()) {
379         USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: OOBE is not ready!", __func__);
380         return;
381     }
382     bool ret = eventSwitchWindow->ShowFunctionSwitchWindow();
383     if (!ret) {
384         USB_HILOGE(MODULE_USB_SERVICE, "watchParameter to ShowFunctionSwitchWindow is failed!");
385     }
386 }
387 
ShouldRejectShowWindow()388 bool UsbFunctionSwitchWindow::ShouldRejectShowWindow()
389 {
390     auto datashareHelper = std::make_shared<UsbSettingDataShare>();
391     std::string device_provisioned {"0"};
392     OHOS::Uri uri(
393         "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true&key=device_provisioned");
394     bool resp = datashareHelper->Query(uri, "device_provisioned", device_provisioned);
395     if (resp && device_provisioned != "1") {
396         USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: device_provisioned is = 0", __func__);
397         return true;
398     }
399 
400     std::string user_setup_complete {"0"};
401     std::vector<int> activedOsAccountIds;
402     OHOS::AccountSA::OsAccountManager::QueryActiveOsAccountIds(activedOsAccountIds);
403     if (activedOsAccountIds.empty()) {
404         USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: activedOsAccountIds is empty", __func__);
405         return true;
406     }
407     int userId = activedOsAccountIds[0];
408     OHOS::Uri uri_setup(
409         "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_"
410         + std::to_string(userId) + "?Proxy=true&key=user_setup_complete");
411     bool resp_userSetup = datashareHelper->Query(uri_setup, "user_setup_complete", user_setup_complete);
412     if (resp_userSetup && user_setup_complete != "1") {
413         USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: user_setup_complete is = 0", __func__);
414         return true;
415     }
416 
417     std::string is_ota_finished {"0"};
418     OHOS::Uri uri_ota(
419         "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_"
420         + std::to_string(userId) + "?Proxy=true&key=is_ota_finished");
421     bool resp_ota = datashareHelper->Query(uri_ota, "is_ota_finished", is_ota_finished);
422     if (resp_ota && is_ota_finished == "0") {
423         USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: is_ota_finished is = 0", __func__);
424         return true;
425     }
426     return false;
427 }
428 } // namespace USB
429 } // namespace OHOS
430