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