1/* 2 * Copyright (c) 2021-2024 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#include "hiview_service_ability.h" 16 17#include <cstdio> 18#include <dirent.h> 19#include <fcntl.h> 20#include <functional> 21#include <mutex> 22#include <sys/stat.h> 23#include <unistd.h> 24 25#include "bundle_mgr_client.h" 26#include "file_util.h" 27#include "hiview_log_config_manager.h" 28#include "ipc_skeleton.h" 29#include "iservice_registry.h" 30#include "string_util.h" 31#include "system_ability_definition.h" 32#include "utility/trace_collector.h" 33 34namespace OHOS { 35namespace HiviewDFX { 36namespace { 37DEFINE_LOG_TAG("HiViewSA-HiViewServiceAbility"); 38constexpr int MAXRETRYTIMEOUT = 10; 39constexpr int USER_ID_MOD = 200000; 40 41static std::string GetApplicationNameById(int32_t uid) 42{ 43 std::string bundleName; 44 AppExecFwk::BundleMgrClient client; 45 if (client.GetNameForUid(uid, bundleName) != ERR_OK) { 46 HIVIEW_LOGW("Failed to query bundle name, uid:%{public}d.", uid); 47 } 48 return bundleName; 49} 50 51static std::string GetSandBoxPathByUid(int32_t uid) 52{ 53 std::string bundleName = GetApplicationNameById(uid); 54 if (bundleName.empty()) { 55 return ""; 56 } 57 std::string path; 58 path.append("/data/app/el2/") 59 .append(std::to_string(uid / USER_ID_MOD)) 60 .append("/base/") 61 .append(bundleName) 62 .append("/cache/hiview"); 63 return path; 64} 65 66static std::string ComposeFilePath(const std::string& rootDir, const std::string& destDir, const std::string& fileName) 67{ 68 std::string filePath(rootDir); 69 if (destDir.empty()) { 70 filePath.append("/").append(fileName); 71 } else { 72 filePath.append("/").append(destDir).append("/").append(fileName); 73 } 74 return filePath; 75} 76} 77 78int HiviewServiceAbility::Dump(int32_t fd, const std::vector<std::u16string> &args) 79{ 80 auto service = GetOrSetHiviewService(nullptr); 81 if (service != nullptr) { 82 std::vector<std::string> cmds; 83 for (const auto &arg : args) { 84 cmds.push_back(StringUtil::ConvertToUTF8(arg)); 85 } 86 service->DumpRequestDispatcher(fd, cmds); 87 } 88 return 0; 89} 90 91HiviewServiceAbility::HiviewServiceAbility() : SystemAbility(DFX_SYS_HIVIEW_ABILITY_ID, true) 92{ 93 HIVIEW_LOGI("begin, cmd : %d", DFX_SYS_HIVIEW_ABILITY_ID); 94} 95 96HiviewServiceAbility::~HiviewServiceAbility() 97{ 98 HIVIEW_LOGI("begin, cmd : %d", DFX_SYS_HIVIEW_ABILITY_ID); 99} 100 101void HiviewServiceAbility::StartServiceAbility(int sleepS) 102{ 103 sptr<ISystemAbilityManager> serviceManager; 104 105 int retryTimeout = MAXRETRYTIMEOUT; 106 while (retryTimeout > 0) { 107 --retryTimeout; 108 if (sleepS > 0) { 109 sleep(sleepS); 110 } 111 112 SystemAbilityManagerClient::GetInstance().DestroySystemAbilityManagerObject(); 113 serviceManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 114 if (serviceManager == nullptr) { 115 continue; 116 } 117 118 int result = serviceManager->AddSystemAbility(DFX_SYS_HIVIEW_ABILITY_ID, new HiviewServiceAbility()); 119 if (result != 0) { 120 HIVIEW_LOGE("AddSystemAbility error %d", result); 121 continue; 122 } 123 break; 124 } 125 126 if (serviceManager == nullptr) { 127 HIVIEW_LOGE("serviceManager == nullptr"); 128 return; 129 } 130 131 auto abilityObjext = serviceManager->AsObject(); 132 if (abilityObjext == nullptr) { 133 HIVIEW_LOGE("AsObject() == nullptr"); 134 return; 135 } 136 137 bool ret = abilityObjext->AddDeathRecipient(new HiviewServiceAbilityDeathRecipient()); 138 if (ret == false) { 139 HIVIEW_LOGE("AddDeathRecipient == false"); 140 } 141} 142 143void HiviewServiceAbility::StartService(HiviewService *service) 144{ 145 GetOrSetHiviewService(service); 146 StartServiceAbility(0); 147 IPCSkeleton::JoinWorkThread(); 148} 149 150HiviewService *HiviewServiceAbility::GetOrSetHiviewService(HiviewService *service) 151{ 152 static HiviewService *ref = nullptr; 153 if (service != nullptr) { 154 ref = service; 155 } 156 return ref; 157} 158 159int32_t HiviewServiceAbility::List(const std::string& logType, std::vector<HiviewFileInfo>& fileInfos) 160{ 161 auto configInfoPtr = HiviewLogConfigManager::GetInstance().GetConfigInfoByType(logType); 162 if (configInfoPtr == nullptr) { 163 HIVIEW_LOGI("invalid logtype: %{public}s", logType.c_str()); 164 return HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE; 165 } 166 GetFileInfoUnderDir(configInfoPtr->path, fileInfos); 167 return 0; 168} 169 170void HiviewServiceAbility::GetFileInfoUnderDir(const std::string& dirPath, std::vector<HiviewFileInfo>& fileInfos) 171{ 172 DIR* dir = opendir(dirPath.c_str()); 173 if (dir == nullptr) { 174 HIVIEW_LOGW("open dir failed."); 175 return; 176 } 177 struct stat statBuf {}; 178 for (auto* ent = readdir(dir); ent != nullptr; ent = readdir(dir)) { 179 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0 || ent->d_type == DT_DIR) { 180 continue; 181 } 182 std::string filePath(dirPath + ent->d_name); 183 if (stat(filePath.c_str(), &statBuf) != 0) { 184 HIVIEW_LOGW("stat file failed."); 185 continue; 186 } 187 fileInfos.emplace_back(ent->d_name, statBuf.st_mtime, statBuf.st_size); 188 } 189 closedir(dir); 190} 191 192int32_t HiviewServiceAbility::Copy(const std::string& logType, const std::string& logName, const std::string& dest) 193{ 194 return CopyOrMoveFile(logType, logName, dest, false); 195} 196 197int32_t HiviewServiceAbility::Move(const std::string& logType, const std::string& logName, const std::string& dest) 198{ 199 return CopyOrMoveFile(logType, logName, dest, true); 200} 201 202int32_t HiviewServiceAbility::CopyOrMoveFile( 203 const std::string& logType, const std::string& logName, const std::string& dest, bool isMove) 204{ 205 auto service = GetOrSetHiviewService(); 206 if (service == nullptr) { 207 return HiviewNapiErrCode::ERR_DEFAULT; 208 } 209 auto configInfoPtr = HiviewLogConfigManager::GetInstance().GetConfigInfoByType(logType); 210 if (configInfoPtr == nullptr) { 211 HIVIEW_LOGI("invalid logtype: %{public}s", logType.c_str()); 212 return HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE; 213 } 214 if (isMove && configInfoPtr->isReadOnly) { 215 HIVIEW_LOGW("log: %{public}s is read only.", logType.c_str()); 216 return HiviewNapiErrCode::ERR_INNER_READ_ONLY; 217 } 218 int32_t uid = IPCSkeleton::GetCallingUid(); 219 HIVIEW_LOGI("uid %{public}d, isMove: %{public}d, type:%{public}s, name:%{public}s", 220 uid, isMove, logType.c_str(), StringUtil::HideSnInfo(logName).c_str()); 221 std::string sandboxPath = GetSandBoxPathByUid(uid); 222 if (sandboxPath.empty()) { 223 return HiviewNapiErrCode::ERR_DEFAULT; 224 } 225 std::string sourceFile = configInfoPtr->path + logName; 226 if (!FileUtil::FileExists(sourceFile)) { 227 HIVIEW_LOGW("file: %{public}s not exist.", StringUtil::HideSnInfo(logName).c_str()); 228 return HiviewNapiErrCode::ERR_SOURCE_FILE_NOT_EXIST; 229 } 230 std::string fullPath = ComposeFilePath(sandboxPath, dest, logName); 231 return isMove ? service->Move(sourceFile, fullPath) : service->Copy(sourceFile, fullPath); 232} 233 234int32_t HiviewServiceAbility::Remove(const std::string& logType, const std::string& logName) 235{ 236 auto service = GetOrSetHiviewService(); 237 if (service == nullptr) { 238 return HiviewNapiErrCode::ERR_DEFAULT; 239 } 240 HIVIEW_LOGI("type:%{public}s, name:%{public}s", logType.c_str(), StringUtil::HideSnInfo(logName).c_str()); 241 auto configInfoPtr = HiviewLogConfigManager::GetInstance().GetConfigInfoByType(logType); 242 if (configInfoPtr == nullptr) { 243 HIVIEW_LOGI("invalid logtype: %{public}s", logType.c_str()); 244 return HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE; 245 } 246 if (configInfoPtr->isReadOnly) { 247 HIVIEW_LOGW("log: %{public}s is read only.", logType.c_str()); 248 return HiviewNapiErrCode::ERR_INNER_READ_ONLY; 249 } 250 std::string sourceFile = configInfoPtr->path + logName; 251 if (!FileUtil::FileExists(sourceFile)) { 252 HIVIEW_LOGW("file: %{public}s not exist.", StringUtil::HideSnInfo(logName).c_str()); 253 return HiviewNapiErrCode::ERR_SOURCE_FILE_NOT_EXIST; 254 } 255 return service->Remove(sourceFile); 256} 257 258void HiviewServiceAbility::OnDump() 259{ 260 HIVIEW_LOGI("called"); 261} 262 263void HiviewServiceAbility::OnStart() 264{ 265 HIVIEW_LOGI("called"); 266} 267 268void HiviewServiceAbility::OnStop() 269{ 270 HIVIEW_LOGI("called"); 271} 272 273CollectResultParcelable<int32_t> HiviewServiceAbility::OpenSnapshotTrace(const std::vector<std::string>& tagGroups) 274{ 275 auto traceRetHandler = [&tagGroups] (HiviewService* service) { 276 return service->OpenSnapshotTrace(tagGroups); 277 }; 278 return TraceCalling<int32_t>(traceRetHandler); 279} 280 281CollectResultParcelable<std::vector<std::string>> HiviewServiceAbility::DumpSnapshotTrace(int32_t caller) 282{ 283 auto traceRetHandler = [caller] (HiviewService* service) { 284 return service->DumpSnapshotTrace(static_cast<UCollect::TraceCaller>(caller)); 285 }; 286 return TraceCalling<std::vector<std::string>>(traceRetHandler); 287} 288 289CollectResultParcelable<int32_t> HiviewServiceAbility::OpenRecordingTrace(const std::string& tags) 290{ 291 auto traceRetHandler = [&tags] (HiviewService* service) { 292 return service->OpenRecordingTrace(tags); 293 }; 294 return TraceCalling<int32_t>(traceRetHandler); 295} 296 297CollectResultParcelable<int32_t> HiviewServiceAbility::RecordingTraceOn() 298{ 299 auto traceRetHandler = [] (HiviewService* service) { 300 return service->RecordingTraceOn(); 301 }; 302 return TraceCalling<int32_t>(traceRetHandler); 303} 304 305CollectResultParcelable<std::vector<std::string>> HiviewServiceAbility::RecordingTraceOff() 306{ 307 auto traceRetHandler = [] (HiviewService* service) { 308 return service->RecordingTraceOff(); 309 }; 310 return TraceCalling<std::vector<std::string>>(traceRetHandler); 311} 312 313CollectResultParcelable<int32_t> HiviewServiceAbility::CloseTrace() 314{ 315 auto traceRetHandler = [] (HiviewService* service) { 316 return service->CloseTrace(); 317 }; 318 return TraceCalling<int32_t>(traceRetHandler); 319} 320 321CollectResultParcelable<int32_t> HiviewServiceAbility::RecoverTrace() 322{ 323 auto traceRetHandler = [] (HiviewService* service) { 324 return service->RecoverTrace(); 325 }; 326 return TraceCalling<int32_t>(traceRetHandler); 327} 328 329CollectResultParcelable<int32_t> HiviewServiceAbility::CaptureDurationTrace(UCollectClient::AppCaller &appCaller) 330{ 331 appCaller.uid = IPCSkeleton::GetCallingUid(); 332 appCaller.pid = IPCSkeleton::GetCallingPid(); 333 334 auto traceRetHandler = [=, &appCaller] (HiviewService* service) { 335 return service->CaptureDurationTrace(appCaller); 336 }; 337 return TraceCalling<int32_t>(traceRetHandler); 338} 339 340CollectResultParcelable<double> HiviewServiceAbility::GetSysCpuUsage() 341{ 342 return TraceCalling<double>([] (HiviewService* service) { 343 return service->GetSysCpuUsage(); 344 }); 345} 346 347CollectResultParcelable<int32_t> HiviewServiceAbility::SetAppResourceLimit(UCollectClient::MemoryCaller& memoryCaller) 348{ 349 auto handler = [&memoryCaller] (HiviewService* service) { 350 return service->SetAppResourceLimit(memoryCaller); 351 }; 352 return TraceCalling<int32_t>(handler); 353} 354 355CollectResultParcelable<int32_t> HiviewServiceAbility::GetGraphicUsage(int32_t pid) 356{ 357 auto handler = [pid] (HiviewService* service) { 358 return service->GetGraphicUsage(pid); 359 }; 360 return TraceCalling<int32_t>(handler); 361} 362 363HiviewServiceAbilityDeathRecipient::HiviewServiceAbilityDeathRecipient() 364{ 365 HIVIEW_LOGI("called"); 366} 367 368HiviewServiceAbilityDeathRecipient::~HiviewServiceAbilityDeathRecipient() 369{ 370 HIVIEW_LOGI("called"); 371} 372 373void HiviewServiceAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object) 374{ 375 HIVIEW_LOGI("called"); 376 if (object == nullptr) { 377 return; 378 } 379 HiviewServiceAbility::StartServiceAbility(1); 380} 381} // namespace HiviewDFX 382} // namespace OHOS 383