1 /*
2 * Copyright (c) 2025 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
17 #include <algorithm>
18
19 #include "ability_manager_errors.h"
20 #include "ability_manager_service.h"
21 #include "ability_record.h"
22 #include "ability_util.h"
23 #include "common_event.h"
24 #include "common_event_manager.h"
25 #include "common_event_support.h"
26 #include "hilog_tag_wrapper.h"
27 #include "interceptor/kiosk_interceptor.h"
28 #include "ipc_skeleton.h"
29 #include "kiosk_manager.h"
30 #include "permission_constants.h"
31 #include "session_manager_lite.h"
32 #include "singleton.h"
33 #include "utils/want_utils.h"
34
35 namespace OHOS {
36 namespace AAFwk {
37 constexpr char KIOSK_MODE_ENABLED[] = "const.product.kioskmode.enabled";
38
GetInstance()39 KioskManager &KioskManager::GetInstance()
40 {
41 static KioskManager manager;
42 return manager;
43 }
44
OnAppStop(const AppInfo & info)45 void KioskManager::OnAppStop(const AppInfo &info)
46 {
47 if (info.state != AppState::TERMINATED && info.state != AppState::END) {
48 return;
49 }
50 TAG_LOGD(AAFwkTag::ABILITYMGR, "App stop, bundleName: %{public}s, state: %{public}d",
51 info.bundleName.c_str(), static_cast<int32_t>(info.state));
52 std::lock_guard<std::mutex> lock(kioskManagermutex_);
53 if (IsInKioskModeInner() && (info.bundleName == kioskStatus_.kioskBundleName_)) {
54 ExitKioskModeInner(info.bundleName, kioskStatus_.kioskToken_);
55 }
56 }
57
UpdateKioskApplicationList(const std::vector<std::string> & appList)58 int32_t KioskManager::UpdateKioskApplicationList(const std::vector<std::string> &appList)
59 {
60 if (!system::GetBoolParameter(KIOSK_MODE_ENABLED, false)) {
61 TAG_LOGE(AAFwkTag::ABILITYMGR, "Disabled config");
62 return ERR_CAPABILITY_NOT_SUPPORT;
63 }
64
65 if (!PermissionVerification::GetInstance()->IsSystemAppCall() &&
66 !PermissionVerification::GetInstance()->IsSACall()) {
67 TAG_LOGE(AAFwkTag::ABILITYMGR, "not system app");
68 return ERR_NOT_SYSTEM_APP;
69 }
70 if (!PermissionVerification::GetInstance()->VerifyCallingPermission(
71 PermissionConstants::PERMISSION_MANAGE_EDM_POLICY)) {
72 TAG_LOGE(AAFwkTag::ABILITYMGR, "not MANAGE_EDM_POLICY permission");
73 return CHECK_PERMISSION_FAILED;
74 }
75 std::lock_guard<std::mutex> lock(kioskManagermutex_);
76 if (IsInKioskModeInner()) {
77 auto it = std::find(appList.begin(), appList.end(), kioskStatus_.kioskBundleName_);
78 if (it == appList.end()) {
79 auto ret = ExitKioskModeInner(kioskStatus_.kioskBundleName_, kioskStatus_.kioskToken_);
80 if (ret != ERR_OK) {
81 return ret;
82 }
83 }
84 }
85 whitelist_.clear();
86 for (const auto &app : appList) {
87 whitelist_.insert(app);
88 }
89 auto sceneSessionManager = Rosen::SessionManagerLite::GetInstance().GetSceneSessionManagerLiteProxy();
90 CHECK_POINTER_AND_RETURN_LOG(sceneSessionManager, INNER_ERR, "sceneSessionManager is nullptr");
91 sceneSessionManager->UpdateKioskAppList(appList);
92 return ERR_OK;
93 }
94
EnterKioskMode(sptr<IRemoteObject> callerToken)95 int32_t KioskManager::EnterKioskMode(sptr<IRemoteObject> callerToken)
96 {
97 if (!system::GetBoolParameter(KIOSK_MODE_ENABLED, false)) {
98 TAG_LOGE(AAFwkTag::ABILITYMGR, "Disabled config");
99 return ERR_CAPABILITY_NOT_SUPPORT;
100 }
101 auto record = Token::GetAbilityRecordByToken(callerToken);
102 if (!record) {
103 TAG_LOGE(AAFwkTag::ABILITYMGR, "record null");
104 return INVALID_PARAMETERS_ERR;
105 }
106 std::string bundleName = record->GetAbilityInfo().bundleName;
107 if (!CheckCallerIsForeground(callerToken)) {
108 TAG_LOGE(AAFwkTag::ABILITYMGR, "The application is not in the foreground !");
109 return ERR_APP_NOT_IN_FOCUS;
110 }
111 std::lock_guard<std::mutex> lock(kioskManagermutex_);
112 if (!IsInWhiteListInner(bundleName)) {
113 return ERR_KIOSK_MODE_NOT_IN_WHITELIST;
114 }
115
116 if (IsInKioskModeInner()) {
117 return ERR_ALREADY_IN_KIOSK_MODE;
118 }
119
120 kioskStatus_.isKioskMode_ = true;
121 kioskStatus_.kioskBundleName_ = bundleName;
122 kioskStatus_.kioskBundleUid_ = IPCSkeleton::GetCallingUid();
123 kioskStatus_.kioskToken_ = callerToken;
124 GetEnterKioskModeCallback()();
125 NotifyKioskModeChanged(true);
126 auto sceneSessionManager = Rosen::SessionManagerLite::GetInstance().GetSceneSessionManagerLiteProxy();
127 CHECK_POINTER_AND_RETURN_LOG(sceneSessionManager, INNER_ERR, "sceneSessionManager is nullptr");
128 sceneSessionManager->EnterKioskMode(callerToken);
129 return ERR_OK;
130 }
131
ExitKioskMode(sptr<IRemoteObject> callerToken)132 int32_t KioskManager::ExitKioskMode(sptr<IRemoteObject> callerToken)
133 {
134 if (!system::GetBoolParameter(KIOSK_MODE_ENABLED, false)) {
135 TAG_LOGE(AAFwkTag::ABILITYMGR, "Disabled config");
136 return ERR_CAPABILITY_NOT_SUPPORT;
137 }
138 auto record = Token::GetAbilityRecordByToken(callerToken);
139 if (!record) {
140 TAG_LOGE(AAFwkTag::ABILITYMGR, "record null");
141 return INVALID_PARAMETERS_ERR;
142 }
143 std::lock_guard<std::mutex> lock(kioskManagermutex_);
144 return ExitKioskModeInner(record->GetAbilityInfo().bundleName, callerToken);
145 }
146
ExitKioskModeInner(const std::string & bundleName,sptr<IRemoteObject> callerToken)147 int32_t KioskManager::ExitKioskModeInner(const std::string &bundleName, sptr<IRemoteObject> callerToken)
148 {
149 if (!IsInWhiteListInner(bundleName)) {
150 return ERR_KIOSK_MODE_NOT_IN_WHITELIST;
151 }
152
153 if (!IsInKioskModeInner()) {
154 return ERR_NOT_IN_KIOSK_MODE;
155 }
156 GetExitKioskModeCallback()();
157 NotifyKioskModeChanged(false);
158 kioskStatus_.Clear();
159 auto sceneSessionManager = Rosen::SessionManagerLite::GetInstance().GetSceneSessionManagerLiteProxy();
160 CHECK_POINTER_AND_RETURN_LOG(sceneSessionManager, INNER_ERR, "sceneSessionManager is nullptr");
161 sceneSessionManager->ExitKioskMode(callerToken);
162 return ERR_OK;
163 }
164
GetKioskStatus(KioskStatus & kioskStatus)165 int32_t KioskManager::GetKioskStatus(KioskStatus &kioskStatus)
166 {
167 if (!system::GetBoolParameter(KIOSK_MODE_ENABLED, false)) {
168 TAG_LOGE(AAFwkTag::ABILITYMGR, "Disabled config");
169 return ERR_CAPABILITY_NOT_SUPPORT;
170 }
171 if (!PermissionVerification::GetInstance()->IsSystemAppCall() &&
172 !(PermissionVerification::GetInstance()->IsSACall() &&
173 PermissionVerification::GetInstance()->VerifyCallingPermission(
174 PermissionConstants::PERMISSION_GET_EDM_CONFIG))) {
175 TAG_LOGE(AAFwkTag::ABILITYMGR, "not system app or sa call without permission");
176 return ERR_NOT_SYSTEM_APP;
177 }
178 std::lock_guard<std::mutex> lock(kioskManagermutex_);
179 kioskStatus = kioskStatus_;
180 return ERR_OK;
181 }
182
IsInKioskMode()183 bool KioskManager::IsInKioskMode()
184 {
185 std::lock_guard<std::mutex> lock(kioskManagermutex_);
186 return IsInKioskModeInner();
187 }
188
IsInWhiteList(const std::string & bundleName)189 bool KioskManager::IsInWhiteList(const std::string &bundleName)
190 {
191 std::lock_guard<std::mutex> lock(kioskManagermutex_);
192 return IsInWhiteListInner(bundleName);
193 }
194
IsInKioskModeInner()195 bool KioskManager::IsInKioskModeInner()
196 {
197 return kioskStatus_.isKioskMode_;
198 }
199
NotifyKioskModeChanged(bool isInKioskMode)200 void KioskManager::NotifyKioskModeChanged(bool isInKioskMode)
201 {
202 std::string eventData = isInKioskMode
203 ? EventFwk::CommonEventSupport::COMMON_EVENT_KIOSK_MODE_ON
204 : EventFwk::CommonEventSupport::COMMON_EVENT_KIOSK_MODE_OFF;
205 Want want;
206 want.SetAction(eventData);
207 want.SetParam("bundleName", kioskStatus_.kioskBundleName_);
208 want.SetParam("uid", kioskStatus_.kioskBundleUid_);
209 want.SetParam("userId", kioskStatus_.kioskBundleUid_ / BASE_USER_RANGE);
210 EventFwk::CommonEventData commonData {want};
211 if (!IN_PROCESS_CALL(EventFwk::CommonEventManager::PublishCommonEvent(commonData))) {
212 TAG_LOGE(AAFwkTag::ABILITYMGR, "PublishCommonEvent failed, eventData: %{public}s", eventData.c_str());
213 }
214 }
215
IsInWhiteListInner(const std::string & bundleName)216 bool KioskManager::IsInWhiteListInner(const std::string &bundleName)
217 {
218 return whitelist_.count(bundleName) != 0;
219 }
220
GetEnterKioskModeCallback()221 std::function<void()> KioskManager::GetEnterKioskModeCallback()
222 {
223 auto enterKioskModeCallback = []() {
224 TAG_LOGI(AAFwkTag::ABILITYMGR, "EnterKioskMode");
225 KioskManager::GetInstance().AddKioskInterceptor();
226 };
227 return enterKioskModeCallback;
228 }
229
GetExitKioskModeCallback()230 std::function<void()> KioskManager::GetExitKioskModeCallback()
231 {
232 auto exitKioskModeCallback = []() {
233 TAG_LOGI(AAFwkTag::ABILITYMGR, "ExitKioskMode");
234 KioskManager::GetInstance().RemoveKioskInterceptor();
235 };
236 return exitKioskModeCallback;
237 }
238
AddKioskInterceptor()239 void KioskManager::AddKioskInterceptor()
240 {
241 auto abilityMgr = DelayedSingleton<AbilityManagerService>::GetInstance();
242 if (abilityMgr == nullptr) {
243 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid abilityMgr pointer");
244 return;
245 }
246 auto interceptorExecuter = abilityMgr->GetAbilityInterceptorExecuter();
247 if (interceptorExecuter == nullptr) {
248 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid interceptorExecuter pointer");
249 return;
250 }
251 interceptorExecuter->AddInterceptor("KioskWhitelist", std::make_shared<KioskInterceptor>());
252 }
253
RemoveKioskInterceptor()254 void KioskManager::RemoveKioskInterceptor()
255 {
256 auto abilityMgr = DelayedSingleton<AbilityManagerService>::GetInstance();
257 if (abilityMgr == nullptr) {
258 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid abilityMgr pointer");
259 return;
260 }
261 auto interceptorExecuter = abilityMgr->GetAbilityInterceptorExecuter();
262 if (interceptorExecuter == nullptr) {
263 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid interceptorExecuter pointer");
264 return;
265 }
266 interceptorExecuter->RemoveInterceptor("KioskWhitelist");
267 }
268
CheckCallerIsForeground(sptr<IRemoteObject> callerToken)269 bool KioskManager::CheckCallerIsForeground(sptr<IRemoteObject> callerToken)
270 {
271 AppExecFwk::RunningProcessInfo processInfo;
272 DelayedSingleton<AppScheduler>::GetInstance()->GetRunningProcessInfoByToken(
273 callerToken, processInfo);
274
275 return processInfo.state_ ==
276 AppExecFwk::AppProcessState::APP_STATE_FOREGROUND;
277 }
278 } // namespace AAFwk
279 } // namespace OHOS
280