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_mass_storage_notification.h"
17 #include <parameters.h>
18 #include "hilog_wrapper.h"
19 #include "want_agent_info.h"
20 #include "want_agent_helper.h"
21 #include "notification_normal_content.h"
22 #include "notification_helper.h"
23 #include "notification_content.h"
24 #include "notification_request.h"
25 #include "resource_manager.h"
26 #include "locale_config.h"
27 #include "locale_info.h"
28 #include "string_wrapper.h"
29 #include "iservice_registry.h"
30 #include "bundle_mgr_interface.h"
31 #include "system_ability_definition.h"
32 #include "os_account_manager.h"
33 #include "usb_errors.h"
34 
35 using namespace OHOS::AAFwk;
36 
37 namespace OHOS {
38 namespace USB {
39 namespace {
40     constexpr int16_t USB_DEVICE_CLASS_MASS_STORAGE = 8;
41     constexpr int16_t MASS_STORAGE_NOTIFICATION_ID = 100;
42     constexpr int32_t REQUEST_CODE = 10;
43     constexpr int32_t GET_APP_INFO_FLAG = 0;
44     const std::string FILEMANAGER_BUNDLE_NAME_KEY = "hmos.filemanager";
45     const std::string FILES_BUNDLE_NAME_KEY = "hmos.files";
46     const std::string FILES_ABILITY_NAME = "EntryAbility";
47     const std::string HAP_PATH = "/system/app/usb_right_dialog/usb_right_dialog.hap";
48 } // namespace
49 
50 std::shared_ptr<UsbMassStorageNotification> UsbMassStorageNotification::instance_ = nullptr;
51 
GetInstance()52 std::shared_ptr<UsbMassStorageNotification> UsbMassStorageNotification::GetInstance()
53 {
54     if (instance_ == nullptr) {
55         USB_HILOGI(MODULE_USB_SERVICE, "reset to new instance");
56         instance_.reset(new UsbMassStorageNotification());
57     }
58     return instance_;
59 }
60 
UsbMassStorageNotification()61 UsbMassStorageNotification::UsbMassStorageNotification()
62 {
63     GetHapString();
64 }
65 
~UsbMassStorageNotification()66 UsbMassStorageNotification::~UsbMassStorageNotification() {}
67 
GetHapString()68 void UsbMassStorageNotification::GetHapString()
69 {
70     std::shared_ptr<Global::Resource::ResourceManager> resourceManager(Global::Resource::CreateResourceManager());
71     if (resourceManager == nullptr) {
72         USB_HILOGE(MODULE_USB_SERVICE, "resourceManager is null");
73         return;
74     }
75     std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
76     if (resConfig == nullptr) {
77         USB_HILOGE(MODULE_USB_SERVICE, "resConfig is null");
78         return;
79     }
80     std::map<std::string, std::string> configs;
81     OHOS::Global::I18n::LocaleInfo locale(Global::I18n::LocaleConfig::GetSystemLocale(), configs);
82     resConfig->SetLocaleInfo(locale.GetLanguage().c_str(), locale.GetScript().c_str(), locale.GetRegion().c_str());
83     resourceManager->UpdateResConfig(*resConfig);
84     if (!resourceManager->AddResource(HAP_PATH.c_str())) {
85         USB_HILOGE(MODULE_USB_SERVICE, "AddResource failed");
86         return;
87     }
88     for (auto it : notificationMap) {
89         std::string outValue;
90         resourceManager->GetStringByName(it.first.c_str(), outValue);
91         notificationMap[it.first] = outValue;
92     }
93     return;
94 }
95 
GetFilemanagerBundleName()96 void UsbMassStorageNotification::GetFilemanagerBundleName()
97 {
98     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
99     if (sam == nullptr) {
100         USB_HILOGW(MODULE_USB_SERVICE, "GetSystemAbilityManager return nullptr");
101         return;
102     }
103     auto bundleMgrSa = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
104     if (bundleMgrSa == nullptr) {
105         USB_HILOGW(MODULE_USB_SERVICE, "GetSystemAbility return nullptr");
106         return;
107     }
108     auto bundleMgr = iface_cast<OHOS::AppExecFwk::IBundleMgr>(bundleMgrSa);
109     if (bundleMgr == nullptr) {
110         USB_HILOGW(MODULE_USB_SERVICE, "iface_cast return nullptr");
111         return;
112     }
113 
114     std::vector<int> activatedOsAccountIds;
115     int32_t res = OHOS::AccountSA::OsAccountManager::QueryActiveOsAccountIds(activatedOsAccountIds);
116     if ((res != UEC_OK) || (activatedOsAccountIds.size() <= 0)) {
117         USB_HILOGW(MODULE_USB_SERVICE, "QueryActiveOsAccountIds fail. : %{public}d", res);
118     } else {
119         osAccountId = activatedOsAccountIds[0];
120     }
121 
122     std::vector<OHOS::AppExecFwk::ApplicationInfo> appInfos {};
123     if (!bundleMgr->GetApplicationInfos(OHOS::AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO,
124         osAccountId, appInfos)) {
125         USB_HILOGW(MODULE_USB_SERVICE, "BundleMgr GetApplicationInfos failed");
126         return;
127     }
128     OHOS::AppExecFwk::ApplicationInfo appInfoTemp;
129     for (auto const &appInfo : appInfos) {
130         size_t start_pos = appInfo.bundleName.find(FILEMANAGER_BUNDLE_NAME_KEY);
131         if (start_pos != std::string::npos) {
132             filemanagerBundleName = appInfo.bundleName;
133             std::string bundleNameTemp = appInfo.bundleName;
134             int32_t resultCode = bundleMgr->GetApplicationInfoV9(bundleNameTemp.replace(
135                 start_pos, FILEMANAGER_BUNDLE_NAME_KEY.length(), FILES_BUNDLE_NAME_KEY),
136                 GET_APP_INFO_FLAG, osAccountId, appInfoTemp);
137             USB_HILOGD(MODULE_USB_SERVICE, "GetApplicationInfoV9 resultCode %{public}d", resultCode);
138             if (resultCode == ERR_OK) {
139                 filemanagerBundleName = appInfoTemp.bundleName;
140                 filemanagerAbilityName = FILES_ABILITY_NAME;
141             }
142             return;
143         }
144     }
145     return;
146 }
147 
IsMassStorage(const UsbDevice & dev)148 bool UsbMassStorageNotification::IsMassStorage(const UsbDevice &dev)
149 {
150     for (int32_t i = 0; i < dev.GetConfigCount(); ++i) {
151         USBConfig config;
152         dev.GetConfig(i, config);
153         for (uint32_t j = 0; j < config.GetInterfaceCount(); ++j) {
154             UsbInterface interface;
155             config.GetInterface(j, interface);
156             if (interface.GetClass() == USB_DEVICE_CLASS_MASS_STORAGE) {
157                 return true;
158             }
159         }
160     }
161     return false;
162 }
163 
SendNotification(const UsbDevice & dev)164 void UsbMassStorageNotification::SendNotification(const UsbDevice &dev)
165 {
166     USB_HILOGD(MODULE_USB_SERVICE, "enter SendNotification");
167     if (!IsMassStorage(dev)) {
168         USB_HILOGD(MODULE_USB_SERVICE, "Send Notification, not Mass Storage, return!");
169         return;
170     }
171     if (notificationMap[MASS_STORAGE_NOTIFICATION_TITLE_KEY].empty() ||
172         notificationMap[MASS_STORAGE_NOTIFICATION_TEXT_KEY].empty() ||
173         notificationMap[MASS_STORAGE_NOTIFICATION_BUTTON_KEY].empty()) {
174         USB_HILOGE(MODULE_USB_SERVICE, "notificationMap is empty, return!");
175         return;
176     }
177     PublishUsbNotification();
178 }
179 
PublishUsbNotification()180 void UsbMassStorageNotification::PublishUsbNotification()
181 {
182     std::shared_ptr<OHOS::Notification::NotificationNormalContent> normalContent =
183     std::make_shared<OHOS::Notification::NotificationNormalContent>();
184     if (normalContent == nullptr) {
185         USB_HILOGE(MODULE_USB_SERVICE, "notification normal content nullptr");
186         return;
187     }
188     normalContent->SetTitle(notificationMap[MASS_STORAGE_NOTIFICATION_TITLE_KEY]);
189     normalContent->SetText(notificationMap[MASS_STORAGE_NOTIFICATION_TEXT_KEY]);
190     std::shared_ptr<OHOS::Notification::NotificationContent> content =
191         std::make_shared<OHOS::Notification::NotificationContent>(normalContent);
192     auto want = std::make_shared<OHOS::AAFwk::Want>();
193     if (content == nullptr || want == nullptr) {
194         USB_HILOGE(MODULE_USB_SERVICE, "notification content nullptr or want nulllptr");
195         want.reset();
196         content.reset();
197         return;
198     }
199     GetFilemanagerBundleName();
200     want->SetElementName(filemanagerBundleName, filemanagerAbilityName);
201     std::vector<std::shared_ptr<OHOS::AAFwk::Want>> wants;
202     wants.push_back(want);
203     std::vector<OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags> flags;
204     flags.push_back(OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG);
205     OHOS::AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo(
206         REQUEST_CODE,
207         AbilityRuntime::WantAgent::WantAgentConstant::OperationType::START_ABILITY,
208         flags, wants, nullptr
209     );
210     auto wantAgent = OHOS::AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo);
211     std::string buttonTitle = notificationMap[MASS_STORAGE_NOTIFICATION_BUTTON_KEY];
212     std::shared_ptr<OHOS::Notification::NotificationActionButton> actionButton =
213         OHOS::Notification::NotificationActionButton::Create(nullptr, buttonTitle, wantAgent);
214     if (actionButton == nullptr) {
215         USB_HILOGE(MODULE_USB_SERVICE, "notification actionButton nullptr");
216         return;
217     }
218     OHOS::Notification::NotificationRequest request;
219     request.SetNotificationId(MASS_STORAGE_NOTIFICATION_ID);
220     request.SetContent(content);
221     request.AddActionButton(actionButton);
222     request.SetCreatorUid(USB_SYSTEM_ABILITY_ID);
223     request.SetCreatorBundleName(filemanagerBundleName);
224     request.SetCreatorUserId(osAccountId);
225     request.SetLabel(notificationMap[MASS_STORAGE_NOTIFICATION_LABEL_KEY]);
226     request.SetSlotType(OHOS::Notification::NotificationConstant::SlotType::SOCIAL_COMMUNICATION);
227     int32_t result = OHOS::Notification::NotificationHelper::PublishNotification(request);
228     USB_HILOGI(MODULE_USB_SERVICE, "publish mass storage notification result : %{public}d", result);
229 }
230 
CancelNotification(const std::map<std::string,UsbDevice * > & devices,const UsbDevice & dev,const std::string & name)231 void UsbMassStorageNotification::CancelNotification(const std::map<std::string, UsbDevice *> &devices,
232     const UsbDevice &dev, const std::string &name)
233 {
234     if (!IsMassStorage(dev)) {
235         USB_HILOGD(MODULE_USB_SERVICE, "Cancel Notification, not Mass Storage, return!");
236         return;
237     }
238     for (auto it : devices) {
239         UsbDevice *device = it.second;
240         if (device == nullptr) {
241             continue;
242         }
243         if ((it.first != name) && IsMassStorage(*device)) {
244             USB_HILOGD(MODULE_USB_SERVICE, "Cancel Notification, still has other Mass Storage, return!");
245             return;
246         }
247     }
248     int32_t result = OHOS::Notification::NotificationHelper::CancelNotification(MASS_STORAGE_NOTIFICATION_ID);
249     USB_HILOGI(MODULE_USB_SERVICE, "Cancel mass storage notification result : %{public}d", result);
250 }
251 } // namespace USB
252 } // namespace OHOS
253