diff --git a/CODEOWNERS b/CODEOWNERS index c0a5b14ae5d09aa5cc2e66ee100b5e0e5c112f29..3d321f2da33cfcf3088534543d8266b16683046f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -13,4 +13,4 @@ * limitations under the License. */ - * @liveery @wang_fenging @cat \ No newline at end of file + * @liveery @wang_fenging @zl_zl @zhouge94 diff --git a/appdata-sandbox-app.json b/appdata-sandbox-app.json index 3f6dd7b35d0c3f2011097b88f6fe31ccd185f0a0..05ae5c5b948a8442504702c8aa333b76ef39cb86 100755 --- a/appdata-sandbox-app.json +++ b/appdata-sandbox-app.json @@ -13,7 +13,7 @@ "sandbox-path" : "/dev" }, { "src-path" : "/proc", - "sandbox-path" : "/proc" + "sandbox-path" : "/proc" }, { "src-path" : "/sys", "sandbox-path" : "/sys" @@ -24,8 +24,11 @@ "src-path" : "/module_update", "sandbox-path" : "/module_update" }, { - "src-path" : "/system/app", - "sandbox-path" : "/system/app" + "src-path" : "/system/app/appServiceFwk", + "sandbox-path" : "/system/app/appServiceFwk" + }, { + "src-path" : "/system/app/shared_bundles", + "sandbox-path" : "/system/app/shared_bundles" }, { "src-path" : "/system/fonts", "sandbox-path" : "/system/fonts" @@ -58,7 +61,7 @@ "sandbox-path" : "/vendor/" }, { "src-path" : "/vendor/etc/vulkan", - "sandbox-path" : "/vendor/etc/vulkan" + "sandbox-path" : "/vendor/etc/vulkan" }, { "src-path" : "/vendor/etc/silk", "sandbox-path" : "/vendor/etc/silk" @@ -89,12 +92,12 @@ }, { "src-path" : "/system/app/SystemResources", "sandbox-path" : "/data/global/systemResources" - }, { - "src-path" : "/data/misc", - "sandbox-path" : "/data/storage/el1/bundle/misc" }, { "src-path" : "/data/service/el1/public/cert_manager_service/certificates/user_open", "sandbox-path" : "/data/certificates/user_cacerts" + },{ + "src-path" : "/chip_prod/etc/passthrough", + "sandbox-path" : "/chip_prod/etc/passthrough" }], "mount-files": [{ "src-path" : "/system/etc/hosts", @@ -130,10 +133,13 @@ "sandbox-path" : "/data/storage/el1/bundle", "check-action-status": "true" }, { - "src-path" : "/data/local/ark-cache/", + "src-path" : "/data/misc", + "sandbox-path" : "/data/storage/el1/bundle/misc" + }, { + "src-path" : "/data/app/el1/public/aot_compiler/ark_cache/", "sandbox-path" : "/data/storage/ark-cache" }, { - "src-path" : "/data/local/ark-profile//", + "src-path" : "/data/app/el1//aot_compiler/ark_profile/", "sandbox-path" : "/data/storage/ark-profile" }, { "src-path" : "/data/local/shader_cache/local/", @@ -159,6 +165,9 @@ }, { "src-path" : "/mnt/hmdfs//cloud/data/", "sandbox-path" : "/data/storage/el2/cloud" + }, { + "src-path" : "/mnt/data//media_fuse", + "sandbox-path" : "/data/storage/el2/media" }], "symbol-links" : [{ "target-name" : "/mnt/nweb/tmp", @@ -173,13 +182,10 @@ "sandbox-switch": "ON", "gids": ["file_manager", "user_data_rw"], "mount-paths": [{ - "src-path": "/storage/media//local/files/Docs", - "sandbox-path": "/storage/Users/" - }, { - "src-path": "/storage/media//local/files/.Recent", - "sandbox-path": "/storage/Users//.Recent" + "src-path": "/mnt/user//nosharefs/docs", + "sandbox-path": "/storage/Users" }], - "mount-groups": [ "user-public", "Users" ] + "mount-groups": [ "user-public", "file_manager_recent" ] }, { "name": "ohos.permission.READ_IMAGEVIDEO", "sandbox-switch": "ON", @@ -191,19 +197,12 @@ }, { "name": "ohos.permission.FILE_CROSS_APP", "gids": ["file_manager"], - "mount-paths": [{ - "src-path": "/storage/media//local/files/Docs", - "sandbox-path": "/storage/Users/" - }, { - "src-path": "/data/app/el1//base", - "sandbox-path": "/storage/Users//appdata/el1", - "category": "dac_override" - }, { - "src-path": "/data/app/el2//base", - "sandbox-path": "/storage/Users//appdata/el2", - "category": "dac_override" - }], - "mount-groups": [ "user-public" ] + "mount-paths": [], + "mount-groups": [ "user-public", "storage_users" ] + }, { + "name": "ohos.permission.FILE_ACCESS_COMMON_DIR", + "mount-paths": [], + "mount-groups": [ "user-public", "storage_users" ] }, { "name": "ohos.permission.ACTIVATE_THEME_PACKAGE", "gids": ["wallpaper"], @@ -339,7 +338,7 @@ }] }, { "name": "ohos.permission.RECEIVE_UPDATE_MESSAGE", - "mount-paths": [{ + "mount-paths": [{ "src-path": "/data/service/el1/public/update/param_service/install/system/etc/", "sandbox-path": "/data/service/el1/public/update/param_service/install/system/etc/" }] @@ -348,6 +347,14 @@ "gids": ["file_manager"], "mount-paths":[], "mount-groups": ["Users", "user-public"] + }, { + "name": "ohos.permission.ACCESS_APP_INSTALL_DIR", + "sandbox-switch": "ON", + "gids": ["app_install"], + "mount-paths": [{ + "src-path": "/data/service/el1/public/bms/bundle_manager_service/app_install//", + "sandbox-path": "/data/bms_app_install/" + }] }], "spawn-flag": [{ "name": "START_FLAGS_BACKUP", @@ -389,8 +396,14 @@ }, { "src-path" : "/data/app/el1/bundle//hnp/", "sandbox-path" : "/data/app" - } - ]}], + }] + }, { + "name": "PREINSTALLED_HAP", + "mount-paths": [{ + "src-path": "/system/app", + "sandbox-path": "/system/app" + }] + }], "package-name": [{ "name": "com.ohos.medialibrary.medialibrarydata", "mount-paths" : [{ @@ -444,6 +457,24 @@ "src-path": "/storage/media//local/files/Docs", "sandbox-path": "/currentUser" }] + }, { + "name": "file_manager_recent", + "type": "app-variable", + "mount-paths": [{ + "src-path": "/storage/media//local/files/.Recent", + "sandbox-path": "/storage/Users//.Recent" + }] + }, { + "name": "storage_users", + "type": "app-variable", + "mount-paths": [{ + "src-path": "/mnt/user//sharefs/docs", + "sandbox-path": "/mnt/storage/Users" + }, { + "src-path": "/mnt/sandbox//app-root/mnt/storage/Users", + "sandbox-path": "/storage/Users", + "category": "dac_override_delete" + }] }, { "name": "el2", "type": "app-variable", @@ -543,4 +574,4 @@ "category": "shared" }] }] -} \ No newline at end of file +} diff --git a/appdata-sandbox-isolated.json b/appdata-sandbox-isolated.json index 19a8b9633d7259cb6da34472dad6d60729238c35..bd9aa04b5b3203111a2a5fbae35af3b334002671 100644 --- a/appdata-sandbox-isolated.json +++ b/appdata-sandbox-isolated.json @@ -49,51 +49,6 @@ "sandbox-path" : "/system/lib64", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" - }, { - "src-path" : "/system/lib/platformsdk", - "sandbox-path" : "/system/lib/platformsdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/ndk", - "sandbox-path" : "/system/lib/ndk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/module", - "sandbox-path" : "/system/lib/module", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/chipset-pub-sdk", - "sandbox-path" : "/system/lib/chipset-pub-sdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/chipset-sdk", - "sandbox-path" : "/system/lib/chipset-sdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/seccomp", - "sandbox-path" : "/system/lib/seccomp", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/extensionability", - "sandbox-path" : "/system/lib/extensionability", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/media", - "sandbox-path" : "/system/lib/media", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/ld-musl-arm.so.1", - "sandbox-path" : "/system/lib/ld-musl-arm.so.1", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" }, { "src-path" : "/data/app/el1/bundle/public/", "sandbox-path" : "/data/storage/el1/bundle", diff --git a/appdata-sandbox.json b/appdata-sandbox.json index 9be9213fcffc65b83e84701ad4821a9903390e92..ce3425734850459d261cf22a856174c09aac04c8 100755 --- a/appdata-sandbox.json +++ b/appdata-sandbox.json @@ -48,51 +48,6 @@ "sandbox-path" : "/system/lib", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" - }, { - "src-path" : "/system/lib/platformsdk", - "sandbox-path" : "/system/lib/platformsdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/ld-musl-arm.so.1", - "sandbox-path" : "/system/lib/ld-musl-arm.so.1", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - },{ - "src-path" : "/system/lib/ndk", - "sandbox-path" : "/system/lib/ndk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/module", - "sandbox-path" : "/system/lib/module", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/chipset-pub-sdk", - "sandbox-path" : "/system/lib/chipset-pub-sdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/chipset-sdk", - "sandbox-path" : "/system/lib/chipset-sdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/seccomp", - "sandbox-path" : "/system/lib/seccomp", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/extensionability", - "sandbox-path" : "/system/lib/extensionability", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/media", - "sandbox-path" : "/system/lib/media", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" }, { "src-path" : "/system/data", "sandbox-path" : "/system/data", @@ -199,12 +154,12 @@ "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/data/local/ark-cache/", + "src-path" : "/data/app/el1/public/aot_compiler/ark_cache/", "sandbox-path" : "/data/storage/ark-cache", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/data/local/ark-profile//", + "src-path" : "/data/app/el1//aot_compiler/ark_profile/", "sandbox-path" : "/data/storage/ark-profile", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" @@ -283,6 +238,16 @@ "sandbox-path" : "/data/storage/el2/cloud", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" + }, { + "src-path" : "/mnt/data//media_fuse", + "sandbox-path" : "/data/storage/el2/media", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/chip_prod/etc/passthrough", + "sandbox-path" : "/chip_prod/etc/passthrough", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" } ], "symbol-links" : [{ @@ -386,6 +351,14 @@ "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" } + ]}, { + "flags": "PREINSTALLED_HAP", + "mount-paths": [{ + "src-path": "/system/app", + "sandbox-path": "/system/app", + "sandbox-flags": [ "bind", "rec" ], + "check-action-status": "false" + } ]} ], "symbol-links" : [ @@ -531,48 +504,98 @@ "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/system/lib/platformsdk", - "sandbox-path" : "/system/lib/platformsdk", + "src-path" : "/data/service/el1/public/for-all-app", + "sandbox-path" : "/data/service/el1/public/for-all-app", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/system/lib/ndk", - "sandbox-path" : "/system/lib/ndk", + "src-path" : "/system/app/", + "sandbox-path" : "/system/app/", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/system/lib/module", - "sandbox-path" : "/system/lib/module", + "src-path" : "/vendor/lib", + "sandbox-path" : "/vendor/lib", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/system/lib/chipset-pub-sdk", - "sandbox-path" : "/system/lib/chipset-pub-sdk", + "src-path" : "/data/app/el1/bundle/public/", + "sandbox-path" : "/data/app/el1/bundle/public/", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/system/lib/chipset-sdk", - "sandbox-path" : "/system/lib/chipset-sdk", + "src-path" : "/system/app/NWeb", + "sandbox-path" : "/system/app/NWeb", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/system/lib/seccomp", - "sandbox-path" : "/system/lib/seccomp", + "src-path" : "/module_update/ArkWebCore/app/", + "sandbox-path" : "/module_update/ArkWebCore/app/", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" + } + ], + "symbol-links" : [{ + "target-name" : "/system/etc", + "link-name" : "/etc", + "check-action-status": "false" + }, { + "target-name" : "/system/bin", + "link-name" : "/bin", + "check-action-status": "false" }, { - "src-path" : "/system/lib/extensionability", - "sandbox-path" : "/system/lib/extensionability", + "target-name" : "/system/lib", + "link-name" : "/lib", + "check-action-status": "false" + } + ] + }], + "__internal__.com.ohos.gpu" : [{ + "sandbox-root" : "/mnt/sandbox/com.ohos.render/", + "sandbox-ns-flags" : [ "pid", "net" ], + "mount-paths" : [{ + "src-path" : "/dev", + "sandbox-path" : "/dev", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/system/lib/media", - "sandbox-path" : "/system/lib/media", + "src-path" : "/proc", + "sandbox-path" : "/proc", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/system/lib/ld-musl-arm.so.1", - "sandbox-path" : "/system/lib/ld-musl-arm.so.1", + "src-path" : "/sys", + "sandbox-path" : "/sys", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/system/fonts", + "sandbox-path" : "/system/fonts", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/system/etc", + "sandbox-path" : "/system/etc", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/system/etc/hosts", + "sandbox-path" : "/data/service/el1/network/hosts_user/hosts", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/data/app/el1/bundle/public/", + "sandbox-path" : "/data/storage/el1/bundle/arkwebcore", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/system/bin", + "sandbox-path" : "/system/bin", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/system/lib", + "sandbox-path" : "/system/lib", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { @@ -600,6 +623,26 @@ "sandbox-path" : "/module_update/ArkWebCore/app/", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" + }, { + "src-path" : "/vendor/etc/vulkan/icd.d", + "sandbox-path" : "/vendor/etc/vulkan/icd.d", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/data/local/shader_cache/local/", + "sandbox-path" : "/data/storage/shader_cache/local", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/data/local/shader_cache/cloud/", + "sandbox-path" : "/data/storage/shader_cache/cloud", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" + }, { + "src-path" : "/data/local/shader_cache/cloud/common", + "sandbox-path" : "/data/storage/shader_cache/common", + "sandbox-flags" : [ "bind", "rec" ], + "check-action-status": "false" } ], "symbol-links" : [{ @@ -615,13 +658,7 @@ "link-name" : "/lib", "check-action-status": "false" } - ], - "flags-point" : [{ - "flags": "DLP_MANAGER", - "sandbox-root" : "/mnt/sandbox/com.ohos.render/", - "mount-paths" : [], - "symbol-links" : [{}] - }] + ] }] }], "permission":[{ @@ -629,6 +666,10 @@ "sandbox-switch": "ON", "gids": [1006, 1008], "mount-paths": [{ + "src-path": "/mnt/user//nosharefs/docs", + "sandbox-path": "/storage/Users", + "sandbox-flags": [ "bind", "rec" ] + },{ "src-path": "/data/service/el1/public/storage_daemon/share/public", "sandbox-path": "/storage/Share", "sandbox-flags": [ "bind", "rec" ] @@ -638,37 +679,11 @@ "sandbox-path": "/storage/External", "sandbox-flags": [ "bind", "rec" ] }, - { - "src-path": "/storage/media//local/files/Docs", - "sandbox-path": "/storage/Users/", - "sandbox-flags": [ "bind", "rec" ] - }, { "src-path": "/storage/media//local/files/.Recent", "sandbox-path": "/storage/Users//.Recent", "sandbox-flags": [ "bind", "rec" ] }, - { - "src-path": "/data/app/el1//base", - "sandbox-path": "/storage/Users//appdata/el1/base", - "sandbox-flags-customized": ["MS_NODEV"], - "dac-override-sensitive": "true", - "fs-type": "sharefs", - "options": "override" - }, - { - "src-path": "/data/app/el2//base", - "sandbox-path": "/storage/Users//appdata/el2/base", - "sandbox-flags-customized": ["MS_NODEV"], - "dac-override-sensitive": "true", - "fs-type": "sharefs", - "options": "override" - }, - { - "src-path": "/mnt/hmdfs//account/merge_view/data", - "sandbox-path": "/storage/Users//appdata/el2/distributedfiles", - "sandbox-flags": [ "bind", "rec" ] - }, { "src-path": "/mnt/data//hmdfs", "sandbox-path": "/storage/hmdfs", @@ -689,44 +704,36 @@ "ohos.permission.FILE_CROSS_APP":[{ "sandbox-switch": "ON", "mount-paths": [{ - "src-path": "/storage/media//local/files/Docs", - "sandbox-path": "/storage/Users/", + "src-path": "/mnt/data/external", + "sandbox-path": "/storage/External", "sandbox-flags": [ "bind", "rec" ] }, { - "src-path": "/data/app/el1//base", - "sandbox-path": "/storage/Users//appdata/el1", - "sandbox-flags-customized": ["MS_NODEV"], - "dac-override-sensitive": "true", - "fs-type": "sharefs", - "options": "override" + "src-path": "/mnt/user//sharefs/docs", + "sandbox-path": "/mnt/storage/Users", + "sandbox-flags": [ "bind", "rec" ] }, { - "src-path": "/data/app/el2//base", - "sandbox-path": "/storage/Users//appdata/el2", - "sandbox-flags-customized": ["MS_NODEV"], + "src-path": "/mnt/sandbox///mnt/storage/Users", + "sandbox-path": "/storage/Users", + "sandbox-flags-customized": [ "MS_NODEV"], "dac-override-sensitive": "true", "fs-type": "sharefs", "options": "override" - }, - { - "src-path": "/data/service/el1/public/storage_daemon/share/public", - "sandbox-path": "/storage/Share", - "sandbox-flags": [ "bind", "rec" ] - }, - { - "src-path": "/mnt/data/external", - "sandbox-path": "/storage/External", - "sandbox-flags": [ "bind", "rec" ] } ] }], "ohos.permission.FILE_ACCESS_COMMON_DIR":[{ "sandbox-switch": "ON", "mount-paths": [{ - "src-path": "/storage/media//local/files/Docs", - "sandbox-path": "/storage/Users/currentUser", - "sandbox-flags": [ "MS_NODEV" ], + "src-path": "/mnt/user//sharefs/docs", + "sandbox-path": "/mnt/storage/Users", + "sandbox-flags": [ "bind", "rec" ] + }, + { + "src-path": "/mnt/sandbox///mnt/storage/Users", + "sandbox-path": "/storage/Users", + "sandbox-flags-customized": [ "MS_NODEV"], "dac-override-sensitive": "true", "fs-type": "sharefs", "options": "override" @@ -777,6 +784,16 @@ } ] }], + "ohos.permission.ACCESS_APP_INSTALL_DIR":[{ + "sandbox-switch": "ON", + "gids": [2002], + "mount-paths": [{ + "src-path": "/data/service/el1/public/bms/bundle_manager_service/app_install//", + "sandbox-path": "/data/bms_app_install/", + "sandbox-flags": [ "bind", "rec" ] + } + ] + }], "ohos.permission.ACCESS_BBOX_DIR":[{ "sandbox-switch": "ON", "mount-paths": [{ diff --git a/appdata-sandbox64.json b/appdata-sandbox64.json index 2a2541017803a144f9bf5ccb3272c5a928e93e5d..1167b4646cf8909c31d0030622c80bb7b82c134b 100644 --- a/appdata-sandbox64.json +++ b/appdata-sandbox64.json @@ -5,53 +5,8 @@ "sandbox-root" : "/mnt/sandbox/", "sandbox-ns-flags" : [ "net" ], "mount-paths" : [{ - "src-path" : "/system/lib", - "sandbox-path" : "/system/lib", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/platformsdk", - "sandbox-path" : "/system/lib64/platformsdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/ndk", - "sandbox-path" : "/system/lib64/ndk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/module", - "sandbox-path" : "/system/lib64/module", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/chipset-pub-sdk", - "sandbox-path" : "/system/lib64/chipset-pub-sdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/chipset-sdk", - "sandbox-path" : "/system/lib64/chipset-sdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/seccomp", - "sandbox-path" : "/system/lib64/seccomp", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/extensionability", - "sandbox-path" : "/system/lib64/extensionability", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/media", - "sandbox-path" : "/system/lib64/media", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib/ld-musl-aarch64.so.1", - "sandbox-path" : "/system/lib/ld-musl-aarch64.so.1", + "src-path" : "/system/lib64", + "sandbox-path" : "/system/lib64", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { @@ -95,53 +50,30 @@ "sandbox-root" : "/mnt/sandbox/com.ohos.render/", "sandbox-ns-flags" : [ "pid", "net" ], "mount-paths" : [{ - "src-path" : "/system/lib", - "sandbox-path" : "/system/lib", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - },{ - "src-path" : "/system/lib64/platformsdk", - "sandbox-path" : "/system/lib64/platformsdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/ndk", - "sandbox-path" : "/system/lib64/ndk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/module", - "sandbox-path" : "/system/lib64/module", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/chipset-pub-sdk", - "sandbox-path" : "/system/lib64/chipset-pub-sdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/chipset-sdk", - "sandbox-path" : "/system/lib64/chipset-sdk", - "sandbox-flags" : [ "bind", "rec" ], - "check-action-status": "false" - }, { - "src-path" : "/system/lib64/seccomp", - "sandbox-path" : "/system/lib64/seccomp", + "src-path" : "/system/lib64", + "sandbox-path" : "/system/lib64", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { - "src-path" : "/system/lib64/extensionability", - "sandbox-path" : "/system/lib64/extensionability", + "src-path" : "/vendor/lib64", + "sandbox-path" : "/vendor/lib64", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" - }, { - "src-path" : "/system/lib64/media", - "sandbox-path" : "/system/lib64/media", - "sandbox-flags" : [ "bind", "rec" ], + } + ], + "symbol-links" : [{ + "target-name" : "/system/lib64", + "link-name" : "/lib64", "check-action-status": "false" - }, { - "src-path" : "/system/lib/ld-musl-aarch64.so.1", - "sandbox-path" : "/system/lib/ld-musl-aarch64.so.1", + } + ] + }], + "__internal__.com.ohos.gpu" : [{ + "sandbox-root" : "/mnt/sandbox/com.ohos.render/", + "sandbox-ns-flags" : [ "pid", "net" ], + "mount-paths" : [{ + "src-path" : "/system/lib64", + "sandbox-path" : "/system/lib64", "sandbox-flags" : [ "bind", "rec" ], "check-action-status": "false" }, { @@ -156,13 +88,7 @@ "link-name" : "/lib64", "check-action-status": "false" } - ], - "flags-point" : [{ - "flags": "DLP_MANAGER", - "sandbox-root" : "/mnt/sandbox/com.ohos.render/", - "mount-paths" : [], - "symbol-links" : [{}] - }] + ] }] }] } diff --git a/appspawn.cfg b/appspawn.cfg index 768b92e863196ffec22115e1e8e44aae7bd65943..461c71b70a1a22c96e0cdbdad81d2b897613a825 100644 --- a/appspawn.cfg +++ b/appspawn.cfg @@ -1,18 +1,18 @@ { "jobs" : [{ - "name" : "service:nwebspawn", + "name" : "boot", "cmds" : [ "mkdir /mnt/sandbox", "mkdir /mnt/sandbox/com.ohos.render/ 0711 nwebspawn nwebspawn", - "mkdir /mnt/startup", - "mkdir /mnt/startup/appspawn 0700 root root", - "mkdir /mnt/startup/nwebspawn/ 0700 nwebspawn nwebspawn" + "mkdir /data/service/el1/startup/appspawn 0700 root root", + "mkdir /data/service/el1/startup/nwebspawn/ 0700 nwebspawn nwebspawn" ] }, { "name" : "init", "cmds" : [ "mkdir /dev/pids", + "mkdir /dev/pids/native", "mount cgroup none /dev/pids pids", "chown root appspawn /dev/pids", "chown root appspawn /dev/pids/tasks", @@ -35,6 +35,7 @@ "uid" : "root", "gid" : ["root"], "setuid" : true, + "cgroup" : true, "socket" : [{ "name" : "AppSpawn", "family" : "AF_LOCAL", @@ -60,9 +61,6 @@ "sandbox" : 0, "start-mode" : "boot", "secon" : "u:r:appspawn:s0", - "jobs" : { - "on-start" : "service:nwebspawn" - }, "bootevents" : "bootevent.appspawn.started" } ] diff --git a/appspawn.gni b/appspawn.gni index ae2da360d374aba84722902fefa125bde781c3c9..dd383ed49fe63772eb0c7d6e5482d51b1579108d 100644 --- a/appspawn.gni +++ b/appspawn.gni @@ -33,6 +33,8 @@ declare_args() { appspawn_mount_tmpshm = false appspawn_seccomp_privilege = false appspawn_support_prefork = true + appspawn_support_code_signature = true + appspawn_allow_internet_permission = false } if (!defined(global_parts_info) || diff --git a/appspawn_preload.json b/appspawn_preload.json index 0a15fe7f3c1ba84f0e12b388098be3e01d7c855c..1a985569db88412baf851aa942abe20a8731a334 100644 --- a/appspawn_preload.json +++ b/appspawn_preload.json @@ -74,16 +74,12 @@ "app.ability.contextconstant", "app.ability.contextConstant_napi", "app.ability.UIExtensionAbility", - "arkui.componentutils", - "arkui.modifier", - "arkui.node", "data.dataSharePredicates", "hiappevent", "hiviewdfx.hiappevent", "resourceManager", "settings", "multimodalInput.inputDevice", - "util.json", - "arkui.advanced.SubHeader" + "util.json" ] } diff --git a/appspawn_systemLib.json b/appspawn_systemLib.json new file mode 100644 index 0000000000000000000000000000000000000000..05e42a8fc65464b41c935d5ca88342d83ed542c8 --- /dev/null +++ b/appspawn_systemLib.json @@ -0,0 +1,4 @@ +{ + "systemLib" : [ + ] +} diff --git a/bundle.json b/bundle.json index bf616295586b72540424ca7349d191c6bd153043..2e91919ac8e4bfa2bb820a18ae14ed0f979b4c40 100644 --- a/bundle.json +++ b/bundle.json @@ -25,11 +25,14 @@ "appspawn_use_encaps", "appspawn_mount_tmpshm", "appspawn_seccomp_privilege", - "appspawn_support_prefork" + "appspawn_support_prefork", + "appspawn_support_code_signature", + "appspawn_allow_internet_permission" ], "rom": "296KB", "ram": "13125KB", "hisysevent_config": [ + "//base/startup/appspawn/hisysevent.yaml", "//base/startup/appspawn/startup_events.yaml" ], "deps": { @@ -69,14 +72,15 @@ "cJSON", "json", "faultloggerd", - "dlp_permission_service" + "dlp_permission_service", + "ffrt" ], - "third_party": [ + "third_party": [ "bounds_checking_function", "zlib", "selinux", "cJSON" - ] + ] }, "build": { "sub_component": [ diff --git a/common/appspawn_server.c b/common/appspawn_server.c index 68a3b1b13892bc19b867200bcea4ee69f1d3c42c..c59f93fa3453db3570049616fad8ff9213b66485 100644 --- a/common/appspawn_server.c +++ b/common/appspawn_server.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 20214 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -26,6 +26,7 @@ #include "appspawn_utils.h" #ifndef OHOS_LITE #include "appspawn_manager.h" +#include "ffrt_inner.h" #endif #define MAX_FORK_TIME (30 * 1000) // 30ms @@ -84,7 +85,6 @@ int AppSpawnChild(AppSpawnContent *content, AppSpawnClient *client) } APPSPAWN_LOGW("AppSpawnChild cold start fail %{public}u", client->id); } - StartAppspawnTrace("AppSpawnExecuteSpawningHook"); ret = AppSpawnExecuteSpawningHook(content, client); FinishAppspawnTrace(); @@ -121,6 +121,8 @@ int AppSpawnChild(AppSpawnContent *content, AppSpawnClient *client) static int CloneAppSpawn(void *arg) { APPSPAWN_CHECK(arg != NULL, return -1, "Invalid content for appspawn"); + APPSPAWN_LOGI("CloneNwebSpawn done."); + ffrt_child_init(); AppSpawnForkArg *forkArg = (AppSpawnForkArg *)arg; ProcessExit(AppSpawnChild(forkArg->content, forkArg->client)); return 0; diff --git a/common/appspawn_server.h b/common/appspawn_server.h index 7ccc93b1d1ffa25c8ac6e703d4f8aa9616aef815..76a299d918e4ba238c509a856e2a9497dde92358 100644 --- a/common/appspawn_server.h +++ b/common/appspawn_server.h @@ -56,6 +56,12 @@ typedef struct AppSpawnClient { uint32_t flags; // Save negotiated flags } AppSpawnClient; +typedef struct AppSpawnPreforkMsg { + uint32_t id; + uint32_t flags; // Save negotiated flags + uint32_t msgLen; +} AppSpawnPreforkMsg; + typedef struct AppSpawnContent { char *longProcName; uint32_t longProcNameLen; @@ -64,6 +70,7 @@ typedef struct AppSpawnContent { bool isLinux; int sandboxType; RunMode mode; + int signalFd; #ifndef OHOS_LITE int32_t preforkFd[2]; int32_t parentToChildFd[2]; diff --git a/etc/BUILD.gn b/etc/BUILD.gn index fdda0586c61d333eb987db6b320c83efb8a016a1..dddce63f76ca86119fb1b0a958057fee0e80b679 100644 --- a/etc/BUILD.gn +++ b/etc/BUILD.gn @@ -66,10 +66,17 @@ ohos_prebuilt_etc("appspawn_preload.json") { module_install_dir = "etc/appspawn" } +ohos_prebuilt_etc("appspawn_systemLib.json") { + source = "../appspawn_systemLib.json" + part_name = "${part_name}" + module_install_dir = "etc/appspawn" +} + group("etc_files") { deps = [ ":appdata-sandbox.json", ":appspawn_preload.json", + ":appspawn_systemLib.json", ] if (defined(appspawn_sandbox_new) && appspawn_sandbox_new) { deps += [ ":appdata-sandbox-nweb.json" ] diff --git a/hisysevent.yaml b/hisysevent.yaml new file mode 100644 index 0000000000000000000000000000000000000000..10df09ac4c3c8e1f24ba15ab58a54c1045032d8a --- /dev/null +++ b/hisysevent.yaml @@ -0,0 +1,39 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +domain: APPSPAWN + +SPAWN_CHILD_PROCESS_FAIL: + __BASE: {type: FAULT, level: CRITICAL, desc: Spawn Child Process Fail} + PROCESS_NAME: {type: STRING, desc: Process Name} + ERROR_CODE: {type: INT32, desc: Error Code} + SRC_PATH : {type: STRING, desc: Source Path For Mount Failed} + TARGET_PATH: {type: STRING, desc: Target Path For Mount Failed} + SPAWN_RESULT : {type: INT32, desc: Process Spawn Result} + +SPAWN_KEY_EVENT: + __BASE: {type: BEHAVIOR, level: CRITICAL, desc: Spawn Key Event Finish} + EVENT_NAME: {type: STRING, desc: Event Name} + +SPAWN_PROCESS_DURATION: + __BASE: {type: STATISTIC, level: CRITICAL, desc: Boot Process Duration} + MAXDURATION: {type: INT64, desc: Max Spawn Process Duration} + MINDURATION: {type: INT64, desc: Min Spawn Process Duration} + TOTALDURATION: {type: INT64, desc: Total Spawn Process Duration} + EVENTCOUNT: {type: INT64, desc: Total Spawn Process Count} + STAGE: {type: STRING, desc: Boot Stage Or BootFinished Stage} + +SPAWN_ABNORMAL_DURATION: + __BASE: {type: BEHAVIOR, level: CRITICAL, desc: Scene Duration} + SCENE_NAME: {type: STRING, desc: Scene Name} + DURATION: {type: INT64, desc: Scene Duration} \ No newline at end of file diff --git a/interfaces/innerkits/client/appspawn_client.c b/interfaces/innerkits/client/appspawn_client.c index 00707f50a5be7317393819b8acd1ceca4c781ce4..563b05699c9b95081262c3f68418f71f8d8a22dd 100644 --- a/interfaces/innerkits/client/appspawn_client.c +++ b/interfaces/innerkits/client/appspawn_client.c @@ -35,8 +35,14 @@ #include "parameter.h" #include "securec.h" +#define USER_LOCK_STATUS_SIZE 8 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; static AppSpawnReqMsgMgr *g_clientInstance[CLIENT_MAX] = {NULL}; +static pthread_mutex_t g_spawnListenMutex = PTHREAD_MUTEX_INITIALIZER; +static int g_spawnListenFd = 0; +static bool g_spawnListenStart = false; + +APPSPAWN_STATIC void SpawnListen(AppSpawnReqMsgMgr *reqMgr, const char *processName); static uint32_t GetDefaultTimeout(uint32_t def) { @@ -152,15 +158,28 @@ APPSPAWN_STATIC int UpdateSocketTimeout(uint32_t timeout, int socketFd) return ret; } -static int ReadMessage(int socketFd, uint32_t sendMsgId, uint8_t *buf, int len, AppSpawnResult *result) +static int ReadMessage(int socketFd, uint8_t *buf, int len, AppSpawnReqMsgNode *reqNode, AppSpawnResult *result) { + struct timespec readStart = { 0 }; + clock_gettime(CLOCK_MONOTONIC, &readStart); ssize_t rLen = TEMP_FAILURE_RETRY(read(socketFd, buf, len)); + if (rLen == -1 && errno == EAGAIN) { + struct timespec readEnd = { 0 }; + clock_gettime(CLOCK_MONOTONIC, &readEnd); + uint64_t diff = DiffTime(&readStart, &readEnd); + uint64_t timeout = reqNode->isAsan ? COLDRUN_READ_RETRY_TIME : NORMAL_READ_RETRY_TIME; + // If difftime is greater than timeout, it is considered that system hibernation or a time jump has occurred + if (diff > timeout) { + APPSPAWN_LOGW("Read message again from fd %{public}d, difftime %{public}" PRId64 " us", socketFd, diff); + rLen = TEMP_FAILURE_RETRY(read(socketFd, buf, len)); + } + } APPSPAWN_CHECK(rLen >= 0, return APPSPAWN_TIMEOUT, "Read message from fd %{public}d rLen %{public}zd errno: %{public}d", socketFd, rLen, errno); if ((size_t)rLen >= sizeof(AppSpawnResponseMsg)) { AppSpawnResponseMsg *msg = (AppSpawnResponseMsg *)(buf); - APPSPAWN_CHECK_ONLY_LOG(sendMsgId == msg->msgHdr.msgId, - "Invalid msg recvd %{public}u %{public}u", sendMsgId, msg->msgHdr.msgId); + APPSPAWN_CHECK_ONLY_LOG(reqNode->msg->msgId == msg->msgHdr.msgId, + "Invalid msg recvd %{public}u %{public}u", reqNode->msg->msgId, msg->msgHdr.msgId); return memcpy_s(result, sizeof(AppSpawnResult), &msg->result, sizeof(msg->result)); } return APPSPAWN_TIMEOUT; @@ -265,6 +284,11 @@ static int ClientSendMsg(AppSpawnReqMsgMgr *reqMgr, AppSpawnReqMsgNode *reqNode, continue; } } + if (reqNode->msg->msgType != MSG_OBSERVE_PROCESS_SIGNAL_STATUS) { + pthread_mutex_lock(&g_spawnListenMutex); + SpawnListen(reqMgr, reqNode->msg->processName); + pthread_mutex_unlock(&g_spawnListenMutex); + } if (isColdRun && reqMgr->timeout < ASAN_TIMEOUT) { UpdateSocketTimeout(ASAN_TIMEOUT, reqMgr->socketId); } @@ -274,8 +298,7 @@ static int ClientSendMsg(AppSpawnReqMsgMgr *reqMgr, AppSpawnReqMsgNode *reqNode, } int ret = HandleMsgSend(reqMgr, reqMgr->socketId, reqNode); if (ret == 0) { - ret = ReadMessage(reqMgr->socketId, reqNode->msg->msgId, - reqMgr->recvBlock.buffer, reqMgr->recvBlock.blockSize, result); + ret = ReadMessage(reqMgr->socketId, reqMgr->recvBlock.buffer, reqMgr->recvBlock.blockSize, reqNode, result); } if (ret == 0) { if (isColdRun && reqMgr->timeout < ASAN_TIMEOUT) { @@ -294,6 +317,35 @@ static int ClientSendMsg(AppSpawnReqMsgMgr *reqMgr, AppSpawnReqMsgNode *reqNode, return APPSPAWN_TIMEOUT; } +APPSPAWN_STATIC void SpawnListen(AppSpawnReqMsgMgr *reqMgr, const char *processName) +{ + AppSpawnClientType type = reqMgr->type; + if (g_spawnListenFd <= 0 || g_spawnListenStart) { + APPSPAWN_LOGV("Spawn Listen fail,fd:%{public}d,start:%{public}d", g_spawnListenFd, g_spawnListenStart); + return; + } + APPSPAWN_CHECK((type == CLIENT_FOR_APPSPAWN), return, "Invalid type"); + APPSPAWN_CHECK(processName != NULL, return, "Invalid process name"); + + APPSPAWN_LOGI("Spawn Listen start type:%{public}d,fd:%{public}d", type, g_spawnListenFd); + + AppSpawnReqMsgHandle reqHandle; + int ret = AppSpawnReqMsgCreate(MSG_OBSERVE_PROCESS_SIGNAL_STATUS, processName, &reqHandle); + APPSPAWN_CHECK(ret == 0, return, "Failed to create type:%{public}d req msg, ret = %{public}d", type, ret); + + ret = AppSpawnReqMsgAddFd(reqHandle, SPAWN_LISTEN_FD_NAME, g_spawnListenFd); + APPSPAWN_CHECK(ret == 0, AppSpawnReqMsgFree(reqHandle); + return, "Failed to add info message, ret=%{public}d", ret); + + AppSpawnResult result = {0}; + ret = ClientSendMsg(reqMgr, (AppSpawnReqMsgNode *)reqHandle, &result); + APPSPAWN_CHECK(ret == 0, return, "Send msg to type:%{public}d failed, ret=%{public}d", type, ret); + APPSPAWN_CHECK(result.result == 0, return, "Appspawn failed to handle message, result=%{public}d", result.result); + + g_spawnListenStart = true; + APPSPAWN_LOGI("Spawn Listen client type[%{public}d] Send fd[%{public}d] success", type, g_spawnListenFd); +} + int AppSpawnClientInit(const char *serviceName, AppSpawnClientHandle *handle) { APPSPAWN_CHECK(serviceName != NULL, return APPSPAWN_ARG_INVALID, "Invalid service name"); @@ -358,3 +410,56 @@ int AppSpawnClientSendMsg(AppSpawnClientHandle handle, AppSpawnReqMsgHandle reqH AppSpawnReqMsgFree(reqHandle); return ret; } + +int AppSpawnClientSendUserLockStatus(uint32_t userId, bool isLocked) +{ + char lockstatus[USER_LOCK_STATUS_SIZE] = {0}; + int ret = snprintf_s(lockstatus, USER_LOCK_STATUS_SIZE, USER_LOCK_STATUS_SIZE - 1, "%u:%d", userId, isLocked); + APPSPAWN_CHECK(ret > 0, return ret, "Failed to build lockstatus req msg, ret = %{public}d", ret); + APPSPAWN_LOGI("Send lockstatus msg to appspawn %{public}s", lockstatus); + + AppSpawnReqMsgHandle reqHandle; + ret = AppSpawnReqMsgCreate(MSG_LOCK_STATUS, "storage_manager", &reqHandle); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to create appspawn req msg, ret = %{public}d", ret); + + ret = AppSpawnReqMsgAddStringInfo(reqHandle, "lockstatus", lockstatus); + APPSPAWN_CHECK(ret == 0, AppSpawnReqMsgFree(reqHandle); + return ret, "Failed to add lockstatus message, ret=%{public}d", ret); + + AppSpawnClientHandle clientHandle; + ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle); + APPSPAWN_CHECK(ret == 0, AppSpawnReqMsgFree(reqHandle); + return ret, "Appspawn client failed to init, ret=%{public}d", ret); + + AppSpawnResult result = {0}; + ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); + AppSpawnClientDestroy(clientHandle); + APPSPAWN_CHECK(ret == 0, return ret, "Send msg to appspawn failed, ret=%{public}d", ret); + + if (result.result != 0) { + APPSPAWN_LOGE("Appspawn failed to handle message, result=%{public}d", result.result); + return result.result; + } + APPSPAWN_LOGI("Send lockstatus msg to appspawn success"); + return 0; +} + +int SpawnListenFdSet(int fd) +{ + if (fd <= 0) { + APPSPAWN_LOGE("Spawn Listen fd set[%{public}d] failed", fd); + return APPSPAWN_ARG_INVALID; + } + g_spawnListenFd = fd; + APPSPAWN_LOGI("Spawn Listen fd set[%{public}d] success", fd); + return 0; +} + +int SpawnListenCloseSet(void) +{ + pthread_mutex_lock(&g_spawnListenMutex); + g_spawnListenStart = false; + pthread_mutex_unlock(&g_spawnListenMutex); + APPSPAWN_LOGI("Spawn Listen close set success"); + return 0; +} \ No newline at end of file diff --git a/interfaces/innerkits/client/appspawn_client.h b/interfaces/innerkits/client/appspawn_client.h index 784065bb8f53b12f051cef9fa386ba92c39617c0..22f3b9076090056dbef4e6a5502e7814d53bd0ba 100644 --- a/interfaces/innerkits/client/appspawn_client.h +++ b/interfaces/innerkits/client/appspawn_client.h @@ -37,6 +37,9 @@ extern "C" { #define RETRY_TIME (200 * 1000) // 200 * 1000 wait 200ms CONNECT_RETRY_DELAY = 200 * 1000 #define MAX_RETRY_SEND_COUNT 2 // 2 max retry count CONNECT_RETRY_MAX_TIMES = 2; +#define NORMAL_READ_RETRY_TIME (3 * 1000 * 1000 + 500 * 1000) // 3.5s, Exceed WAIT_CHILD_RESPONSE_TIMEOUT by 0.5s +#define COLDRUN_READ_RETRY_TIME (5 * 1000 * 1000 + 500 * 1000) // 5.5s, Exceed COLD_CHILD_RESPONSE_TIMEOUT by 0.5s + // only used for ExternalFileManager.hap #define GID_FILE_ACCESS 1006 #define GID_USER_DATA_RW 1008 diff --git a/interfaces/innerkits/client/libappspawn_client.versionscript b/interfaces/innerkits/client/libappspawn_client.versionscript index 0863f5417c5880beb0d8f61e3381e650399e3435..dce211fcb29f8b48607e69698d9db222971bc7c2 100644 --- a/interfaces/innerkits/client/libappspawn_client.versionscript +++ b/interfaces/innerkits/client/libappspawn_client.versionscript @@ -33,9 +33,12 @@ AppSpawnReqMsgAddStringInfo; AppSpawnTerminateMsgCreate; AppSpawnClientAddPermission; + AppSpawnClientSendUserLockStatus; GetPermissionIndex; GetMaxPermissionIndex; GetPermissionByIndex; + SpawnListenFdSet; + SpawnListenCloseSet; local: *; }; diff --git a/interfaces/innerkits/hnp/src/hnp_api.c b/interfaces/innerkits/hnp/src/hnp_api.c index 2f3032341a687c2de6ba05976cf119796e5b48d4..62b4245a59ab6d7e68a24820e3ac903c53174c34 100644 --- a/interfaces/innerkits/hnp/src/hnp_api.c +++ b/interfaces/innerkits/hnp/src/hnp_api.c @@ -164,11 +164,6 @@ int NativeInstallHnp(const char *userId, const char *hnpRootPath, const HapInfo char *apcEnv[MAX_ENV_NUM] = {0}; int index = 0; - if (!IsDeveloperModeOpen()) { - HNPAPI_LOG("\r\n [HNP API] native package install not in developer mode"); - return HNP_API_NOT_IN_DEVELOPER_MODE; - } - if ((userId == NULL) || (hnpRootPath == NULL) || (hapInfo == NULL)) { return HNP_API_ERRNO_PARAM_INVALID; } @@ -207,11 +202,6 @@ int NativeUnInstallHnp(const char *userId, const char *packageName) char *apcEnv[MAX_ENV_NUM] = {0}; int index = 0; - if (!IsDeveloperModeOpen()) { - HNPAPI_LOG("\r\n [HNP API] native package uninstall not in developer mode"); - return HNP_API_NOT_IN_DEVELOPER_MODE; - } - if ((userId == NULL) || (packageName == NULL)) { return HNP_API_ERRNO_PARAM_INVALID; } diff --git a/interfaces/innerkits/include/appspawn.h b/interfaces/innerkits/include/appspawn.h index c75504bc4babbdce6724152c61e0fa52de7b8194..1abb96d70dc3ef25c88f46884ef5a90ea1e85469 100644 --- a/interfaces/innerkits/include/appspawn.h +++ b/interfaces/innerkits/include/appspawn.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -97,6 +98,15 @@ int AppSpawnClientDestroy(AppSpawnClientHandle handle); */ int AppSpawnClientSendMsg(AppSpawnClientHandle handle, AppSpawnReqMsgHandle reqHandle, AppSpawnResult *result); +/** + * @brief send client user lock status request + * + * @param userId user id + * @param isLocked lock status + * @return if succeed return 0,else return other value + */ +int AppSpawnClientSendUserLockStatus(uint32_t userId, bool isLocked); + typedef enum { MSG_APP_SPAWN = 0, MSG_GET_RENDER_TERMINATION_STATUS, @@ -107,6 +117,9 @@ typedef enum { MSG_UPDATE_MOUNT_POINTS, MSG_RESTART_SPAWNER, MSG_DEVICE_DEBUG, + MSG_UNINSTALL_DEBUG_HAP, + MSG_LOCK_STATUS, + MSG_OBSERVE_PROCESS_SIGNAL_STATUS, MAX_TYPE_INVALID } AppSpawnMsgType; @@ -183,6 +196,8 @@ typedef enum { APP_FLAGS_ISOLATED_NETWORK, APP_FLAGS_ISOLATED_DATAGROUP, APP_FLAGS_TEMP_JIT = 28, + APP_FLAGS_PRE_INSTALLED_HAP = 29, + APP_FLAGS_GET_ALL_PROCESSES = 30, MAX_FLAGS_INDEX = 63, } AppFlagsIndex; @@ -277,6 +292,8 @@ int AppSpawnClientAddPermission(AppSpawnClientHandle handle, AppSpawnReqMsgHandl #define MSG_EXT_NAME_MAX_CHILD_PROCCESS_MAX "MaxChildProcess" #define MSG_EXT_NAME_APP_FD "AppFd" #define MSG_EXT_NAME_JIT_PERMISSIONS "JITPermissions" +#define MSG_EXT_NAME_USERID "uid" +#define MSG_EXT_NAME_EXTENSION_TYPE "ExtensionType" int AppSpawnReqMsgAddExtInfo(AppSpawnReqMsgHandle reqHandle, const char *name, const uint8_t *value, uint32_t valueLen); @@ -326,6 +343,21 @@ int32_t GetMaxPermissionIndex(AppSpawnClientHandle handle); */ const char *GetPermissionByIndex(AppSpawnClientHandle handle, int32_t index); +/** + * @brief set up a pipe fd to capture the exit reason of a child process + * + * @param fd fd for write signal info + * @return if succeed return 0,else return other value + */ +int SpawnListenFdSet(int fd); + +/** + * @brief close the listener for child process exit + * + * @return if succeed return 0,else return other value + */ +int SpawnListenCloseSet(void); + #ifdef __cplusplus } #endif diff --git a/interfaces/innerkits/permission/appspawn_mount_permission.c b/interfaces/innerkits/permission/appspawn_mount_permission.c index 1149829a47785e6e2263fe3dd3e545df500d4422..b2c75fe6ca6548c2c6bdd14fefbad3f03b9e45ce 100755 --- a/interfaces/innerkits/permission/appspawn_mount_permission.c +++ b/interfaces/innerkits/permission/appspawn_mount_permission.c @@ -106,7 +106,7 @@ static int LoadPermissionConfig(PermissionManager *mgr) { int ret = ParseJsonConfig("etc/sandbox", mgr->type == CLIENT_FOR_APPSPAWN ? APP_SANDBOX_FILE_NAME : WEB_SANDBOX_FILE_NAME, ParseAppSandboxConfig, mgr); - APPSPAWN_CHECK(ret == 0, return ret, "Load sandbox fail %{public}d", ret); + APPSPAWN_CHECK(ret == 0, return 0, "Load sandbox fail %{public}d", ret); mgr->maxPermissionIndex = PermissionRenumber(&mgr->permissionQueue); return 0; } diff --git a/modules/ace_adapter/ace_adapter.cpp b/modules/ace_adapter/ace_adapter.cpp index 8aaa6468c7c0e335a5fae6ea7663ddb6accc34b0..464d7ad80b39b8f53151892cc815ab4b0c96b8ef 100644 --- a/modules/ace_adapter/ace_adapter.cpp +++ b/modules/ace_adapter/ace_adapter.cpp @@ -43,6 +43,7 @@ using namespace OHOS::AppSpawn; using namespace OHOS::Global; +#define SYSTEMLIB_JSON "/appspawn_systemLib.json" #ifdef ASAN_DETECTOR static const bool DEFAULT_PRELOAD_VALUE = false; #else @@ -94,6 +95,13 @@ static void PreloadModule(void) return; } + options.lang = OHOS::AbilityRuntime::Runtime::Language::STS; + auto stsRuntime = OHOS::AbilityRuntime::Runtime::Create(options); + if (!stsRuntime) { + APPSPAWN_LOGE("LoadExtendLib: Failed to create sts runtime"); + return; + } + ParseJsonContext context = {}; (void)ParseJsonConfig("etc/appspawn", PRELOAD_JSON_CONFIG.c_str(), GetModuleSet, &context); for (std::string moduleName : context.modules) { @@ -130,6 +138,22 @@ static void LoadExtendLib(void) APPSPAWN_LOGI("LoadExtendLib: End preload JS VM"); } +APPSPAWN_STATIC void PreloadCJLibs(void) +{ + const char* cjEnvLibName = "libcj_environment.z.so"; + const char* cjEnvInitName = "OHOS_InitSpawnEnv"; + void* cjEnvLib = dlopen(cjEnvLibName, RTLD_NOW | RTLD_LOCAL); + APPSPAWN_CHECK(cjEnvLib != nullptr, return, "Failed to dlopen %{public}s, [%{public}s]", cjEnvLibName, dlerror()); + auto symbol = dlsym(cjEnvLib, cjEnvInitName); + if (!symbol) { + dlclose(cjEnvLib); + APPSPAWN_LOGE("Failed to dlsym %{public}s, [%{public}s]", cjEnvInitName, dlerror()); + return; + } + auto initSpawnEnv = reinterpret_cast(symbol); + initSpawnEnv(); +} + APPSPAWN_STATIC void LoadExtendCJLib(void) { const char *acelibdir = OHOS::Ace::AceForwardCompatibility::GetAceLibName(); @@ -137,6 +161,10 @@ APPSPAWN_STATIC void LoadExtendCJLib(void) void *aceAbilityLib = dlopen(acelibdir, RTLD_NOW | RTLD_LOCAL); APPSPAWN_CHECK(aceAbilityLib != nullptr, return, "Fail to dlopen %{public}s, [%{public}s]", acelibdir, dlerror()); APPSPAWN_LOGI("LoadExtendLib: Success to dlopen %{public}s", acelibdir); + + OHOS::AppExecFwk::MainThread::PreloadExtensionPlugin(); + + PreloadCJLibs(); } APPSPAWN_STATIC int BuildFdInfoMap(const AppSpawnMsgNode *message, std::map &fdMap, int isColdRun) @@ -240,7 +268,6 @@ APPSPAWN_STATIC int RunChildByRenderCmd(const AppSpawnMgr *content, const AppSpa static int RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) { - EnableCache(); APPSPAWN_CHECK(client != NULL && content != NULL, return -1, "Invalid client"); AppSpawningCtx *property = reinterpret_cast(client); int ret = 0; @@ -267,8 +294,42 @@ APPSPAWN_STATIC int PreLoadAppSpawn(AppSpawnMgr *content) return 0; } +APPSPAWN_STATIC int DoDlopenLibs(const cJSON *root, ParseJsonContext *context) +{ + cJSON *systemLibs = cJSON_GetObjectItemCaseSensitive(root, "systemLib"); + if (systemLibs == nullptr) { + return 0; + } + + uint32_t libsCount = (uint32_t)cJSON_GetArraySize(systemLibs); + for (uint32_t i = 0; i < libsCount; ++i) { + const char *libName = cJSON_GetStringValue(cJSON_GetArrayItem(systemLibs, i)); + char reaLibPath[PATH_MAX] = {0}; + if (libName == nullptr || realpath(libName, reaLibPath) == nullptr) { + continue; + } + APPSPAWN_LOGV("reaLibPath %{public}s", reaLibPath); + void *lib = dlopen(reaLibPath, RTLD_LAZY); + if (lib == nullptr) { + APPSPAWN_LOGE("FAILED to dlopen %{public}s %{public}s", libName, dlerror()); + } + } + return 0; +} + +APPSPAWN_STATIC int DlopenAppSpawn(AppSpawnMgr *content) +{ + if (!IsAppSpawnMode(content)) { + return 0; + } + + (void)ParseJsonConfig("etc/appspawn", SYSTEMLIB_JSON, DoDlopenLibs, nullptr); + return 0; +} + MODULE_CONSTRUCTOR(void) { APPSPAWN_LOGV("Load ace module ..."); AddPreloadHook(HOOK_PRIO_HIGHEST, PreLoadAppSpawn); + AddPreloadHook(HOOK_PRIO_HIGHEST, DlopenAppSpawn); } diff --git a/modules/asan/asan_detector.c b/modules/asan/asan_detector.c index 15e4c8360cfe80cb0b5b5308838977ef45b82c52..901bc27ae41c9c38dc704ec75638d6faea40db9f 100644 --- a/modules/asan/asan_detector.c +++ b/modules/asan/asan_detector.c @@ -86,15 +86,9 @@ static int SetAsanEnabledEnv(const AppSpawnMgr *content, const AppSpawningCtx *p static void SetGwpAsanEnabled(const AppSpawnMgr *content, const AppSpawningCtx *property) { - if (!(CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE) || - CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_NORMAL))) { - return; - } - if (IsDeveloperModeOn(property)) { - APPSPAWN_LOGV("SetGwpAsanEnabled with flags: %{public}d", - CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE)); - may_init_gwp_asan(CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE)); - } + int enforce = CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE); + APPSPAWN_LOGV("SetGwpAsanEnabled with flags: %{public}d", enforce); + may_init_gwp_asan(enforce); } #ifdef ASAN_DETECTOR diff --git a/modules/common/BUILD.gn b/modules/common/BUILD.gn index 7e678381ee77bb6cd431def2b3fdb9e30091579c..a8441284e6a382e00e7405c7acd3995d671530cf 100644 --- a/modules/common/BUILD.gn +++ b/modules/common/BUILD.gn @@ -81,6 +81,16 @@ ohos_shared_library("appspawn_common") { defines += [ "APPSPAWN_SANDBOX_NEW" ] } + if (appspawn_allow_internet_permission) { + defines += [ "APPSPAWN_ALLOW_INTERNET_PERMISSION" ] + } + if (appspawn_report_event) { + defines += [ "APPSPAWN_HISYSEVENT" ] + external_deps += [ "hisysevent:libhisysevent" ] + include_dirs += [ "${appspawn_path}/modules/sysevent" ] + sources += [ "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp" ] + } + subsystem_name = "${subsystem_name}" part_name = "${part_name}" install_enable = true diff --git a/modules/common/appspawn_adapter.cpp b/modules/common/appspawn_adapter.cpp index 9ada875f45537b9e7967e62c016851438cf2f397..e53b3af4a4762f2999a10fe4f869772c76ac45e6 100644 --- a/modules/common/appspawn_adapter.cpp +++ b/modules/common/appspawn_adapter.cpp @@ -82,6 +82,33 @@ int SetSelinuxConNweb(const AppSpawnMgr *content, const AppSpawningCtx *property return 0; } +#ifdef WITH_SELINUX +void SetHapDomainInfo(HapDomainInfo *hapDomainInfo, const AppSpawningCtx *property, + AppSpawnMsgDomainInfo *msgDomainInfo, AppDacInfo *appInfo) +{ + hapDomainInfo->apl = msgDomainInfo->apl; + hapDomainInfo->packageName = GetBundleName(property); + hapDomainInfo->hapFlags = msgDomainInfo->hapFlags; + // The value of 0 is invalid. Its purpose is to initialize. + hapDomainInfo->uid = appInfo == nullptr ? 0 : appInfo->uid; + if (CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE)) { + hapDomainInfo->hapFlags |= SELINUX_HAP_DEBUGGABLE; + } + if (CheckAppMsgFlagsSet(property, APP_FLAGS_DLP_MANAGER)) { + hapDomainInfo->hapFlags |= SELINUX_HAP_DLP; + } + if (CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX)) { + hapDomainInfo->hapFlags |= SELINUX_HAP_INPUT_ISOLATE; + } + if (CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SELINUX_LABEL)) { + uint32_t len = 0; + std::string extensionType = + reinterpret_cast(GetAppPropertyExt(property, MSG_EXT_NAME_EXTENSION_TYPE, &len)); + hapDomainInfo->extensionType = extensionType; + } +} +#endif + int SetSelinuxCon(const AppSpawnMgr *content, const AppSpawningCtx *property) { #ifdef WITH_SELINUX @@ -106,20 +133,10 @@ int SetSelinuxCon(const AppSpawnMgr *content, const AppSpawningCtx *property) reinterpret_cast(GetAppProperty(property, TLV_DOMAIN_INFO)); APPSPAWN_CHECK(msgDomainInfo != NULL, return APPSPAWN_TLV_NONE, "No domain info in req form %{public}s", GetProcessName(property)); + AppDacInfo *appInfo = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); HapContext hapContext; HapDomainInfo hapDomainInfo; - hapDomainInfo.apl = msgDomainInfo->apl; - hapDomainInfo.packageName = GetBundleName(property); - hapDomainInfo.hapFlags = msgDomainInfo->hapFlags; - if (CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE)) { - hapDomainInfo.hapFlags |= SELINUX_HAP_DEBUGGABLE; - } - if (CheckAppMsgFlagsSet(property, APP_FLAGS_DLP_MANAGER)) { - hapDomainInfo.hapFlags |= SELINUX_HAP_DLP; - } - if (CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX)) { - hapDomainInfo.hapFlags |= SELINUX_HAP_INPUT_ISOLATE; - } + SetHapDomainInfo(&hapDomainInfo, property, msgDomainInfo, appInfo); int32_t ret = hapContext.HapDomainSetcontext(hapDomainInfo); if (CheckAppMsgFlagsSet(property, APP_FLAGS_ASANENABLED)) { ret = 0; @@ -175,25 +192,23 @@ int SetSeccompFilter(const AppSpawnMgr *content, const AppSpawningCtx *property) #ifdef SECCOMP_PRIVILEGE if (IsDeveloperModeOpen()) { - static GetPermissionFunc getPermissionFuncPtr = nullptr; - if (getPermissionFuncPtr == nullptr) { - getPermissionFuncPtr = reinterpret_cast(dlsym(nullptr, GET_PERMISSION_INDEX)); - if (getPermissionFuncPtr == nullptr) { - APPSPAWN_LOGE("Failed to dlsym get permission errno is %{public}d", errno); - return -EINVAL; - } - } - int32_t index = getPermissionFuncPtr(nullptr, GET_ALL_PROCESSES); - if (CheckAppPermissionFlagSet(property, static_cast(index)) != 0) { + // Enable high permission seccomp policy for hishell in developer mode. + if (CheckAppMsgFlagsSet(property, APP_FLAGS_GET_ALL_PROCESSES) != 0) { appName = APP_PRIVILEGE; } } #endif - if (CheckAppSpawnMsgFlag(property->message, TLV_MSG_FLAGS, APP_FLAGS_ISOLATED_SANDBOX) != 0) { + // Set seccomp policy for input method security mode. + if (CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX) != 0) { appName = IMF_EXTENTOIN_NAME; } + // Set seccomp policy for atomic service process. + if (CheckAppMsgFlagsSet(property, APP_FLAGS_ATOMIC_SERVICE) != 0) { + appName = APP_ATOMIC; + } + if (!SetSeccompPolicyWithName(type, appName)) { APPSPAWN_LOGE("Failed to set %{public}s seccomp filter and exit %{public}d", appName, errno); return -EINVAL; @@ -211,7 +226,9 @@ int SetInternetPermission(const AppSpawningCtx *property) "No tlv internet permission info in req form %{public}s", GetProcessName(property)); APPSPAWN_LOGV("Set internet permission %{public}d %{public}d", info->setAllowInternet, info->allowInternet); if (info->setAllowInternet == 1 && info->allowInternet == 0) { +#ifndef APPSPAWN_ALLOW_INTERNET_PERMISSION DisallowInternet(); +#endif } return 0; } diff --git a/modules/common/appspawn_common.c b/modules/common/appspawn_common.c index b5a9f00925ce96d9ef58e2e502646fa8a657a79b..6ce56b278bdf850bffdb602b9da410848a4ed464 100644 --- a/modules/common/appspawn_common.c +++ b/modules/common/appspawn_common.c @@ -59,9 +59,11 @@ #define PROVISION_TYPE_DEBUG "debug" #define DEVICE_NULL_STR "/dev/null" +#define PROCESS_START_TIME_ENV "PROCESS_START_TIME" #define BITLEN32 32 #define PID_NS_INIT_UID 100000 // reserved for pid_ns_init process, avoid app, render proc, etc. #define PID_NS_INIT_GID 100000 +#define PREINSTALLED_HAP_FLAG 0x01 // hapFlags 0x01: SELINUX_HAP_RESTORECON_PREINSTALLED_APP in selinux static int SetProcessName(const AppSpawnMgr *content, const AppSpawningCtx *property) { @@ -226,6 +228,12 @@ static int SetXpmConfig(const AppSpawnMgr *content, const AppSpawningCtx *proper static int SetUidGid(const AppSpawnMgr *content, const AppSpawningCtx *property) { + if (IsAppSpawnMode(content)) { + struct sched_param param = { 0 }; + param.sched_priority = 0; + int ret = sched_setscheduler(0, SCHED_OTHER, ¶m); + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "UpdateSchedPrio failed ret: %{public}d, %{public}d", ret, errno); + } AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO); APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE, "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, GetProcessName(property)); @@ -353,6 +361,21 @@ static int32_t WaitForDebugger(const AppSpawningCtx *property) return 0; } +static int SpawnSetPreInstalledFlag(AppSpawningCtx *property) +{ + AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetAppProperty(property, TLV_DOMAIN_INFO); + APPSPAWN_CHECK(msgDomainInfo != NULL, return APPSPAWN_TLV_NONE, "No domain info in req from %{public}s", + GetProcessName(property)); + if ((msgDomainInfo->hapFlags & PREINSTALLED_HAP_FLAG) != 0) { + int ret = SetAppSpawnMsgFlag(property->message, TLV_MSG_FLAGS, APP_FLAGS_PRE_INSTALLED_HAP); + if (ret != 0) { + APPSPAWN_LOGE("Set appspawn msg flag failed"); + return ret; + } + } + return 0; +} + static int SpawnInitSpawningEnv(AppSpawnMgr *content, AppSpawningCtx *property) { APPSPAWN_LOGV("Spawning: clear env"); @@ -365,6 +388,9 @@ static int SpawnInitSpawningEnv(AppSpawnMgr *content, AppSpawningCtx *property) ret = SetAppAccessToken(content, property); APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); + + ret = SpawnSetPreInstalledFlag(property); + APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); return 0; } @@ -376,9 +402,15 @@ static int SpawnSetAppEnv(AppSpawnMgr *content, AppSpawningCtx *property) return 0; } -static int SpawnSetIntPermission(AppSpawnMgr *content, AppSpawningCtx *property) +static int SpawnEnableCache(AppSpawnMgr *content, AppSpawningCtx *property) { - APPSPAWN_LOGV("Spawning: set Internet Permission for app process"); + APPSPAWN_LOGV("Spawning: enable cache for app process"); + // enable cache for app process + mallopt(M_OHOS_CONFIG, M_TCACHE_PERFORMANCE_MODE); + mallopt(M_OHOS_CONFIG, M_ENABLE_OPT_TCACHE); + mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_ENABLE); + mallopt(M_DELAYED_FREE, M_DELAYED_FREE_ENABLE); + int ret = SetInternetPermission(property); APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); return ret; @@ -534,6 +566,20 @@ APPSPAWN_STATIC int SetFdEnv(AppSpawnMgr *content, AppSpawningCtx *property) return 0; } +APPSPAWN_STATIC int RecordStartTime(AppSpawnMgr *content, AppSpawningCtx *property) +{ + struct timespec ts; + int ret = clock_gettime(CLOCK_MONOTONIC, &ts); + APPSPAWN_CHECK(ret == 0, return 0, "clock_gettime failed %{public}d,%{public}d", ret, errno); + long long startTime = (ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000); + char timeChar[32]; + ret = snprintf_s(timeChar, sizeof(timeChar), sizeof(timeChar) - 1, "%lld", startTime); + APPSPAWN_CHECK(ret > 0, return 0, "failed to snprintf_s %{public}d,%{public}d", ret, errno); + ret = setenv(PROCESS_START_TIME_ENV, timeChar, 1); + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "set env failed %{public}d,%{public}d", ret, errno); + return 0; +} + MODULE_CONSTRUCTOR(void) { APPSPAWN_LOGV("Load common module ..."); @@ -543,9 +589,10 @@ MODULE_CONSTRUCTOR(void) AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_HIGHEST, SpawnGetSpawningFlag); AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SpawnInitSpawningEnv); AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON + 1, SpawnSetAppEnv); - AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_HIGHEST, SpawnSetIntPermission); + AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_HIGHEST, SpawnEnableCache); AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_PROPERTY, SpawnSetProperties); AddAppSpawnHook(STAGE_CHILD_POST_RELY, HOOK_PRIO_HIGHEST, SpawnComplete); AddAppSpawnHook(STAGE_PARENT_POST_FORK, HOOK_PRIO_HIGHEST, CloseFdArgs); AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SetFdEnv); + AddAppSpawnHook(STAGE_CHILD_PRE_RUN, HOOK_PRIO_HIGHEST, RecordStartTime); } diff --git a/modules/common/appspawn_encaps.c b/modules/common/appspawn_encaps.c index 6581d53bf3c4b7c6ee15dc51b293f00a2df6006a..9337ce167cc978803e81e3545e9148531746d786 100644 --- a/modules/common/appspawn_encaps.c +++ b/modules/common/appspawn_encaps.c @@ -67,7 +67,7 @@ static int WriteEncapsInfo(int fd, AppSpawnEncapsBaseType encapsType, const char int ret = 0; switch (encapsType) { - case ENCAPS_MAX_TYPE_MODE: + case ENCAPS_PROC_TYPE_MODE: ret = ioctl(fd, SET_ENCAPS_PROC_TYPE_CMD, &flag); break; case ENCAPS_PERMISSION_TYPE_MODE: @@ -85,7 +85,7 @@ static int WriteEncapsInfo(int fd, AppSpawnEncapsBaseType encapsType, const char APPSPAWN_STATIC int EnableEncapsForProc(int encapsFileFd) { - uint32_t flag = OH_PROC_APP; + uint32_t flag = OH_PROC_HAP; return WriteEncapsInfo(encapsFileFd, ENCAPS_PROC_TYPE_MODE, OH_ENCAPS_DEFAULT_STR, flag); } @@ -111,13 +111,16 @@ static uint32_t SpawnGetMaxPids(AppSpawnMgr *content, AppSpawningCtx *property) /* set ohos.encaps.fork.count to encaps */ static int SpawnSetMaxPids(AppSpawnMgr *content, AppSpawningCtx *property, cJSON *encaps) { - uint32_t maxPidCount = SpawnGetMaxPids(content, property); + uint32_t maxPidCount = 0; + if (GetAppSpawnMsgType(property) != MSG_SPAWN_NATIVE_PROCESS) { + maxPidCount = SpawnGetMaxPids(content, property); + } if (maxPidCount == 0 || maxPidCount > OH_APP_MAX_PIDS_NUM) { APPSPAWN_LOGV("Don't need to set pid max count. Use default pid max"); return APPSPAWN_PIDMGR_DEFAULT_PID_MAX; } - if (cJSON_AddNumberToObject(encaps, APP_OHOS_ENCAPS_COUNT_KEY, maxPidCount) == NULL) { + if (cJSON_AddNumberToObject(encaps, APP_OHOS_ENCAPS_FORK_KEY, maxPidCount) == NULL) { APPSPAWN_LOGV("Add number to object failed.(ignore)"); return APPSPAWN_PIDMGR_DEFAULT_PID_MAX; } @@ -155,10 +158,10 @@ static int AddJITPermissionToEncaps(cJSON *extInfoJson, cJSON *encaps, uint32_t return APPSPAWN_ARG_INVALID; } - // If permissionName is obtained, it needs to be written in the format of ["permissionName: "true""] in the encaps + // If permissionName is obtained, it needs to be written in the format of ["permissionName: 1"] in the encaps for (int i = 0; i < count; i++) { char *permissionName = cJSON_GetStringValue(cJSON_GetArrayItem(permissions, i)); - if (cJSON_AddStringToObject(encaps, permissionName, "true") == NULL) { + if (cJSON_AddNumberToObject(encaps, permissionName, 1) == NULL) { APPSPAWN_LOGV("Add permission to object failed.(ignore)"); return APPSPAWN_ERROR_UTILS_ADD_JSON_FAIL; } @@ -184,7 +187,7 @@ static int SpawnSetJITPermissions(AppSpawnMgr *content, AppSpawningCtx *property return ret; } -static int AddMembersToEncaps(AppSpawnMgr *content, AppSpawningCtx *property, CJSON *encaps) +static int AddMembersToEncaps(AppSpawnMgr *content, AppSpawningCtx *property, cJSON *encaps) { uint32_t encapsPermissionCount = 0; // need set ohos.encaps.count to encaps firstly @@ -266,8 +269,8 @@ APPSPAWN_STATIC int SpawnSetEncapsPermissions(AppSpawnMgr *content, AppSpawningC return APPSPAWN_ARG_INVALID; } - // The trustlist is used to control not appspawn - if (!IsAppSpawnMode(content)) { + // The trustlist is used to control not appspawn or nativespawn + if (!(IsAppSpawnMode(content) || IsNativeSpawnMode(content))) { return 0; } @@ -278,12 +281,14 @@ APPSPAWN_STATIC int SpawnSetEncapsPermissions(AppSpawnMgr *content, AppSpawningC int ret = EnableEncapsForProc(encapsFileFd); if (ret != 0) { + close(encapsFileFd); return 0; // Can't enable encaps ability } char *encapsInfoStr = NULL; ret = SpawnBuildEncaps(content, property, &encapsInfoStr); if (ret != 0) { + close(encapsFileFd); APPSPAWN_LOGW("Build encaps object failed, ret: %{public}d", ret); return 0; // Can't set permission encpas ability } diff --git a/modules/common/appspawn_namespace.c b/modules/common/appspawn_namespace.c index 8122410fee0cb3f3690732b197a201110b930bca..5f0870234322a2472e0c10063641203f17a2ade8 100644 --- a/modules/common/appspawn_namespace.c +++ b/modules/common/appspawn_namespace.c @@ -32,7 +32,7 @@ #define PID_NS_INIT_UID 100000 // reserved for pid_ns_init process, avoid app, render proc, etc. #define PID_NS_INIT_GID 100000 -typedef struct TagAppSpawnNamespace { +typedef struct { AppSpawnExtData extData; int nsSelfPidFd; // ns pid fd of appspawn int nsInitPidFd; // ns pid fd of pid_ns_init diff --git a/modules/module_engine/include/appspawn_hook.h b/modules/module_engine/include/appspawn_hook.h index f8df0b10e48fc329c0f84a06679a65ca51edc3cc..8b59bc7463c80482437a3df40c279fb8065afba9 100644 --- a/modules/module_engine/include/appspawn_hook.h +++ b/modules/module_engine/include/appspawn_hook.h @@ -56,16 +56,18 @@ typedef struct TagAppSpawnExtData { typedef enum TagAppSpawnHookStage { // 服务状态处理 STAGE_SERVER_PRELOAD = 10, + STAGE_SERVER_LOCK, STAGE_SERVER_EXIT, // 应用状态处理 STAGE_SERVER_APP_ADD, STAGE_SERVER_APP_DIED, + STAGE_SERVER_APP_UMOUNT, // run before fork STAGE_PARENT_PRE_FORK = 20, STAGE_PARENT_POST_FORK = 21, STAGE_PARENT_PRE_RELY = 22, STAGE_PARENT_POST_RELY = 23, - + STAGE_PARENT_UNINSTALL, // run in child process STAGE_CHILD_PRE_COLDBOOT = 30, // clear env, set token before cold boot STAGE_CHILD_EXECUTE, diff --git a/modules/module_engine/include/appspawn_msg.h b/modules/module_engine/include/appspawn_msg.h index 3c6325292b56169bbf272631368cb9aa7e3e7941..94f966b95b47f94395dd893a1dc5878b8eaa787e 100644 --- a/modules/module_engine/include/appspawn_msg.h +++ b/modules/module_engine/include/appspawn_msg.h @@ -31,6 +31,7 @@ extern "C" { #define CJAPPSPAWN_SOCKET_NAME "CJAppSpawn" #define KEEPALIVE_NAME "keepalive" #define NATIVESPAWN_SOCKET_NAME "NativeSpawn" +#define SPAWN_LISTEN_FD_NAME "SpawnListenFd" #define APPSPAWN_ALIGN(len) (((len) + 0x03) & (~0x03)) #define APPSPAWN_TLV_NAME_LEN 32 diff --git a/modules/modulemgr/appspawn_modulemgr.c b/modules/modulemgr/appspawn_modulemgr.c index e3dd3d7ee6ef334f5dcb69b13e9e018928cbed9b..c29076de3db7191a0ca7198efa7a3d39299236ab 100644 --- a/modules/modulemgr/appspawn_modulemgr.c +++ b/modules/modulemgr/appspawn_modulemgr.c @@ -259,7 +259,7 @@ int ProcessMgrHookExecute(AppSpawnHookStage stage, const AppSpawnContent *conten { APPSPAWN_CHECK(content != NULL && appInfo != NULL, return APPSPAWN_ARG_INVALID, "Invalid hook"); - APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_DIED), + APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_UMOUNT), return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage); AppSpawnAppArg arg; @@ -279,7 +279,7 @@ static int ProcessMgrHookRun(const HOOK_INFO *hookInfo, void *executionContext) int AddProcessMgrHook(AppSpawnHookStage stage, int prio, ProcessChangeHook hook) { APPSPAWN_CHECK(hook != NULL, return APPSPAWN_ARG_INVALID, "Invalid hook"); - APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_DIED), + APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_UMOUNT), return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage); HOOK_INFO info; info.stage = stage; diff --git a/modules/nweb_adapter/BUILD.gn b/modules/nweb_adapter/BUILD.gn index b552b3dc4e72af3c44644557731a0fed76423444..acd15abe223a366520e29f0fe8fac4c159b09e25 100644 --- a/modules/nweb_adapter/BUILD.gn +++ b/modules/nweb_adapter/BUILD.gn @@ -20,15 +20,11 @@ ohos_shared_library("appspawn_nweb") { ".", "${appspawn_path}/common", "${appspawn_path}/standard", - "${appspawn_path}/util/include", ] defines = [] cflags = [] - deps = [ - "${appspawn_path}/modules/module_engine:libappspawn_module_engine", - "${appspawn_path}/util:libappspawn_util", - ] + deps = [ "${appspawn_path}/modules/module_engine:libappspawn_module_engine" ] if (target_cpu == "arm64") { defines += [ "webview_arm64" ] } diff --git a/modules/nweb_adapter/nwebspawn_adapter.cpp b/modules/nweb_adapter/nwebspawn_adapter.cpp index 8f4375f44007f388f93da3339f61fa0d38a59b67..6a54d3d087bc925d181ae3237ec31a5299b5f51d 100644 --- a/modules/nweb_adapter/nwebspawn_adapter.cpp +++ b/modules/nweb_adapter/nwebspawn_adapter.cpp @@ -29,18 +29,11 @@ #include "appspawn_hook.h" #include "appspawn_manager.h" -#include "appspawn_utils.h" #ifdef WITH_SECCOMP #include "seccomp_policy.h" #endif -#ifndef APPSPAWN_TEST -#define APPSPAWN_STATIC static -#else -#define APPSPAWN_STATIC -#endif - namespace { #if defined(webview_arm64) const std::string ARK_WEB_CORE_HAP_LIB_PATH = @@ -58,7 +51,7 @@ namespace { const std::string WEB_RENDER_LIB_NAME = "libnweb_render.so"; } // namespace -APPSPAWN_STATIC bool SetSeccompPolicyForRenderer(void *nwebRenderHandle) +static bool SetSeccompPolicyForRenderer(void *nwebRenderHandle) { #ifdef WITH_SECCOMP if (IsEnableSeccomp()) { @@ -95,11 +88,12 @@ APPSPAWN_STATIC std::string GetArkWebRenderLibName() APPSPAWN_STATIC int RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) { - EnableCache(); uint32_t len = 0; char *renderCmd = reinterpret_cast(GetAppPropertyExt( reinterpret_cast(client), MSG_EXT_NAME_RENDER_CMD, &len)); - APPSPAWN_CHECK_ONLY_EXPER(renderCmd != nullptr, return -1); + if (renderCmd == nullptr) { + return -1; + } std::string renderStr(renderCmd); void *webEngineHandle = nullptr; void *nwebRenderHandle = nullptr; @@ -109,15 +103,15 @@ APPSPAWN_STATIC int RunChildProcessor(AppSpawnContent *content, AppSpawnClient * const std::string renderLibName = GetArkWebRenderLibName(); #ifdef __MUSL__ - Dl_namespace dlns; + Dl_namespace dlns, ndkns; dlns_init(&dlns, "nweb_ns"); dlns_create(&dlns, libPath.c_str()); + dlns_get("ndk", &ndkns); + dlns_inherit(&dlns, &ndkns, "allow_all_shared_libs"); // preload libweb_engine - webEngineHandle = - dlopen_ns(&dlns, engineLibName.c_str(), RTLD_NOW | RTLD_GLOBAL); + webEngineHandle = dlopen_ns(&dlns, engineLibName.c_str(), RTLD_NOW | RTLD_GLOBAL); // load libnweb_render - nwebRenderHandle = - dlopen_ns(&dlns, renderLibName.c_str(), RTLD_NOW | RTLD_GLOBAL); + nwebRenderHandle = dlopen_ns(&dlns, renderLibName.c_str(), RTLD_NOW | RTLD_GLOBAL); #else // preload libweb_engine const std::string engineLibPath = libPath + "/" + engineLibName; diff --git a/modules/sandbox/BUILD.gn b/modules/sandbox/BUILD.gn index ad320a82963aec4c4c1a820800e1c9ffb05ff05f..5a7d2d2c7188861dbf3efcf98882ee7119cd8f66 100644 --- a/modules/sandbox/BUILD.gn +++ b/modules/sandbox/BUILD.gn @@ -78,6 +78,7 @@ if (defined(appspawn_sandbox_new) && appspawn_sandbox_new) { sources = [ "${appspawn_innerkits_path}/permission/appspawn_mount_permission.c", "appspawn_permission.c", + "sandbox_shared_mount.cpp", "sandbox_utils.cpp", ] @@ -114,6 +115,12 @@ if (defined(appspawn_sandbox_new) && appspawn_sandbox_new) { external_deps += [ "selinux_adapter:librestorecon" ] } } + if (appspawn_report_event) { + defines += [ "APPSPAWN_HISYSEVENT" ] + external_deps += [ "hisysevent:libhisysevent" ] + include_dirs += [ "${appspawn_path}/modules/sysevent" ] + sources += [ "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp" ] + } subsystem_name = "${subsystem_name}" part_name = "${part_name}" diff --git a/modules/sandbox/appspawn_mount_template.c b/modules/sandbox/appspawn_mount_template.c index eb889e5f72bcb921e4798c442a26b42a34e20e09..49c6f2b9b92334c2aecfcfae5dc131ee1fe00385 100644 --- a/modules/sandbox/appspawn_mount_template.c +++ b/modules/sandbox/appspawn_mount_template.c @@ -160,7 +160,7 @@ static void DumpMode(const char *info, mode_t mode) APPSPAWN_CHECK_ONLY_EXPER(info != NULL, return); char buffer[64] = {0}; // 64 to show flags DumpSandboxFlags(buffer, sizeof(buffer), mode, PATH_MODE_MAP, ARRAY_LENGTH(PATH_MODE_MAP)); - APPSPAPWN_DUMP("%{public}s[0x%{public}x] %{public}s", info, (uint32_t)(mode), buffer); + APPSPAWN_DUMP("%{public}s[0x%{public}x] %{public}s", info, (uint32_t)(mode), buffer); } static void DumpMountFlags(const char *info, unsigned long mountFlags) @@ -168,7 +168,7 @@ static void DumpMountFlags(const char *info, unsigned long mountFlags) APPSPAWN_CHECK_ONLY_EXPER(info != NULL, return); char buffer[128] = {0}; // 64 to show flags DumpSandboxFlags(buffer, sizeof(buffer), mountFlags, MOUNT_FLAGS_MAP, ARRAY_LENGTH(MOUNT_FLAGS_MAP)); - APPSPAPWN_DUMP("%{public}s[0x%{public}x] %{public}s", info, (uint32_t)(mountFlags), buffer); + APPSPAWN_DUMP("%{public}s[0x%{public}x] %{public}s", info, (uint32_t)(mountFlags), buffer); } void DumpMountPathMountNode(const PathMountNode *pathNode) @@ -177,13 +177,13 @@ void DumpMountPathMountNode(const PathMountNode *pathNode) if (tmp == NULL) { return; } - APPSPAPWN_DUMP(" sandbox node category: %{public}u(%{public}s)", tmp->category, tmp->name); + APPSPAWN_DUMP(" sandbox node category: %{public}u(%{public}s)", tmp->category, tmp->name); DumpMountFlags(" sandbox node mountFlags: ", tmp->mountFlags); - APPSPAPWN_DUMP(" sandbox node mountSharedFlag: %{public}s", + APPSPAWN_DUMP(" sandbox node mountSharedFlag: %{public}s", tmp->mountSharedFlag == MS_SLAVE ? "MS_SLAVE" : "MS_SHARED"); - APPSPAPWN_DUMP(" sandbox node options: %{public}s", tmp->options ? tmp->options : "null"); - APPSPAPWN_DUMP(" sandbox node fsType: %{public}s", tmp->fsType ? tmp->fsType : "null"); + APPSPAWN_DUMP(" sandbox node options: %{public}s", tmp->options ? tmp->options : "null"); + APPSPAWN_DUMP(" sandbox node fsType: %{public}s", tmp->fsType ? tmp->fsType : "null"); DumpMode(" sandbox node destMode: ", pathNode->destMode); - APPSPAPWN_DUMP(" sandbox node config mountSharedFlag: %{public}s", + APPSPAWN_DUMP(" sandbox node config mountSharedFlag: %{public}s", pathNode->mountSharedFlag ? "MS_SHARED" : "MS_SLAVE"); } \ No newline at end of file diff --git a/modules/sandbox/appspawn_sandbox.c b/modules/sandbox/appspawn_sandbox.c index 50c57d24771885680c945d6ef300a23a95f8e46f..1b5dfd02336a86838c79262a8ac04e133598d710 100644 --- a/modules/sandbox/appspawn_sandbox.c +++ b/modules/sandbox/appspawn_sandbox.c @@ -47,6 +47,8 @@ #define USER_ID_SIZE 16 #define DIR_MODE 0711 +#define LOCK_STATUS_PARAM_SIZE 64 +#define LOCK_STATUS_SIZE 16 #define DEV_SHM_DIR "/dev/shm/" static inline void SetMountPathOperation(uint32_t *operation, uint32_t index) @@ -102,11 +104,11 @@ int SandboxMountPath(const MountArg *arg) int ret = mount(arg->originPath, arg->destinationPath, arg->fsType, arg->mountFlags, arg->options); if (ret != 0) { - if (arg->originPath != NULL && strstr(arg->originPath, "/data/app/el2/") != NULL) { - CheckDirRecursive(arg->originPath); - } APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s", errno, arg->originPath, arg->destinationPath); + if (strstr(arg->originPath, "/data/app/el1/") != NULL || strstr(arg->originPath, "/data/app/el2/") != NULL) { + CheckDirRecursive(arg->originPath); + } return errno; } ret = mount(NULL, arg->destinationPath, NULL, arg->mountSharedFlag, NULL); @@ -186,6 +188,24 @@ void DeleteSandboxContext(SandboxContext *context) free(context); } +static bool NeedNetworkIsolated(SandboxContext *context, const AppSpawningCtx *property) +{ + int developerMode = IsDeveloperModeOpen(); + if (CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_SANDBOX) && !developerMode) { + return true; + } + + if (CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_NETWORK)) { + uint32_t len = 0; + char *extensionType = GetAppPropertyExt(property, MSG_EXT_NAME_EXTENSION_TYPE, &len); + if (extensionType == NULL || extensionType[0] == '\0' || !developerMode) { + return true; + } + } + + return false; +} + static int InitSandboxContext(SandboxContext *context, const AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn) { @@ -206,10 +226,9 @@ static int InitSandboxContext(SandboxContext *context, context->sandboxShared = packageNode->section.sandboxShared; } context->message = property->message; - context->sandboxNsFlags = CLONE_NEWNS; - if ((CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_SANDBOX) && !IsDeveloperModeOpen()) || - CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_NETWORK)) { + + if (NeedNetworkIsolated(context, property)) { context->sandboxNsFlags |= sandbox->sandboxNsFlags & CLONE_NEWNET ? CLONE_NEWNET : 0; } @@ -412,7 +431,7 @@ static int32_t SetMountArgsOption(const SandboxContext *context, uint32_t catego return 0; } -// 根据沙盒配置文件中挂载类别进行挂载挂载 +// 根据沙盒配置文件中挂载类别进行挂载 static int DoSandboxMountByCategory(const SandboxContext *context, const PathMountNode *sandboxNode, MountArg *args, uint32_t operation) { @@ -465,13 +484,16 @@ static int DoSandboxPathNodeMount(const SandboxContext *context, CreateSandboxDir(args.destinationPath, FILE_MODE); } } + CreateDemandSrc(context, sandboxNode, &args); + int ret = 0; if (CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_UNMOUNT)) { // unmount this deps APPSPAWN_LOGV("umount2 %{public}s", args.destinationPath); - umount2(args.destinationPath, MNT_DETACH); + ret = umount2(args.destinationPath, MNT_DETACH); + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to umount %{public}s errno %{public}d", args.destinationPath, errno); } - int ret = 0; + ret = DoSandboxMountByCategory(context, sandboxNode, &args, operation); if (ret != 0 && sandboxNode->checkErrorFlag) { APPSPAWN_LOGE("Failed to mount config, section: %{public}s result: %{public}d category: %{public}d", @@ -540,29 +562,24 @@ static int DoSandboxNodeMount(const SandboxContext *context, const SandboxSectio return 0; } -static bool IsUnlockStatus(uint32_t uid, const char *bundleName, size_t bundleNameLen) +static bool IsUnlockStatus(uint32_t uid) { const int userIdBase = UID_BASE; uid = uid / userIdBase; - if (uid == 0) { + if (uid == 0) { // uid = 0 不涉及加密目录的挂载 return true; } - const char rootPath[] = "/data/app/el2/"; - const char basePath[] = "/base/"; - size_t allPathSize = strlen(rootPath) + strlen(basePath) + 1 + USER_ID_SIZE + bundleNameLen; - char *path = (char *)malloc(sizeof(char) * allPathSize); - APPSPAWN_CHECK(path != NULL, return true, "Failed to malloc path"); - int len = sprintf_s(path, allPathSize, "%s%u%s%s", rootPath, uid, basePath, bundleName); - APPSPAWN_CHECK(len > 0 && ((size_t)len < allPathSize), free(path); return true, "Failed to get base path"); - - if (access(path, F_OK) == 0) { - APPSPAWN_LOGI("this is unlock status"); - free(path); + char lockStatusParam[LOCK_STATUS_PARAM_SIZE] = {0}; + char userLockStatus[LOCK_STATUS_SIZE] = {0}; + int ret = snprintf_s(lockStatusParam, sizeof(lockStatusParam), sizeof(lockStatusParam) - 1, + "startup.appspawn.lockstatus_%u", uid); + APPSPAWN_CHECK(ret > 0, return false, "get lock status param failed, errno %{public}d", errno); + ret = GetParameter(lockStatusParam, "1", userLockStatus, sizeof(userLockStatus)); + APPSPAWN_LOGI("get param %{public}s %{public}s", lockStatusParam, userLockStatus); + if (ret > 0 && (strcmp(userLockStatus, "0") == 0)) { // 0:解密状态 1:加密状态 return true; } - free(path); - APPSPAWN_LOGI("this is lock status"); return false; } @@ -573,33 +590,30 @@ static void MountDir(AppSpawnMsgDacInfo *info, const char *bundleName, const cha } const int userIdBase = UID_BASE; - size_t allPathSize = strlen(rootPath) + strlen(targetPath) + strlen(bundleName) + 2; - allPathSize += USER_ID_SIZE; - char *path = (char *)malloc(sizeof(char) * (allPathSize)); - APPSPAWN_CHECK(path != NULL, return, "Failed to malloc path"); - int len = sprintf_s(path, allPathSize, "%s%u/%s%s", rootPath, info->uid / userIdBase, bundleName, targetPath); - APPSPAWN_CHECK(len > 0 && ((size_t)len < allPathSize), free(path); - return, "Failed to get sandbox path"); + char path[MAX_SANDBOX_BUFFER] = {0}; + int ret = snprintf_s(path, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s%u/%s%s", rootPath, + info->uid / userIdBase, bundleName, targetPath); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf_s path failed, errno %{public}d", errno); + return; + } if (access(path, F_OK) == 0) { - free(path); return; } - MakeDirRec(path, DIR_MODE, 1); + ret = MakeDirRec(path, DIR_MODE, 1); + APPSPAWN_CHECK(ret == 0, return, "mkdir %{public}s failed, ret %{public}d", path, ret); + if (mount(path, path, NULL, MS_BIND | MS_REC, NULL) != 0) { APPSPAWN_LOGI("bind mount %{public}s failed, error %{public}d", path, errno); - free(path); return; } if (mount(NULL, path, NULL, MS_SHARED, NULL) != 0) { APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", path, errno); - free(path); - return; + } else { + APPSPAWN_LOGI("mount path %{public}s to shared success", path); } - APPSPAWN_LOGI("mount path %{public}s to shared success", path); - free(path); - return; } static const MountSharedTemplate MOUNT_SHARED_MAP[] = { @@ -607,9 +621,140 @@ static const MountSharedTemplate MOUNT_SHARED_MAP[] = { {"/data/storage/el3", NULL}, {"/data/storage/el4", NULL}, {"/data/storage/el5", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"}, - {"/storage/Users", "ohos.permission.FILE_ACCESS_MANAGER"}, }; +static int MountInShared(const AppSpawnMsgDacInfo *info, const char *rootPath, const char *src, const char *target) +{ + if (info == NULL) { + return APPSPAWN_ARG_INVALID; + } + + char path[MAX_SANDBOX_BUFFER] = {0}; + int ret = snprintf_s(path, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/%u/app-root/%s", rootPath, + info->uid / UID_BASE, target); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf_s path failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + char currentUserPath[MAX_SANDBOX_BUFFER] = {0}; + ret = snprintf_s(currentUserPath, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/currentUser", path); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf_s currentUserPath failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + if (access(currentUserPath, F_OK) == 0) { + return 0; + } + + ret = MakeDirRec(path, DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, ret %{public}d", path, ret); + return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; + } + + if (mount(src, path, NULL, MS_BIND | MS_REC, NULL) != 0) { + APPSPAWN_LOGI("bind mount %{public}s to %{public}s failed, error %{public}d", src, path, errno); + return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL; + } + if (mount(NULL, path, NULL, MS_SHARED, NULL) != 0) { + APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", path, errno); + return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL; + } + + return 0; +} + +static int SharedMountInSharefs(const AppSpawnMsgDacInfo *info, const char *rootPath, + const char *src, const char *target) +{ + char currentUserPath[MAX_SANDBOX_BUFFER] = {0}; + int ret = snprintf_s(currentUserPath, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/currentUser", target); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf_s currentUserPath failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + if (access(currentUserPath, F_OK) == 0) { + return 0; + } + + ret = MakeDirRec(target, DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, ret %{public}d", target, ret); + return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; + } + + char options[OPTIONS_MAX_LEN] = {0}; + ret = snprintf_s(options, OPTIONS_MAX_LEN, OPTIONS_MAX_LEN - 1, "override_support_delete,user_id=%d", + info->uid / UID_BASE); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf_s options failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + if (mount(src, target, "sharefs", MS_NODEV, options) != 0) { + APPSPAWN_LOGE("sharefs mount %{public}s to %{public}s failed, error %{public}d", + src, target, errno); + return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL; + } + if (mount(NULL, target, NULL, MS_SHARED, NULL) != 0) { + APPSPAWN_LOGE("mount path %{public}s to shared failed, errno %{public}d", target, errno); + return APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL; + } + + return 0; +} + +static void UpdateStorageDir(const SandboxContext *context, AppSpawnSandboxCfg *sandbox, const AppSpawnMsgDacInfo *info) +{ + const char mntUser[] = "/mnt/user"; + const char nosharefsDocs[] = "nosharefs/docs"; + const char sharefsDocs[] = "sharefs/docs"; + const char rootPath[] = "/mnt/sandbox"; + const char userPath[] = "/storage/Users"; + + /* /mnt/user//nosharefs/Docs */ + char nosharefsDocsDir[MAX_SANDBOX_BUFFER] = {0}; + int ret = snprintf_s(nosharefsDocsDir, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/%d/%s", + mntUser, info->uid / UID_BASE, nosharefsDocs); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf_s nosharefsDocsDir failed, errno %{public}d", errno); + return; + } + + /* /mnt/user//sharefs/Docs */ + char sharefsDocsDir[MAX_SANDBOX_BUFFER] = {0}; + ret = snprintf_s(sharefsDocsDir, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/%d/%s", + mntUser, info->uid / UID_BASE, sharefsDocs); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf_s sharefsDocsDir failed, errno %{public}d", errno); + return; + } + + int index = GetPermissionIndexInQueue(&sandbox->permissionQueue, FILE_ACCESS_MANAGER_MODE); + int res = CheckSpawningPermissionFlagSet(context, index); + if (res == 0) { + char storageUserPath[MAX_SANDBOX_BUFFER] = {0}; + ret = snprintf_s(storageUserPath, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s/%d/app-root/%s", rootPath, + info->uid / UID_BASE, userPath); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf_s storageUserPath failed, errno %{public}d", errno); + return; + } + /* mount /mnt/user//sharefs/docs to /mnt/sandbox//app-root/storage/Users */ + ret = SharedMountInSharefs(info, rootPath, sharefsDocsDir, storageUserPath); + } else { + /* mount /mnt/user//nosharefs/docs to /mnt/sandbox//app-root/storage/Users */ + ret = MountInShared(info, rootPath, nosharefsDocsDir, userPath); + } + if (ret != 0) { + APPSPAWN_LOGE("Update storage dir, ret %{public}d", ret); + } + APPSPAWN_LOGI("Update %{public}s storage dir success", res == 0 ? "sharefs dir" : "no sharefs dir"); +} + static void MountDirToShared(const SandboxContext *context, AppSpawnSandboxCfg *sandbox) { const char rootPath[] = "/mnt/sandbox/"; @@ -620,10 +765,13 @@ static void MountDirToShared(const SandboxContext *context, AppSpawnSandboxCfg * if (info == NULL || context->bundleName == NULL) { return; } + + UpdateStorageDir(context, sandbox, info); + MountDir(info, appRootName, rootPath, nwebPath); MountDir(info, appRootName, rootPath, nwebTmpPath); - if (IsUnlockStatus(info->uid, context->bundleName, strlen(context->bundleName))) { + if (IsUnlockStatus(info->uid)) { return; } @@ -754,7 +902,7 @@ static int SetExpandSandboxConfig(const SandboxContext *context, const AppSpawnS AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO); if (msgDomainInfo != NULL) { mountDestBundlePath = (strcmp(msgDomainInfo->apl, APL_SYSTEM_BASIC) == 0) || - (strcmp(msgDomainInfo->apl, APL_SYSTEM_CORE) == 0); + (strcmp(msgDomainInfo->apl, APL_SYSTEM_CORE) == 0); } if (mountDestBundlePath || (CheckSpawningMsgFlagSet(context, APP_FLAGS_ACCESS_BUNDLE_DIR) != 0)) { // need permission check for system app here @@ -1007,7 +1155,6 @@ static bool IsADFPermission(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *p if (index > 0 && CheckAppPermissionFlagSet(property, index)) { return true; } - if (GetBundleName(property) != NULL && strstr(GetBundleName(property), "com.ohos.dlpmanager") != NULL) { return true; } @@ -1075,7 +1222,7 @@ static int MountDepGroups(const SandboxContext *context, SandboxNameGroupNode *g } ret = UpdateMountPathDepsPath(context, groupNode); - APPSPAWN_CHECK(ret == 0, return ret, "Failed to updata deps path name groups %{public}s", groupNode->section.name); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to update deps path name groups %{public}s", groupNode->section.name); if (groupNode->depMode == MOUNT_MODE_NOT_EXIST && CheckAndCreateDepPath(context, groupNode)) { return 0; diff --git a/modules/sandbox/appspawn_sandbox.h b/modules/sandbox/appspawn_sandbox.h index af78fd3721c34551edf7544f76fedce95e6df4de..7602178f97bcf0a6297020978b0de57914c09070 100644 --- a/modules/sandbox/appspawn_sandbox.h +++ b/modules/sandbox/appspawn_sandbox.h @@ -72,6 +72,7 @@ extern "C" { #define ACCESS_DLP_FILE_MODE "ohos.permission.ACCESS_DLP_FILE" #define FILE_ACCESS_MANAGER_MODE "ohos.permission.FILE_ACCESS_MANAGER" #define READ_WRITE_USER_FILE_MODE "ohos.permission.READ_WRITE_USER_FILE" +#define GET_ALL_PROCESSES_MODE "ohos.permission.GET_ALL_PROCESSES" typedef enum SandboxTag { SANDBOX_TAG_MOUNT_PATH = 0, @@ -293,8 +294,8 @@ typedef struct TagVarExtraData { void ClearVariable(void); void AddDefaultVariable(void); -const char *GetSandboxRealVar(const SandboxContext *context, - uint32_t bufferType, const char *source, const char *prefix, const VarExtraData *extraData); +const char *GetSandboxRealVar(const SandboxContext *context, uint32_t bufferType, const char *source, + const char *prefix, const VarExtraData *extraData); /** * @brief expand config diff --git a/modules/sandbox/sandbox_cfgvar.c b/modules/sandbox/sandbox_cfgvar.c index ac035918fd0207a7184bfc248d61d95da986076e..78384842981ff56bcdb8e4618ade977316ed56d7 100644 --- a/modules/sandbox/sandbox_cfgvar.c +++ b/modules/sandbox/sandbox_cfgvar.c @@ -287,8 +287,8 @@ static int HandleVariableReplace(const SandboxContext *context, return 0; } -const char *GetSandboxRealVar(const SandboxContext *context, - uint32_t bufferType, const char *source, const char *prefix, const VarExtraData *extraData) +const char *GetSandboxRealVar(const SandboxContext *context, uint32_t bufferType, const char *source, + const char *prefix, const VarExtraData *extraData) { APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return NULL); APPSPAWN_CHECK(bufferType < ARRAY_LENGTH(context->buffer), return NULL, "Invalid index for buffer"); diff --git a/modules/sandbox/sandbox_expand.c b/modules/sandbox/sandbox_expand.c index ef9d5e41ca6858b13bc2ff207f91078079344b0a..7c53fcb8a66949553ff8d0a662696ac5341b7e57 100644 --- a/modules/sandbox/sandbox_expand.c +++ b/modules/sandbox/sandbox_expand.c @@ -166,7 +166,9 @@ static int SetOverlayAppPath(const char *hapPath, void *context) APPSPAWN_LOGV("SetOverlayAppPath path: '%{public}s' => '%{public}s'", sandboxContext->buffer[0].buffer, sandboxContext->buffer[1].buffer); - (void)MakeDirRec(sandboxContext->buffer[1].buffer, FILE_MODE, 1); + ret = MakeDirRec(sandboxContext->buffer[1].buffer, FILE_MODE, 1); + APPSPAWN_CHECK(ret == 0, return ret, "Fail to mkdir dir %{public}s, ret: %{public}d", + sandboxContext->buffer[1].buffer, ret); MountArg mountArg = { sandboxContext->buffer[0].buffer, sandboxContext->buffer[1].buffer, NULL, MS_REC | MS_BIND, NULL, MS_SHARED }; diff --git a/modules/sandbox/sandbox_load.c b/modules/sandbox/sandbox_load.c index 3158aa3d7f8a2afff613187cfade4ab5434a0fc3..9bb7cd2410ed48437d34a9ae156a4b7c96ea5ce5 100644 --- a/modules/sandbox/sandbox_load.c +++ b/modules/sandbox/sandbox_load.c @@ -45,7 +45,8 @@ static const SandboxFlagInfo FLAGE_POINT_MAP[] = { {"0", 0}, {"START_FLAGS_BACKUP", (unsigned long)APP_FLAGS_BACKUP_EXTENSION}, {"DLP_MANAGER", (unsigned long)APP_FLAGS_DLP_MANAGER}, - {"DEVELOPER_MODE", (unsigned long)APP_FLAGS_DEVELOPER_MODE} + {"DEVELOPER_MODE", (unsigned long)APP_FLAGS_DEVELOPER_MODE}, + {"PREINSTALLED_HAP", (unsigned long)APP_FLAGS_PRE_INSTALLED_HAP} }; static const SandboxFlagInfo MOUNT_MODE_MAP[] = { @@ -677,6 +678,7 @@ int LoadAppSandboxConfig(AppSpawnSandboxCfg *sandbox, RunMode mode) { APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_ARG_INVALID); const char *sandboxName = GetSandboxNameByMode(mode); + APPSPAWN_LOGV("Get sandboxName %{public}s by mode %{public}d", sandboxName, mode); if (sandbox->depGroupNodes != NULL) { APPSPAWN_LOGW("Sandbox has been load"); return 0; diff --git a/modules/sandbox/sandbox_manager.c b/modules/sandbox/sandbox_manager.c index bbcabb050084e422cd2329e40a9656aef0157dac..80e0fd1f87188606b24b9e721a072f49fecb44e4 100644 --- a/modules/sandbox/sandbox_manager.c +++ b/modules/sandbox/sandbox_manager.c @@ -165,24 +165,24 @@ void DumpSandboxMountNode(const SandboxMountNode *sandboxNode, uint32_t index) case SANDBOX_TAG_MOUNT_PATH: case SANDBOX_TAG_MOUNT_FILE: { PathMountNode *pathNode = (PathMountNode *)sandboxNode; - APPSPAPWN_DUMP(" ****************************** %{public}u", index); - APPSPAPWN_DUMP(" sandbox node source: %{public}s", pathNode->source ? pathNode->source : "null"); - APPSPAPWN_DUMP(" sandbox node target: %{public}s", pathNode->target ? pathNode->target : "null"); + APPSPAWN_DUMP(" ****************************** %{public}u", index); + APPSPAWN_DUMP(" sandbox node source: %{public}s", pathNode->source ? pathNode->source : "null"); + APPSPAWN_DUMP(" sandbox node target: %{public}s", pathNode->target ? pathNode->target : "null"); DumpMountPathMountNode(pathNode); - APPSPAPWN_DUMP(" sandbox node apl: %{public}s", + APPSPAWN_DUMP(" sandbox node apl: %{public}s", pathNode->appAplName ? pathNode->appAplName : "null"); - APPSPAPWN_DUMP(" sandbox node checkErrorFlag: %{public}s", + APPSPAWN_DUMP(" sandbox node checkErrorFlag: %{public}s", pathNode->checkErrorFlag ? "true" : "false"); break; } case SANDBOX_TAG_SYMLINK: { SymbolLinkNode *linkNode = (SymbolLinkNode *)sandboxNode; - APPSPAPWN_DUMP(" ***********************************"); - APPSPAPWN_DUMP(" sandbox node target: %{public}s", linkNode->target ? linkNode->target : "null"); - APPSPAPWN_DUMP(" sandbox node linkName: %{public}s", + APPSPAWN_DUMP(" ***********************************"); + APPSPAWN_DUMP(" sandbox node target: %{public}s", linkNode->target ? linkNode->target : "null"); + APPSPAWN_DUMP(" sandbox node linkName: %{public}s", linkNode->linkName ? linkNode->linkName : "null"); - APPSPAPWN_DUMP(" sandbox node destMode: %{public}x", linkNode->destMode); - APPSPAPWN_DUMP(" sandbox node checkErrorFlag: %{public}s", + APPSPAWN_DUMP(" sandbox node destMode: %{public}x", linkNode->destMode); + APPSPAWN_DUMP(" sandbox node checkErrorFlag: %{public}s", linkNode->checkErrorFlag ? "true" : "false"); break; } @@ -255,20 +255,20 @@ static void DumpSandboxQueue(const ListNode *front, static void DumpSandboxSection(const SandboxSection *section) { - APPSPAPWN_DUMP(" sandboxSwitch %{public}s", section->sandboxSwitch ? "true" : "false"); - APPSPAPWN_DUMP(" sandboxShared %{public}s", section->sandboxShared ? "true" : "false"); - APPSPAPWN_DUMP(" gidCount: %{public}u", section->gidCount); + APPSPAWN_DUMP(" sandboxSwitch %{public}s", section->sandboxSwitch ? "true" : "false"); + APPSPAWN_DUMP(" sandboxShared %{public}s", section->sandboxShared ? "true" : "false"); + APPSPAWN_DUMP(" gidCount: %{public}u", section->gidCount); for (uint32_t index = 0; index < section->gidCount; index++) { - APPSPAPWN_DUMP(" gidTable[%{public}u]: %{public}u", index, section->gidTable[index]); + APPSPAWN_DUMP(" gidTable[%{public}u]: %{public}u", index, section->gidTable[index]); } - APPSPAPWN_DUMP(" mount group count: %{public}u", section->number); + APPSPAWN_DUMP(" mount group count: %{public}u", section->number); for (uint32_t i = 0; i < section->number; i++) { if (section->nameGroups[i]) { SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i]; - APPSPAPWN_DUMP(" name[%{public}d] %{public}s", i, groupNode->section.name); + APPSPAWN_DUMP(" name[%{public}d] %{public}s", i, groupNode->section.name); } } - APPSPAPWN_DUMP(" mount-paths: "); + APPSPAWN_DUMP(" mount-paths: "); DumpSandboxQueue(§ion->front, DumpSandboxMountNode); } @@ -385,29 +385,29 @@ void DeleteAppSpawnSandbox(AppSpawnSandboxCfg *sandbox) static void DumpSandboxPermission(const SandboxMountNode *node, uint32_t index) { SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)node; - APPSPAPWN_DUMP(" ========================================= "); - APPSPAPWN_DUMP(" Section %{public}s", permissionNode->section.name); - APPSPAPWN_DUMP(" Section permission index %{public}d", permissionNode->permissionIndex); + APPSPAWN_DUMP(" ========================================= "); + APPSPAWN_DUMP(" Section %{public}s", permissionNode->section.name); + APPSPAWN_DUMP(" Section permission index %{public}d", permissionNode->permissionIndex); DumpSandboxSection(&permissionNode->section); } static void DumpSandboxSectionNode(const SandboxMountNode *node, uint32_t index) { SandboxSection *section = (SandboxSection *)node; - APPSPAPWN_DUMP(" ========================================= "); - APPSPAPWN_DUMP(" Section %{public}s", section->name); + APPSPAWN_DUMP(" ========================================= "); + APPSPAWN_DUMP(" Section %{public}s", section->name); DumpSandboxSection(section); } static void DumpSandboxNameGroupNode(const SandboxMountNode *node, uint32_t index) { SandboxNameGroupNode *nameGroupNode = (SandboxNameGroupNode *)node; - APPSPAPWN_DUMP(" ========================================= "); - APPSPAPWN_DUMP(" Section %{public}s", nameGroupNode->section.name); - APPSPAPWN_DUMP(" Section dep mode %{public}s", + APPSPAWN_DUMP(" ========================================= "); + APPSPAWN_DUMP(" Section %{public}s", nameGroupNode->section.name); + APPSPAWN_DUMP(" Section dep mode %{public}s", nameGroupNode->depMode == MOUNT_MODE_ALWAYS ? "always" : "not-exists"); if (nameGroupNode->depNode != NULL) { - APPSPAPWN_DUMP(" mount-paths-deps: "); + APPSPAWN_DUMP(" mount-paths-deps: "); DumpMountPathMountNode(nameGroupNode->depNode); } DumpSandboxSection(&nameGroupNode->section); @@ -469,12 +469,12 @@ AppSpawnSandboxCfg *CreateAppSpawnSandbox(ExtDataType type) void DumpAppSpawnSandboxCfg(AppSpawnSandboxCfg *sandbox) { APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return); - APPSPAPWN_DUMP("Sandbox root path: %{public}s", sandbox->rootPath); - APPSPAPWN_DUMP("Sandbox sandboxNsFlags: %{public}x ", sandbox->sandboxNsFlags); - APPSPAPWN_DUMP("Sandbox topSandboxSwitch: %{public}s", sandbox->topSandboxSwitch ? "true" : "false"); - APPSPAPWN_DUMP("Sandbox appFullMountEnable: %{public}s", sandbox->appFullMountEnable ? "true" : "false"); - APPSPAPWN_DUMP("Sandbox pidNamespaceSupport: %{public}s", sandbox->pidNamespaceSupport ? "true" : "false"); - APPSPAPWN_DUMP("Sandbox common info: "); + APPSPAWN_DUMP("Sandbox root path: %{public}s", sandbox->rootPath); + APPSPAWN_DUMP("Sandbox sandboxNsFlags: %{public}x ", sandbox->sandboxNsFlags); + APPSPAWN_DUMP("Sandbox topSandboxSwitch: %{public}s", sandbox->topSandboxSwitch ? "true" : "false"); + APPSPAWN_DUMP("Sandbox appFullMountEnable: %{public}s", sandbox->appFullMountEnable ? "true" : "false"); + APPSPAWN_DUMP("Sandbox pidNamespaceSupport: %{public}s", sandbox->pidNamespaceSupport ? "true" : "false"); + APPSPAWN_DUMP("Sandbox common info: "); DumpSandboxQueue(&sandbox->requiredQueue.front, DumpSandboxSectionNode); DumpSandboxQueue(&sandbox->packageNameQueue.front, DumpSandboxSectionNode); DumpSandboxQueue(&sandbox->permissionQueue.front, DumpSandboxPermission); @@ -495,7 +495,7 @@ APPSPAWN_STATIC int PreLoadIsoLatedSandboxCfg(AppSpawnMgr *content) APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_SYSTEM_ERROR); OH_ListAddTail(&content->extData, &sandbox->extData.node); - // load app sandbox config + // load isolated sandbox config LoadAppSandboxConfig(sandbox, MODE_FOR_NATIVE_SPAWN); sandbox->maxPermissionIndex = PermissionRenumber(&sandbox->permissionQueue); @@ -515,8 +515,12 @@ APPSPAWN_STATIC int PreLoadSandboxCfg(AppSpawnMgr *content) APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_SYSTEM_ERROR); OH_ListAddTail(&content->extData, &sandbox->extData.node); - // load app sandbox config - LoadAppSandboxConfig(sandbox, MODE_FOR_APP_SPAWN); + // load app/nweb sandbox config + if (IsNWebSpawnMode(content)) { + LoadAppSandboxConfig(sandbox, MODE_FOR_NWEB_SPAWN); + } else { + LoadAppSandboxConfig(sandbox, MODE_FOR_APP_SPAWN); + } sandbox->maxPermissionIndex = PermissionRenumber(&sandbox->permissionQueue); content->content.sandboxNsFlags = 0; @@ -644,7 +648,23 @@ static int AppendPackageNameGids(const AppSpawnSandboxCfg *sandbox, AppSpawningC return 0; } -static int SetSandboxPermissionFlag(AppSpawnSandboxCfg *sandbox, AppSpawningCtx *property) +static void UpdateMsgFlagsWithPermission(AppSpawnSandboxCfg *sandbox, AppSpawningCtx *property) +{ + int32_t allProcessIndex = GetPermissionIndexInQueue(&sandbox->permissionQueue, GET_ALL_PROCESSES_MODE); + int res = CheckAppPermissionFlagSet(property, (uint32_t)allProcessIndex); + if (res == 0) { + APPSPAWN_LOGV("Don't need set GET_ALL_PROCESSES_MODE flag"); + return; + } + + int ret = SetAppSpawnMsgFlag(property->message, TLV_MSG_FLAGS, APP_FLAGS_GET_ALL_PROCESSES); + if (ret != 0) { + APPSPAWN_LOGE("Set GET_ALL_PROCESSES_MODE flag failed"); + } + return; +} + +static int UpdatePermissionFlags(AppSpawnSandboxCfg *sandbox, AppSpawningCtx *property) { int32_t index = 0; if (sandbox->appFullMountEnable) { @@ -690,13 +710,16 @@ int SpawnPrepareSandboxCfg(AppSpawnMgr *content, AppSpawningCtx *property) AppSpawnSandboxCfg *sandbox = GetAppSpawnSandbox(content, type); content->content.sandboxType = type; APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property)); - int ret = SetSandboxPermissionFlag(sandbox, property); + + int ret = UpdatePermissionFlags(sandbox, property); if (ret != 0) { APPSPAWN_LOGW("set sandbox permission flag failed."); return APPSPAWN_SANDBOX_ERROR_SET_PERMISSION_FLAG_FAIL; } - APPSPAWN_CHECK(ret == 0, return ret, "Failed to add gid for %{public}s", GetProcessName(property)); + UpdateMsgFlagsWithPermission(sandbox, property); + ret = AppendGids(sandbox, property); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to add gid for %{public}s", GetProcessName(property)); ret = StagedMountSystemConst(sandbox, property, IsNWebSpawnMode(content)); APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount system-const for %{public}s", GetProcessName(property)); return 0; diff --git a/modules/sandbox/sandbox_shared_mount.cpp b/modules/sandbox/sandbox_shared_mount.cpp new file mode 100644 index 0000000000000000000000000000000000000000..feade8309a14f2f2ca07969d4cf4fed3d9c27723 --- /dev/null +++ b/modules/sandbox/sandbox_shared_mount.cpp @@ -0,0 +1,600 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "nlohmann/json.hpp" + +#include "sandbox_shared_mount.h" +#include "appspawn_mount_permission.h" +#include "appspawn_utils.h" +#include "parameter.h" + +#define USER_ID_SIZE 16 +#define DIR_MODE 0711 +#define LOCK_STATUS_SIZE 16 + +#define DATA_GROUP_SOCKET_TYPE "DataGroup" +#define GROUPLIST_KEY_DATAGROUPID "dataGroupId" +#define GROUPLIST_KEY_GID "gid" +#define GROUPLIST_KEY_DIR "dir" +#define GROUPLIST_KEY_UUID "uuid" + +static const MountSharedTemplate MOUNT_SHARED_MAP[] = { + {"/data/storage/el2", nullptr}, + {"/data/storage/el3", nullptr}, + {"/data/storage/el4", nullptr}, + {"/data/storage/el5", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"}, +}; + +static const DataGroupSandboxPathTemplate DATA_GROUP_SANDBOX_PATH_MAP[] = { + {"el2", EL2, "/data/storage/el2/group/", nullptr}, + {"el3", EL3, "/data/storage/el3/group/", nullptr}, + {"el4", EL4, "/data/storage/el4/group/", nullptr}, + {"el5", EL5, "/data/storage/el5/group/", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"}, +}; + +static std::map g_mountInfoMap; + +int GetElxInfoFromDir(const char *path) +{ + int ret = ELX_MAX; + if (path == nullptr) { + return ret; + } + uint32_t count = ARRAY_LENGTH(DATA_GROUP_SANDBOX_PATH_MAP); + for (uint32_t i = 0; i < count; ++i) { + if (strstr(path, DATA_GROUP_SANDBOX_PATH_MAP[i].elxName) != nullptr) { + return DATA_GROUP_SANDBOX_PATH_MAP[i].category; + } + } + if (ret == 0) { + APPSPAWN_LOGE("Get elx info from dir failed, path %{public}s", path); + } + return ret; +} + +const DataGroupSandboxPathTemplate *GetDataGroupArgTemplate(uint32_t category) +{ + uint32_t count = ARRAY_LENGTH(DATA_GROUP_SANDBOX_PATH_MAP); + if (category > count) { + APPSPAWN_LOGE("category %{public}d is out of range", category); + return nullptr; + } + for (uint32_t i = 0; i < count; ++i) { + if (DATA_GROUP_SANDBOX_PATH_MAP[i].category == category) { + return &DATA_GROUP_SANDBOX_PATH_MAP[i]; + } + } + return nullptr; +} + +bool IsValidDataGroupItem(nlohmann::json &item) +{ + // Check if the item contains the specified key and if the value corresponding to the key is a string + if (item.contains(GROUPLIST_KEY_DATAGROUPID) && item[GROUPLIST_KEY_DATAGROUPID].is_string() && + item.contains(GROUPLIST_KEY_GID) && item[GROUPLIST_KEY_GID].is_string() && + item.contains(GROUPLIST_KEY_DIR) && item[GROUPLIST_KEY_DIR].is_string() && + item.contains(GROUPLIST_KEY_UUID) && item[GROUPLIST_KEY_UUID].is_string()) { + return true; + } + return false; +} + +void *GetEl1BundleMountCount(void) +{ + return static_cast(&g_mountInfoMap); +} + +#ifndef APPSPAWN_SANDBOX_NEW +static bool IsUnlockStatus(uint32_t uid) +{ + const int userIdBase = UID_BASE; + uid = uid / userIdBase; + if (uid == 0) { + return true; + } + std::string lockStatusParam = "startup.appspawn.lockstatus_" + std::to_string(uid); + char userLockStatus[LOCK_STATUS_SIZE] = {0}; + int ret = GetParameter(lockStatusParam.c_str(), "1", userLockStatus, sizeof(userLockStatus)); + APPSPAWN_LOGI("get param %{public}s %{public}s", lockStatusParam.c_str(), userLockStatus); + if (ret > 0 && (strcmp(userLockStatus, "0") == 0)) { // 0:unlock status 1:lock status + return true; + } + return false; +} + +static int DoSharedMount(const SharedMountArgs *arg) +{ + if (arg == nullptr || arg->srcPath == nullptr || arg->destPath == nullptr) { + APPSPAWN_LOGE("Invalid arg"); + return APPSPAWN_ARG_INVALID; + } + + APPSPAWN_LOGV("Mount arg: '%{public}s' '%{public}s' %{public}lu '%{public}s' %{public}s => %{public}s", + arg->fsType, arg->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE", + arg->mountFlags, arg->options, arg->srcPath, arg->destPath); + + int ret = mount(arg->srcPath, arg->destPath, arg->fsType, arg->mountFlags, arg->options); + if (ret != 0) { + APPSPAWN_LOGE("mount %{public}s to %{public}s failed, errno %{public}d", + arg->srcPath, arg->destPath, errno); + return ret; + } + ret = mount(nullptr, arg->destPath, nullptr, arg->mountSharedFlag, nullptr); + if (ret != 0) { + APPSPAWN_LOGE("mount path %{public}s to shared failed, errno %{public}d", arg->destPath, errno); + return ret; + } + APPSPAWN_LOGI("mount path %{public}s to shared success", arg->destPath); + return 0; +} + +static bool SetSandboxPathShared(const std::string &sandboxPath) +{ + int ret = mount(nullptr, sandboxPath.c_str(), nullptr, MS_SHARED, nullptr); + if (ret != 0) { + APPSPAWN_LOGW("Need to mount %{public}s to shared, errno %{public}d", sandboxPath.c_str(), errno); + return false; + } + return true; +} + +static int MountEl1Bundle(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) +{ + /* /data/app/el1/bundle/public/ */ + char sourcePath[PATH_MAX_LEN] = {0}; + int ret = snprintf_s(sourcePath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/data/app/el1/bundle/public/%s", bundleName); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf data/app/el1/bundle/public/%{public}s failed, errno %{public}d", bundleName, errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + /* /mnt/sandbox///data/storage/el1/bundle */ + char targetPath[PATH_MAX_LEN] = {0}; + ret = snprintf_s(targetPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%u/%s/data/storage/el1/bundle", + info->uid/ UID_BASE, bundleName); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf el1 bundle sandbox path failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + ret = MakeDirRec(targetPath, DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", targetPath, errno); + return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; + } + + ret = umount2(targetPath, MNT_DETACH); + if (ret != 0) { + APPSPAWN_LOGE("umount2 %{public}s failed, errno %{public}d", targetPath, errno); + } + + SharedMountArgs arg = { + .srcPath = sourcePath, + .destPath = targetPath, + .fsType = nullptr, + .mountFlags = MS_BIND | MS_REC, + .options = nullptr, + .mountSharedFlag = MS_SHARED + }; + ret = DoSharedMount(&arg); + if (ret != 0) { + APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", targetPath, ret); + } + std::string key = std::to_string(info->uid / UID_BASE) + "-" + std::string(bundleName); + g_mountInfoMap[key]++; + return ret; +} + +static int MountWithFileMgr(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) +{ + /* /mnt/user//nosharefs/docs */ + char nosharefsDocsDir[PATH_MAX_LEN] = {0}; + int ret = snprintf_s(nosharefsDocsDir, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/user/%u/nosharefs/docs", + info->uid / UID_BASE); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf nosharefsDocsDir failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + /* /mnt/sandbox//storage/Users */ + char storageUserPath[PATH_MAX_LEN] = {0}; + ret = snprintf_s(storageUserPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%u/%s/storage/Users", + info->uid / UID_BASE, bundleName); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf storageUserPath failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + // Check whether the directory is a shared mount point + if (SetSandboxPathShared(storageUserPath)) { + APPSPAWN_LOGI("shared mountpoint is exist"); + return 0; + } + + ret = MakeDirRec(storageUserPath, DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", storageUserPath, errno); + return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; + } + + SharedMountArgs arg = { + .srcPath = nosharefsDocsDir, + .destPath = storageUserPath, + .fsType = nullptr, + .mountFlags = MS_BIND | MS_REC, + .options = nullptr, + .mountSharedFlag = MS_SHARED + }; + ret = DoSharedMount(&arg); + if (ret != 0) { + APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", storageUserPath, ret); + } + return ret; +} + +static int MountWithOther(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) +{ + /* /mnt/user//sharefs/docs */ + char sharefsDocsDir[PATH_MAX_LEN] = {0}; + int ret = snprintf_s(sharefsDocsDir, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/user/%u/sharefs/docs", + info->uid / UID_BASE); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf sharefsDocsDir failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + /* /mnt/sandbox//storage/Users */ + char storageUserPath[PATH_MAX_LEN] = {0}; + ret = snprintf_s(storageUserPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%u/%s/storage/Users", + info->uid / UID_BASE, bundleName); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf storageUserPath failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + // Check whether the directory is a shared mount point + if (SetSandboxPathShared(storageUserPath)) { + APPSPAWN_LOGI("shared mountpoint is exist"); + return 0; + } + + ret = MakeDirRec(storageUserPath, DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", storageUserPath, errno); + return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; + } + + char options[PATH_MAX_LEN] = {0}; + ret = snprintf_s(options, PATH_MAX_LEN, PATH_MAX_LEN - 1, "override_support_delete,user_id=%u", + info->uid / UID_BASE); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf options failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + SharedMountArgs arg = { + .srcPath = sharefsDocsDir, + .destPath = storageUserPath, + .fsType = "sharefs", + .mountFlags = MS_NODEV, + .options = options, + .mountSharedFlag = MS_SHARED + }; + ret = DoSharedMount(&arg); + if (ret != 0) { + APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", storageUserPath, ret); + } + return ret; +} + +static void MountStorageUsers(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) +{ + int ret = 0; + int index = GetPermissionIndex(nullptr, "ohos.permission.FILE_ACCESS_MANAGER"); + int checkRes = CheckAppPermissionFlagSet(property, static_cast(index)); + if (checkRes == 0) { + /* mount /mnt/user//sharefs/docs to /mnt/sandbox///storage/Users */ + ret = MountWithOther(property, info, bundleName); + } else { + /* mount /mnt/user//nosharefs/docs to /mnt/sandbox///storage/Users */ + ret = MountWithFileMgr(property, info, bundleName); + } + if (ret != 0) { + APPSPAWN_LOGE("Update %{public}s storage dir failed, ret %{public}d", + checkRes == 0 ? "sharefs dir" : "no sharefs dir", ret); + } else { + APPSPAWN_LOGI("Update %{public}s storage dir success", checkRes == 0 ? "sharefs dir" : "no sharefs dir"); + } +} + +static int MountSharedMapItem(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName, + const char *sandboxPathItem) +{ + /* /mnt/sandbox///data/storage/el */ + char sandboxPath[PATH_MAX_LEN] = {0}; + int ret = snprintf_s(sandboxPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "/mnt/sandbox/%u/%s%s", + info->uid / UID_BASE, bundleName, sandboxPathItem); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf sandboxPath failed, errno %{public}d", errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + // Check whether the directory is a shared mount point + if (SetSandboxPathShared(sandboxPath)) { + APPSPAWN_LOGI("shared mountpoint is exist"); + return 0; + } + + ret = MakeDirRec(sandboxPath, DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", sandboxPath, errno); + return APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL; + } + + SharedMountArgs arg = { + .srcPath = sandboxPath, + .destPath = sandboxPath, + .fsType = nullptr, + .mountFlags = MS_BIND | MS_REC, + .options = nullptr, + .mountSharedFlag = MS_SHARED + }; + ret = DoSharedMount(&arg); + if (ret != 0) { + APPSPAWN_LOGE("mount %{public}s shared failed, ret %{public}d", sandboxPath, ret); + } + return ret; +} + +static void MountSharedMap(const AppSpawningCtx *property, const AppDacInfo *info, const char *bundleName) +{ + int length = sizeof(MOUNT_SHARED_MAP) / sizeof(MOUNT_SHARED_MAP[0]); + for (int i = 0; i < length; i++) { + if (MOUNT_SHARED_MAP[i].permission == nullptr) { + MountSharedMapItem(property, info, bundleName, MOUNT_SHARED_MAP[i].sandboxPath); + } else { + int index = GetPermissionIndex(nullptr, MOUNT_SHARED_MAP[i].permission); + APPSPAWN_LOGV("mount dir on lock mountPermissionFlags %{public}d", index); + if (CheckAppPermissionFlagSet(property, static_cast(index))) { + MountSharedMapItem(property, info, bundleName, MOUNT_SHARED_MAP[i].sandboxPath); + } + } + } + APPSPAWN_LOGI("mount shared map success"); +} + +static inline bool CheckPath(const std::string& name) +{ + return !name.empty() && name != "." && name != ".." && name.find("/") == std::string::npos; +} + +static int DataGroupCtxNodeCompare(ListNode *node, void *data) +{ + DataGroupCtx *existingNode = (DataGroupCtx *)ListEntry(node, DataGroupCtx, node); + DataGroupCtx *newNode = (DataGroupCtx *)data; + if (existingNode == nullptr || newNode == nullptr) { + APPSPAWN_LOGE("Invalid param"); + return APPSPAWN_ARG_INVALID; + } + + // compare src path and sandbox path + bool isSrcPathEqual = (strcmp(existingNode->srcPath.path, newNode->srcPath.path) == 0); + bool isDestPathEqual = (strcmp(existingNode->destPath.path, newNode->destPath.path) == 0); + + return (isSrcPathEqual && isDestPathEqual) ? 0 : 1; +} + +static int AddDataGroupItemToQueue(AppSpawnMgr *content, const std::string &srcPath, const std::string &destPath, + const std::string &dataGroupUuid) +{ + DataGroupCtx *dataGroupNode = (DataGroupCtx *)calloc(1, sizeof(DataGroupCtx)); + APPSPAWN_CHECK(dataGroupNode != nullptr, return APPSPAWN_ERROR_UTILS_MEM_FAIL, "Calloc dataGroupNode failed"); + if (strcpy_s(dataGroupNode->srcPath.path, PATH_MAX_LEN - 1, srcPath.c_str()) != EOK || + strcpy_s(dataGroupNode->destPath.path, PATH_MAX_LEN - 1, destPath.c_str()) != EOK || + strcpy_s(dataGroupNode->dataGroupUuid, UUID_MAX_LEN, dataGroupUuid.c_str()) != EOK) { + APPSPAWN_LOGE("strcpy dataGroupNode->srcPath failed"); + free(dataGroupNode); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + dataGroupNode->srcPath.pathLen = strlen(dataGroupNode->srcPath.path); + dataGroupNode->destPath.pathLen = strlen(dataGroupNode->destPath.path); + ListNode *node = OH_ListFind(&content->dataGroupCtxQueue, (void *)dataGroupNode, DataGroupCtxNodeCompare); + if (node != nullptr) { + APPSPAWN_LOGI("DataGroupCtxNode %{public}s is exist", dataGroupNode->srcPath.path); + return 0; + } + OH_ListInit(&dataGroupNode->node); + OH_ListAddTail(&content->dataGroupCtxQueue, &dataGroupNode->node); + return 0; +} + +static std::string GetExtraInfoByType(const AppSpawningCtx *appPropery, const std::string &type) +{ + uint32_t len = 0; + char *info = reinterpret_cast(GetAppPropertyExt(appPropery, type.c_str(), &len)); + if (info == nullptr) { + return ""; + } + return std::string(info, len); +} + +static void DumpDataGroupCtxQueue(const ListNode *front) +{ + if (front == nullptr) { + return; + } + + uint32_t count = 0; + ListNode *node = front->next; + while (node != front) { + DataGroupCtx *dataGroupNode = (DataGroupCtx *)ListEntry(node, DataGroupCtx, node); + count++; + APPSPAWN_LOGV(" ************************************** %{public}d", count); + APPSPAWN_LOGV(" srcPath: %{public}s", dataGroupNode->srcPath.path); + APPSPAWN_LOGV(" destPath: %{public}s", dataGroupNode->destPath.path); + APPSPAWN_LOGV(" uuid: %{public}s", dataGroupNode->dataGroupUuid); + node = node->next; + } +} + +static int ParseDataGroupList(AppSpawnMgr *content, const AppSpawningCtx *property, AppDacInfo *info, + AppSpawnMsgBundleInfo *bundleInfo) +{ + int ret = 0; + std::string dataGroupList = GetExtraInfoByType(property, DATA_GROUP_SOCKET_TYPE); + if (dataGroupList.length() == 0) { + APPSPAWN_LOGE("dataGroupList is empty"); + return APPSPAWN_ARG_INVALID; + } + + nlohmann::json dataGroupJson = nlohmann::json::parse(dataGroupList.c_str(), nullptr, false); + if (dataGroupJson.is_discarded() && dataGroupJson.contains(GROUPLIST_KEY_DATAGROUPID) && + dataGroupJson.contains(GROUPLIST_KEY_GID) && dataGroupJson.contains(GROUPLIST_KEY_DIR) && + dataGroupJson.contains(GROUPLIST_KEY_UUID)) { + APPSPAWN_LOGE("dataGroupJson is discarded"); + return APPSPAWN_ARG_INVALID; + } + for (auto &item : dataGroupJson) { + APPSPAWN_CHECK(IsValidDataGroupItem(item), return -1, "Element is not a valid data group item"); + std::string srcPath = item[GROUPLIST_KEY_DIR]; + APPSPAWN_CHECK(!CheckPath(srcPath), return -1, "src path %{public}s is invalid", srcPath.c_str()); + + int elxValue = GetElxInfoFromDir(srcPath.c_str()); + APPSPAWN_CHECK((elxValue >= EL2 && elxValue < ELX_MAX), return -1, "Get elx value failed"); + + const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(elxValue); + APPSPAWN_CHECK(templateItem != nullptr, return -1, "Get data group arg template failed"); + + // If permission isn't null, need check permission flag + if (templateItem->permission != nullptr) { + int index = GetPermissionIndex(nullptr, templateItem->permission); + APPSPAWN_LOGV("mount dir no lock mount permission flag %{public}d", index); + if (CheckAppPermissionFlagSet(property, static_cast(index)) == 0) { + continue; + } + } + + // sandboxPath: /mnt/sandbox///data/storage/el/group + std::string sandboxPath = "/mnt/sandbox/" + std::to_string(info->uid / UID_BASE) + "/" + bundleInfo->bundleName + + templateItem->sandboxPath; + + ret = AddDataGroupItemToQueue(content, srcPath, sandboxPath, item[GROUPLIST_KEY_UUID]); + if (ret != 0) { + APPSPAWN_LOGE("Add datagroup item to dataGroupCtxQueue failed, el%{public}d", elxValue); + OH_ListRemoveAll(&content->dataGroupCtxQueue, nullptr); + return -1; + } + } + + DumpDataGroupCtxQueue(&content->dataGroupCtxQueue); + return ret; +} + +int UpdateDataGroupDirs(AppSpawnMgr *content) +{ + if (content == nullptr) { + return APPSPAWN_ARG_INVALID; + } + + ListNode *node = content->dataGroupCtxQueue.next; + while (node != &content->dataGroupCtxQueue) { + DataGroupCtx *dataGroupNode = (DataGroupCtx *)ListEntry(node, DataGroupCtx, node); + char sandboxPath[PATH_MAX_LEN] = {0}; + int ret = snprintf_s(sandboxPath, PATH_MAX_LEN, PATH_MAX_LEN - 1, "%s%s", dataGroupNode->destPath.path, + dataGroupNode->dataGroupUuid); + if (ret <= 0) { + APPSPAWN_LOGE("snprintf_s sandboxPath: %{public}s failed, errno %{public}d", + dataGroupNode->destPath.path, errno); + return APPSPAWN_ERROR_UTILS_MEM_FAIL; + } + + SharedMountArgs args = { + .srcPath = dataGroupNode->srcPath.path, + .destPath = sandboxPath, + .fsType = nullptr, + .mountFlags = MS_BIND | MS_REC, + .options = nullptr, + .mountSharedFlag = MS_SHARED + }; + ret = DoSharedMount(&args); + if (ret != 0) { + APPSPAWN_LOGE("Shared mount %{public}s to %{public}s failed, errno %{public}d", args.srcPath, + sandboxPath, ret); + } + node = node->next; + } + OH_ListRemoveAll(&content->dataGroupCtxQueue, NULL); + return 0; +} + +static void MountDirToShared(AppSpawnMgr *content, const AppSpawningCtx *property) +{ + if (property == nullptr) { + return; + } + + AppDacInfo *info = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); + AppSpawnMsgBundleInfo *bundleInfo = + reinterpret_cast(GetAppProperty(property, TLV_BUNDLE_INFO)); + if (info == NULL || bundleInfo == NULL) { + return; + } + + MountEl1Bundle(property, info, bundleInfo->bundleName); + + if (IsUnlockStatus(info->uid)) { + return; + } + + MountSharedMap(property, info, bundleInfo->bundleName); + MountStorageUsers(property, info, bundleInfo->bundleName); + ParseDataGroupList(content, property, info, bundleInfo); + + std::string lockSbxPathStamp = "/mnt/sandbox/" + std::to_string(info->uid / UID_BASE) + "/"; + lockSbxPathStamp += CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? "isolated/" : ""; + lockSbxPathStamp += bundleInfo->bundleName; + lockSbxPathStamp += "_locked"; + int ret = MakeDirRec(lockSbxPathStamp.c_str(), DIR_MODE, 1); + if (ret != 0) { + APPSPAWN_LOGE("mkdir %{public}s failed, errno %{public}d", lockSbxPathStamp.c_str(), errno); + } +} +#endif + +int MountToShared(AppSpawnMgr *content, const AppSpawningCtx *property) +{ +#ifndef APPSPAWN_SANDBOX_NEW + // mount dynamic directory to shared + MountDirToShared(content, property); +#endif + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ +#ifndef APPSPAWN_SANDBOX_NEW + (void)AddServerStageHook(STAGE_SERVER_LOCK, HOOK_PRIO_COMMON, UpdateDataGroupDirs); +#endif +} diff --git a/test/appspawn_hap_test/AppScope/app.json5 b/modules/sandbox/sandbox_shared_mount.h similarity index 32% rename from test/appspawn_hap_test/AppScope/app.json5 rename to modules/sandbox/sandbox_shared_mount.h index f94669739bfaf1d0cb4080f75764ce3b92e441b9..ad2e8cd9b993c652520ce41997bb6b971e88e3c7 100644 --- a/test/appspawn_hap_test/AppScope/app.json5 +++ b/modules/sandbox/sandbox_shared_mount.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (C) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,13 +13,55 @@ * limitations under the License. */ -{ - "app": { - "bundleName": "com.example.component", - "vendor": "example", - "versionCode": 1000000, - "versionName": "1.0.0", - "icon": "$media:app_icon", - "label": "$string:app_name" - } +#ifndef SANDBOX_SHARED_MOUNT_H +#define SANDBOX_SHARED_MOUNT_H + +#include "appspawn.h" +#include "appspawn_hook.h" +#include "appspawn_manager.h" +#include "appspawn_utils.h" +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct MountSharedTemplate { + const char *sandboxPath; + const char *permission; +} MountSharedTemplate; + +enum { + EL2 = 0, + EL3, + EL4, + EL5, + ELX_MAX +}; + +typedef struct DataGroupSandboxPathTemplate { + const char *elxName; + uint32_t category; + const char *sandboxPath; + const char *permission; +} DataGroupSandboxPathTemplate; + +typedef struct { + const char *srcPath; + const char *destPath; + const char *fsType; + unsigned long mountFlags; + const char *options; + mode_t mountSharedFlag; +} SharedMountArgs; + +bool IsValidDataGroupItem(nlohmann::json &item); +int GetElxInfoFromDir(const char *path); +const DataGroupSandboxPathTemplate *GetDataGroupArgTemplate(uint32_t category); +void *GetEl1BundleMountCount(void); +int MountToShared(AppSpawnMgr *content, const AppSpawningCtx *property); + +#ifdef __cplusplus } +#endif +#endif // SANDBOX_SHARED_MOUNT_H diff --git a/modules/sandbox/sandbox_utils.cpp b/modules/sandbox/sandbox_utils.cpp index bc897e72b737c95f5100c14763ae85c15ad60cb1..1a6bb911d0b14bf3d39e91f09661c1e78803ee73 100644 --- a/modules/sandbox/sandbox_utils.cpp +++ b/modules/sandbox/sandbox_utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Copyright (C) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -35,6 +35,7 @@ #include "appspawn_service.h" #include "appspawn_utils.h" #include "config_policy_utils.h" +#include "sandbox_shared_mount.h" #ifdef WITH_DLP #include "dlp_fuse_fd.h" #endif @@ -43,6 +44,9 @@ #include "parameter.h" #include "parameters.h" #include "securec.h" +#ifdef APPSPAWN_HISYSEVENT +#include "hisysevent_adapter.h" +#endif #ifdef WITH_SELINUX #include "hap_restorecon.h" @@ -52,6 +56,7 @@ #endif // WITH_SELINUX #define MAX_MOUNT_TIME 500 // 500us +#define LOCK_STATUS_SIZE 16 #define DEV_SHM_DIR "/dev/shm/" using namespace std; @@ -93,6 +98,7 @@ namespace { const std::string g_groupList_key_dataGroupId = "dataGroupId"; const std::string g_groupList_key_gid = "gid"; const std::string g_groupList_key_dir = "dir"; + const std::string g_groupList_key_uuid = "uuid"; const std::string HSPLIST_SOCKET_TYPE = "HspList"; const std::string OVERLAY_SOCKET_TYPE = "Overlay"; const std::string DATA_GROUP_SOCKET_TYPE = "DataGroup"; @@ -126,7 +132,9 @@ namespace { const char *g_sandBoxNsFlags = "sandbox-ns-flags"; const char* g_fileSeparator = "/"; const char* g_overlayDecollator = "|"; + const char *CREATE_SANDBOX_PATH = "create-sandbox-path"; const std::string g_sandBoxRootDir = "/mnt/sandbox/"; + const std::string g_ohosGpu = "__internal__.com.ohos.gpu"; const std::string g_ohosRender = "__internal__.com.ohos.render"; const std::string g_sandBoxRootDirNweb = "/mnt/sandbox/com.ohos.render/"; const std::string FILE_CROSS_APP_MODE = "ohos.permission.FILE_CROSS_APP"; @@ -134,6 +142,7 @@ namespace { const std::string ACCESS_DLP_FILE_MODE = "ohos.permission.ACCESS_DLP_FILE"; const std::string FILE_ACCESS_MANAGER_MODE = "ohos.permission.FILE_ACCESS_MANAGER"; const std::string READ_WRITE_USER_FILE_MODE = "ohos.permission.READ_WRITE_USER_FILE"; + const std::string GET_ALL_PROCESSES_MODE = "ohos.permission.GET_ALL_PROCESSES"; const std::string ARK_WEB_PERSIST_PACKAGE_NAME = "persist.arkwebcore.package_name"; const std::string& getArkWebPackageName() @@ -216,6 +225,37 @@ static void MakeDirRecursive(const std::string &path, mode_t mode) } while (index < size); } +static void MakeDirRecursiveWithClock(const std::string &path, mode_t mode) +{ + size_t size = path.size(); + if (size == 0) { + return; + } +#ifdef APPSPAWN_HISYSEVENT + struct timespec startClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &startClock); +#endif + size_t index = 0; + do { + size_t pathIndex = path.find_first_of('/', index); + index = pathIndex == std::string::npos ? size : pathIndex + 1; + std::string dir = path.substr(0, index); +#ifndef APPSPAWN_TEST + APPSPAWN_CHECK(!(access(dir.c_str(), F_OK) < 0 && mkdir(dir.c_str(), mode) < 0), + return, "errno is %{public}d, mkdir %{public}s failed", errno, dir.c_str()); +#endif + } while (index < size); + +#ifdef APPSPAWN_HISYSEVENT + struct timespec endClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &endClock); + uint64_t diff = DiffTime(&startClock, &endClock); + + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, + ReportAbnormalDuration("MakeDirRecursive", diff)); +#endif +} + static bool CheckDirRecursive(const std::string &path) { size_t size = path.size(); @@ -255,10 +295,33 @@ static void CheckAndCreatFile(const char *file) return; } +static void CheckMountStatus(const std::string &path) +{ + std::ifstream file("/proc/self/mountinfo"); + if (!file.is_open()) { + APPSPAWN_LOGE("Failed to open /proc/self/mountinfo errno %{public}d", errno); + return; + } + + bool flag = false; + std::string line; + while (std::getline(file, line)) { + if (line.find(path) != std::string::npos) { + flag = true; + APPSPAWN_LOGI("Current mountinfo %{public}s", line.c_str()); + } + } + file.close(); + APPSPAWN_CHECK_ONLY_LOG(flag, "Mountinfo not contains %{public}s", path.c_str()); +} + int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char *destinationPath, const char *fsType, unsigned long mountFlags, const char *options, mode_t mountSharedFlag) { + if (originPath == nullptr || destinationPath == nullptr || originPath[0] == '\0' || destinationPath[0] == '\0') { + return 0; + } if (originPath != nullptr && strstr(originPath, "system/etc/hosts") != nullptr) { CheckAndCreatFile(destinationPath); } else { @@ -268,14 +331,17 @@ int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char * int ret = 0; // to mount fs and bind mount files or directory struct timespec mountStart = {0}; - clock_gettime(CLOCK_MONOTONIC, &mountStart); + clock_gettime(CLOCK_MONOTONIC_COARSE, &mountStart); APPSPAWN_LOGV("Bind mount %{public}s to %{public}s '%{public}s' '%{public}lu' '%{public}s' '%{public}u'", - originPath, destinationPath, fsType, mountFlags, options, mountSharedFlag); + originPath, destinationPath, fsType, mountFlags, options, mountSharedFlag); ret = mount(originPath, destinationPath, fsType, mountFlags, options); struct timespec mountEnd = {0}; - clock_gettime(CLOCK_MONOTONIC, &mountEnd); + clock_gettime(CLOCK_MONOTONIC_COARSE, &mountEnd); uint64_t diff = DiffTime(&mountStart, &mountEnd); APPSPAWN_CHECK_ONLY_LOG(diff < MAX_MOUNT_TIME, "mount %{public}s time %{public}" PRId64 " us", originPath, diff); +#ifdef APPSPAWN_HISYSEVENT + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportAbnormalDuration("MOUNT", diff)); +#endif if (ret != 0) { APPSPAWN_LOGI("errno is: %{public}d, bind mount %{public}s to %{public}s", errno, originPath, destinationPath); std::string originPathStr = originPath == nullptr ? "" : originPath; @@ -287,8 +353,14 @@ int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char * } ret = mount(nullptr, destinationPath, nullptr, mountSharedFlag, nullptr); - APPSPAWN_CHECK(ret == 0, return ret, "errno is: %{public}d, private mount to %{public}s %{public}u failed", - errno, destinationPath, mountSharedFlag); + if (ret != 0) { + APPSPAWN_LOGI("errno is: %{public}d, private mount to %{public}s '%{public}u' failed", + errno, destinationPath, mountSharedFlag); + if (errno == EINVAL) { + CheckMountStatus(destinationPath); + } + return ret; + } return 0; } @@ -706,7 +778,8 @@ static uint32_t ConvertFlagStr(const std::string &flagStr) { const std::map flagsMap = {{"0", 0}, {"START_FLAGS_BACKUP", 1}, {"DLP_MANAGER", 2}, - {"DEVELOPER_MODE", 17}}; + {"DEVELOPER_MODE", 17}, + {"PREINSTALLED_HAP", 29}}; if (flagsMap.count(flagStr)) { return 1 << flagsMap.at(flagStr); @@ -788,6 +861,20 @@ static bool CheckMountFlag(const AppSpawningCtx *appProperty, const std::string return false; } +static bool GetCreateSandboxPath(nlohmann::json &json, std::string srcPath) +{ + APPSPAWN_CHECK(json != nullptr && json.is_object(), return true, "json is not object."); + bool isRet = json.find(CREATE_SANDBOX_PATH) != json.end() && json.at(CREATE_SANDBOX_PATH).is_string(); + if (isRet) { + std::string value = json.at(CREATE_SANDBOX_PATH).get(); + APPSPAWN_LOGV("Find create-sandbox-path: %{public}s successful.", value.c_str()); + if (value == "false" && access(srcPath.c_str(), F_OK) != 0) { + return false; + } + } + return true; +} + int SandboxUtils::DoAllMntPointsMount(const AppSpawningCtx *appProperty, nlohmann::json &appConfig, const char *typeName, const std::string §ion) { @@ -810,6 +897,9 @@ int SandboxUtils::DoAllMntPointsMount(const AppSpawningCtx *appProperty, } std::string srcPath = ConvertToRealPath(appProperty, mntPoint[g_srcPath].get()); + if (!GetCreateSandboxPath(mntPoint, srcPath)) { + continue; + } std::string sandboxPath = GetSandboxPath(appProperty, mntPoint, section, sandboxRoot); SandboxMountConfig mountConfig = {0}; GetSandboxMountConfig(appProperty, section, mntPoint, mountConfig); @@ -828,6 +918,10 @@ int SandboxUtils::DoAllMntPointsMount(const AppSpawningCtx *appProperty, if (actionStatus == g_statusCheck) { APPSPAWN_LOGE("DoAppSandboxMountOnce section %{public}s failed, %{public}s", section.c_str(), sandboxPath.c_str()); +#ifdef APPSPAWN_HISYSEVENT + ReportMountFail(bundleName.c_str(), srcPath.c_str(), sandboxPath.c_str(), errno); + ret = APPSPAWN_SANDBOX_MOUNT_FAIL; +#endif return ret; } } @@ -984,8 +1078,12 @@ int32_t SandboxUtils::HandleFlagsPoint(const AppSpawningCtx *appProperty, if (flagPoint.find(g_flags) != flagPoint.end() && flagPoint[g_flags].is_string()) { std::string flagsStr = flagPoint[g_flags].get(); uint32_t flag = ConvertFlagStr(flagsStr); - if ((GetAppMsgFlags(appProperty) & flag) != 0) { - return DoAllMntPointsMount(appProperty, flagPoint, nullptr, g_flagePoint); + if ((GetAppMsgFlags(appProperty) & flag) == 0) { + continue; + } + int ret = DoAllMntPointsMount(appProperty, flagPoint, nullptr, g_flagePoint); + if (ret != 0) { + APPSPAWN_LOGE("mount flag points failed"); } } else { APPSPAWN_LOGE("read flags config failed, app name is %{public}s", GetBundleName(appProperty)); @@ -1095,7 +1193,10 @@ int32_t SandboxUtils::SetRenderSandboxPropertyNweb(const AppSpawningCtx *appProp for (auto& config : SandboxUtils::GetJsonConfig(type)) { nlohmann::json& privateAppConfig = config[g_privatePrefix][0]; - if (privateAppConfig.find(g_ohosRender) != privateAppConfig.end()) { + char *processType = (char *)(GetAppSpawnMsgExtInfo(appProperty->message, MSG_EXT_NAME_PROCESS_TYPE, NULL)); + APPSPAWN_CHECK(processType != NULL, return -1, "Invalid processType data"); + + if (strcmp(processType, "render") == 0 && privateAppConfig.find(g_ohosRender) != privateAppConfig.end()) { int ret = DoAllMntPointsMount(appProperty, privateAppConfig[g_ohosRender][0], nullptr, g_ohosRender); APPSPAWN_CHECK(ret == 0, return ret, "DoAllMntPointsMount failed, %{public}s", GetBundleName(appProperty)); @@ -1105,6 +1206,16 @@ int32_t SandboxUtils::SetRenderSandboxPropertyNweb(const AppSpawningCtx *appProp ret = HandleFlagsPoint(appProperty, privateAppConfig[g_ohosRender][0]); APPSPAWN_CHECK_ONLY_LOG(ret == 0, "HandleFlagsPoint for render-sandbox failed, %{public}s", GetBundleName(appProperty)); + } else if (strcmp(processType, "gpu") == 0 && privateAppConfig.find(g_ohosGpu) != privateAppConfig.end()) { + int ret = DoAllMntPointsMount(appProperty, privateAppConfig[g_ohosGpu][0], nullptr, g_ohosGpu); + APPSPAWN_CHECK(ret == 0, return ret, "DoAllMntPointsMount failed, %{public}s", + GetBundleName(appProperty)); + ret = DoAllSymlinkPointslink(appProperty, privateAppConfig[g_ohosGpu][0]); + APPSPAWN_CHECK(ret == 0, return ret, "DoAllSymlinkPointslink failed, %{public}s", + GetBundleName(appProperty)); + ret = HandleFlagsPoint(appProperty, privateAppConfig[g_ohosGpu][0]); + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "HandleFlagsPoint for render-sandbox failed, %{public}s", + GetBundleName(appProperty)); } } return 0; @@ -1292,40 +1403,45 @@ int32_t SandboxUtils::MountAllGroup(const AppSpawningCtx *appProperty, std::stri } nlohmann::json groups = nlohmann::json::parse(dataGroupInfo.c_str(), nullptr, false); - APPSPAWN_CHECK(!groups.is_discarded() && groups.contains(g_groupList_key_dataGroupId) - && groups.contains(g_groupList_key_gid) && groups.contains(g_groupList_key_dir), return -1, - "MountAllGroup: json parse failed"); - - nlohmann::json& dataGroupIds = groups[g_groupList_key_dataGroupId]; - nlohmann::json& gids = groups[g_groupList_key_gid]; - nlohmann::json& dirs = groups[g_groupList_key_dir]; - APPSPAWN_CHECK(dataGroupIds.is_array() && gids.is_array() && dirs.is_array() && dataGroupIds.size() == gids.size() - && dataGroupIds.size() == dirs.size(), return -1, "MountAllGroup: value is not arrary or sizes are not same"); - APPSPAWN_LOGI("MountAllGroup: app = %{public}s, cnt = %{public}lu", - GetBundleName(appProperty), static_cast(dataGroupIds.size())); - for (uint32_t i = 0; i < dataGroupIds.size(); i++) { - // elements in json arrary can be different type - APPSPAWN_CHECK(dataGroupIds[i].is_string() && gids[i].is_string() && dirs[i].is_string(), - return -1, "MountAllGroup: element type error"); - - std::string libPhysicalPath = dirs[i]; - APPSPAWN_CHECK(!CheckPath(libPhysicalPath), return -1, "MountAllGroup: path error"); - - size_t lastPathSplitPos = libPhysicalPath.find_last_of(g_fileSeparator); - APPSPAWN_CHECK(lastPathSplitPos != std::string::npos, return -1, "MountAllGroup: path error"); + if (groups.is_discarded() && groups.contains(g_groupList_key_dataGroupId) && groups.contains(g_groupList_key_dir) && + groups.contains(g_groupList_key_gid) && groups.contains(g_groupList_key_uuid)) { + APPSPAWN_LOGE("dataGroupJson is discarded"); + return APPSPAWN_ARG_INVALID; + } - std::string dataGroupUuid = libPhysicalPath.substr(lastPathSplitPos + 1); - std::string mntPath = sandboxPackagePath + g_sandboxGroupPath + dataGroupUuid; + for (auto& item : groups) { + // elements in json arrary can be different type + APPSPAWN_CHECK(IsValidDataGroupItem(item), return -1, "MountAllGroup: data group item error"); + std::string srcPath = item[g_groupList_key_dir]; + APPSPAWN_CHECK(!CheckPath(srcPath), return -1, "MountAllGroup: path error"); + + int elxValue = GetElxInfoFromDir(srcPath.c_str()); + APPSPAWN_CHECK((elxValue >= EL2 && elxValue < ELX_MAX), return -1, "Get elx value failed"); + + const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(elxValue); + APPSPAWN_CHECK(templateItem != nullptr, return -1, "Get data group arg template failed"); + + // If permission isn't null, need check permission flag + if (templateItem->permission != nullptr) { + int index = GetPermissionIndex(nullptr, templateItem->permission); + APPSPAWN_LOGV("mount dir no lock mount permission flag %{public}d", index); + if (CheckAppPermissionFlagSet(appProperty, static_cast(index)) == 0) { + continue; + } + } + std::string dataGroupUuid = item[g_groupList_key_uuid]; + std::string mntPath = sandboxPackagePath + templateItem->sandboxPath + dataGroupUuid; mode_t mountFlags = MS_REC | MS_BIND; mode_t mountSharedFlag = MS_SLAVE; if (CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX)) { mountSharedFlag |= MS_REMOUNT | MS_NODEV | MS_RDONLY | MS_BIND; } - ret = DoAppSandboxMountOnce(libPhysicalPath.c_str(), mntPath.c_str(), "", mountFlags, nullptr, - mountSharedFlag); - APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret); + ret = DoAppSandboxMountOnce(srcPath.c_str(), mntPath.c_str(), "", mountFlags, nullptr, mountSharedFlag); + if (ret != 0) { + APPSPAWN_LOGE("mount el%{public}d datagroup failed", elxValue); + } } - return ret; + return 0; } int32_t SandboxUtils::DoSandboxRootFolderCreate(const AppSpawningCtx *appProperty, @@ -1540,7 +1656,7 @@ int32_t SandboxUtils::SetSandboxProperty(AppSpawningCtx *appProperty, std::strin ret = SetBundleResourceAppSandboxProperty(appProperty, sandboxPackagePath); APPSPAWN_CHECK(ret == 0, return ret, "SetBundleResourceAppSandboxProperty failed, packagename is %{public}s", bundleName.c_str()); - APPSPAWN_LOGI("Set appsandbox property success"); + APPSPAWN_LOGV("Set appsandbox property success"); return ret; } @@ -1568,9 +1684,19 @@ int32_t SandboxUtils::ChangeCurrentDir(std::string &sandboxPackagePath, const st return ret; } -static inline int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags) +static int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags) { +#ifdef APPSPAWN_HISYSEVENT + struct timespec startClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &startClock); +#endif int rc = unshare(sandboxNsFlags); +#ifdef APPSPAWN_HISYSEVENT + struct timespec endClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &endClock); + uint64_t diff = DiffTime(&startClock, &endClock); + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportAbnormalDuration("unshare", diff)); +#endif APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", GetBundleName(appProperty)); if ((sandboxNsFlags & CLONE_NEWNET) == CLONE_NEWNET) { @@ -1580,7 +1706,23 @@ static inline int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t s return 0; } -int32_t SandboxUtils::SetPermissionWithParam(AppSpawningCtx *appProperty) +void SandboxUtils::UpdateMsgFlagsWithPermission(AppSpawningCtx *appProperty) +{ + int32_t processIndex = GetPermissionIndex(nullptr, GET_ALL_PROCESSES_MODE.c_str()); + if ((CheckAppPermissionFlagSet(appProperty, static_cast(processIndex)) == 0)) { + APPSPAWN_LOGV("Don't need set GET_ALL_PROCESSES_MODE flag"); + return; + } + + int ret = SetAppSpawnMsgFlag(appProperty->message, TLV_MSG_FLAGS, APP_FLAGS_GET_ALL_PROCESSES); + if (ret != 0) { + APPSPAWN_LOGV("Set GET_ALL_PROCESSES_MODE flag failed"); + } + + return; +} + +int32_t SandboxUtils::UpdatePermissionFlags(AppSpawningCtx *appProperty) { int32_t index = 0; int32_t appFullMountStatus = CheckAppFullMountEnable(); @@ -1598,7 +1740,7 @@ int32_t SandboxUtils::SetPermissionWithParam(AppSpawningCtx *appProperty) } if (index > 0 && (fileMgrIndex > 0 && userFileIndex > 0) && (CheckAppPermissionFlagSet(appProperty, static_cast(userFileIndex)) == 0) && - (CheckAppPermissionFlagSet(appProperty, static_cast(fileMgrIndex))== 0)) { + (CheckAppPermissionFlagSet(appProperty, static_cast(fileMgrIndex)) == 0)) { return SetAppPermissionFlags(appProperty, index); } return 0; @@ -1633,17 +1775,16 @@ int32_t SandboxUtils::SetAppSandboxProperty(AppSpawningCtx *appProperty, uint32_ ACCESS_DLP_FILE_MODE.c_str()))) != 0); sandboxPackagePath += CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? "isolated/" : ""; sandboxPackagePath += bundleName; - MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE); + MakeDirRecursiveWithClock(sandboxPackagePath.c_str(), FILE_MODE); // add pid to a new mnt namespace int rc = EnableSandboxNamespace(appProperty, sandboxNsFlags); APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", bundleName.c_str()); - - if (SetPermissionWithParam(appProperty) != 0) { + if (UpdatePermissionFlags(appProperty) != 0) { APPSPAWN_LOGW("Set app permission flag fail."); return -1; } - + UpdateMsgFlagsWithPermission(appProperty); // check app sandbox switch if ((CheckTotalSandboxSwitchStatus(appProperty) == false) || (CheckAppSandboxSwitchStatus(appProperty) == false)) { @@ -1662,7 +1803,7 @@ int32_t SandboxUtils::SetAppSandboxProperty(AppSpawningCtx *appProperty, uint32_ #ifndef APPSPAWN_TEST rc = ChangeCurrentDir(sandboxPackagePath, bundleName, sandboxSharedStatus); APPSPAWN_CHECK(rc == 0, return rc, "change current dir failed"); - APPSPAWN_LOGI("Change root dir success"); + APPSPAWN_LOGV("Change root dir success"); #if defined(APPSPAWN_MOUNT_TMPSHM) && defined(WITH_SELINUX) Restorecon(DEV_SHM_DIR); #endif // APPSPAWN_MOUNT_TMPSHM && WITH_SELINUX @@ -1680,7 +1821,7 @@ int32_t SandboxUtils::SetAppSandboxPropertyNweb(AppSpawningCtx *appProperty, uin const std::string bundleName = GetBundleName(appProperty); bool sandboxSharedStatus = GetSandboxPrivateSharedStatus(bundleName, appProperty); sandboxPackagePath += bundleName; - MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE); + MakeDirRecursiveWithClock(sandboxPackagePath.c_str(), FILE_MODE); // add pid to a new mnt namespace int rc = EnableSandboxNamespace(appProperty, sandboxNsFlags); @@ -1780,10 +1921,35 @@ int LoadAppSandboxConfig(AppSpawnMgr *content) return 0; } +static bool NeedNetworkIsolated(AppSpawningCtx *property) +{ + int developerMode = IsDeveloperModeOpen(); + if (CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX) && !developerMode) { + return true; + } + + if (CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_NETWORK)) { + std::string extensionType = + OHOS::AppSpawn::SandboxUtils::GetExtraInfoByType(property, MSG_EXT_NAME_EXTENSION_TYPE); + if (extensionType.length() == 0 || !developerMode) { + return true; + } + } + + return false; +} + int32_t SetAppSandboxProperty(AppSpawnMgr *content, AppSpawningCtx *property) { APPSPAWN_CHECK(property != nullptr, return -1, "Invalid appspwn client"); APPSPAWN_CHECK(content != nullptr, return -1, "Invalid appspwn content"); + // clear g_mountInfo in the child process + std::map* mapPtr = static_cast*>(GetEl1BundleMountCount()); + if (mapPtr == nullptr) { + APPSPAWN_LOGE("Get el1 bundle mount count failed"); + return APPSPAWN_ARG_INVALID; + } + mapPtr->clear(); int ret = 0; // no sandbox if (CheckAppMsgFlagsSet(property, APP_FLAGS_NO_SANDBOX)) { @@ -1796,10 +1962,11 @@ int32_t SetAppSandboxProperty(AppSpawnMgr *content, AppSpawningCtx *property) } } uint32_t sandboxNsFlags = CLONE_NEWNS; - if ((CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX) && !IsDeveloperModeOpen()) || - CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_NETWORK)) { + + if (NeedNetworkIsolated(property)) { sandboxNsFlags |= content->content.sandboxNsFlags & CLONE_NEWNET ? CLONE_NEWNET : 0; } + APPSPAWN_LOGV("SetAppSandboxProperty sandboxNsFlags 0x%{public}x", sandboxNsFlags); if (IsNWebSpawnMode(content)) { @@ -1818,131 +1985,63 @@ int32_t SetAppSandboxProperty(AppSpawnMgr *content, AppSpawningCtx *property) #define USER_ID_SIZE 16 #define DIR_MODE 0711 -#ifndef APPSPAWN_SANDBOX_NEW -static bool IsUnlockStatus(uint32_t uid, const char *bundleName, size_t bundleNameLen) +static int SpawnMountDirToShared(AppSpawnMgr *content, AppSpawningCtx *property) { - const int userIdBase = 200000; - uid = uid / userIdBase; - if (uid == 0) { - return true; - } - - const char rootPath[] = "/data/app/el2/"; - const char basePath[] = "/base/"; - size_t allPathSize = strlen(rootPath) + strlen(basePath) + 1 + USER_ID_SIZE + bundleNameLen; - char *path = reinterpret_cast(malloc(sizeof(char) * allPathSize)); - APPSPAWN_CHECK(path != NULL, return true, "Failed to malloc path"); - int len = sprintf_s(path, allPathSize, "%s%u%s%s", rootPath, uid, basePath, bundleName); - APPSPAWN_CHECK(len > 0 && ((size_t)len < allPathSize), free(path); - return true, "Failed to get base path"); - - if (access(path, F_OK) == 0) { - APPSPAWN_LOGI("this is unlock status"); - free(path); - return true; +#ifndef APPSPAWN_SANDBOX_NEW + if (!IsNWebSpawnMode(content)) { + // mount dynamic directory + MountToShared(content, property); } - free(path); - APPSPAWN_LOGI("this is lock status"); - return false; +#endif + return 0; } -static void MountDir(const AppSpawningCtx *property, const char *rootPath, const char *srcPath, const char *targetPath) +static void UmountDir(const char *rootPath, const char *targetPath, const AppSpawnedProcessInfo *appInfo) { - const int userIdBase = 200000; - AppDacInfo *info = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); - const char *bundleName = GetBundleName(property); - if (info == NULL || bundleName == NULL) { - return; - } - - size_t allPathSize = strlen(rootPath) + strlen(targetPath) + strlen(bundleName) + 2; - allPathSize += USER_ID_SIZE; + size_t allPathSize = strlen(rootPath) + USER_ID_SIZE + strlen(appInfo->name) + strlen(targetPath) + 2; char *path = reinterpret_cast(malloc(sizeof(char) * (allPathSize))); APPSPAWN_CHECK(path != NULL, return, "Failed to malloc path"); - int len = sprintf_s(path, allPathSize, "%s%u/%s%s", rootPath, info->uid / userIdBase, bundleName, targetPath); - APPSPAWN_CHECK(len > 0 && ((size_t)len < allPathSize), free(path); - return, "Failed to get sandbox path"); - - if (access(path, F_OK) == 0 && srcPath == nullptr) { - free(path); - return; - } - MakeDirRec(path, DIR_MODE, 1); - const char *sourcePath = (srcPath == nullptr) ? path : srcPath; - if (srcPath != nullptr) { - int ret = umount2(path, MNT_DETACH); - APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to umount path %{public}s, errno %{public}d", path, errno); - } + int ret = sprintf_s(path, allPathSize, "%s%u/%s%s", rootPath, appInfo->uid / UID_BASE, + appInfo->name, targetPath); + APPSPAWN_CHECK(ret > 0 && ((size_t)ret < allPathSize), free(path); + return, "Failed to get sandbox path errno %{public}d", errno); - if (mount(sourcePath, path, nullptr, MS_BIND | MS_REC, nullptr) != 0) { - APPSPAWN_LOGI("bind mount %{public}s to %{public}s failed, error %{public}d", sourcePath, path, errno); - free(path); - return; - } - if (mount(nullptr, path, nullptr, MS_SHARED, nullptr) != 0) { - APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", path, errno); - free(path); - return; + ret = umount2(path, MNT_DETACH); + if (ret == 0) { + APPSPAWN_LOGI("Umount2 sandbox path %{public}s success", path); + } else { + APPSPAWN_LOGW("Failed to umount2 sandbox path %{public}s errno %{public}d", path, errno); } - APPSPAWN_LOGI("mount path %{public}s to shared success", path); free(path); - return; } -static const MountSharedTemplate MOUNT_SHARED_MAP[] = { - {"/data/storage/el2", nullptr}, - {"/data/storage/el3", nullptr}, - {"/data/storage/el4", nullptr}, - {"/data/storage/el5", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"}, - {"/storage/Users", "ohos.permission.FILE_ACCESS_MANAGER"}, -}; - -static void MountDirToShared(const AppSpawningCtx *property) +static int UmountSandboxPath(const AppSpawnMgr *content, const AppSpawnedProcessInfo *appInfo) { + APPSPAWN_CHECK(content != NULL && appInfo != NULL && appInfo->name != NULL, + return -1, "Invalid content or appInfo"); + if (IsNWebSpawnMode(content)) { + return 0; + } + APPSPAWN_LOGV("UmountSandboxPath name %{public}s pid %{public}d", appInfo->name, appInfo->pid); const char rootPath[] = "/mnt/sandbox/"; const char el1Path[] = "/data/storage/el1/bundle"; - const char lockSuffix[] = "_locked"; - AppDacInfo *info = reinterpret_cast(GetAppProperty(property, TLV_DAC_INFO)); - const char *bundleName = GetBundleName(property); - if (info == NULL || bundleName == NULL) { - return; - } - string sourcePath = "/data/app/el1/bundle/public/" + string(bundleName); - MountDir(property, rootPath, sourcePath.c_str(), el1Path); - size_t bundleNameLen = strlen(bundleName); - if (IsUnlockStatus(info->uid, bundleName, bundleNameLen)) { - return; + uint32_t userId = appInfo->uid / UID_BASE; + std::string key = std::to_string(userId) + "-" + std::string(appInfo->name); + map *el1BundleCountMap = static_cast*>(GetEl1BundleMountCount()); + if (el1BundleCountMap == nullptr || el1BundleCountMap->find(key) == el1BundleCountMap->end()) { + return 0; } - - int length = sizeof(MOUNT_SHARED_MAP) / sizeof(MOUNT_SHARED_MAP[0]); - for (int i = 0; i < length; i++) { - if (MOUNT_SHARED_MAP[i].permission == nullptr) { - MountDir(property, rootPath, nullptr, MOUNT_SHARED_MAP[i].sandboxPath); - } else { - int index = GetPermissionIndex(nullptr, MOUNT_SHARED_MAP[i].permission); - APPSPAWN_LOGV("mount dir on lock mountPermissionFlags %{public}d", index); - if (CheckAppPermissionFlagSet(property, static_cast(index))) { - MountDir(property, rootPath, nullptr, MOUNT_SHARED_MAP[i].sandboxPath); - } - } + (*el1BundleCountMap)[key]--; + if ((*el1BundleCountMap)[key] == 0) { + APPSPAWN_LOGV("no app %{public}s use it in userId %{public}u, need umount", appInfo->name, userId); + UmountDir(rootPath, el1Path, appInfo); + el1BundleCountMap->erase(key); + } else { + APPSPAWN_LOGV("app %{public}s use it mount times %{public}d in userId %{public}u, not need umount", + appInfo->name, (*el1BundleCountMap)[key], userId); } - - std::string lockSbxPathStamp = rootPath + to_string(info->uid / UID_BASE) + "/"; - lockSbxPathStamp += CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? "isolated/" : ""; - lockSbxPathStamp += bundleName; - lockSbxPathStamp += lockSuffix; - OHOS::AppSpawn::MakeDirRecursive(lockSbxPathStamp.c_str(), OHOS::AppSpawn::FILE_MODE); -} -#endif - -static int SpawnMountDirToShared(AppSpawnMgr *content, AppSpawningCtx *property) -{ -#ifndef APPSPAWN_SANDBOX_NEW - // mount dynamic directory - MountDirToShared(property); -#endif return 0; } @@ -1953,5 +2052,6 @@ MODULE_CONSTRUCTOR(void) (void)AddServerStageHook(STAGE_SERVER_PRELOAD, HOOK_PRIO_SANDBOX, LoadAppSandboxConfig); (void)AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_COMMON, SpawnMountDirToShared); (void)AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_SANDBOX, SetAppSandboxProperty); + (void)AddProcessMgrHook(STAGE_SERVER_APP_UMOUNT, HOOK_PRIO_SANDBOX, UmountSandboxPath); } #endif diff --git a/modules/sandbox/sandbox_utils.h b/modules/sandbox/sandbox_utils.h index 429f09526eb66caa6ad577a5a982886e4707ea66..1ad93280af16cde5d56284860c8278fe8b9a32fb 100755 --- a/modules/sandbox/sandbox_utils.h +++ b/modules/sandbox/sandbox_utils.h @@ -107,7 +107,8 @@ private: static int32_t DoAddGid(AppSpawningCtx *appProperty, nlohmann::json &appConfig, const char* permissionName, const std::string §ion); static int32_t CheckAppFullMountEnable(); - static int32_t SetPermissionWithParam(AppSpawningCtx *appProperty); + static void UpdateMsgFlagsWithPermission(AppSpawningCtx *appProperty); + static int32_t UpdatePermissionFlags(AppSpawningCtx *appProperty); static int32_t SetSandboxProperty(AppSpawningCtx *appProperty, std::string &sandboxPackagePath); static int32_t ChangeCurrentDir(std::string &sandboxPackagePath, const std::string &bundleName, bool sandboxSharedStatus); @@ -119,7 +120,7 @@ private: static std::string GetSandboxPath(const AppSpawningCtx *appProperty, nlohmann::json &mntPoint, const std::string §ion, std::string sandboxRoot); static void GetSandboxMountConfig(const AppSpawningCtx *appProperty, const std::string §ion, - nlohmann::json &mntPoint,SandboxMountConfig &mountConfig); + nlohmann::json &mntPoint, SandboxMountConfig &mountConfig); #ifdef APPSPAWN_MOUNT_TMPSHM static void MountDevShmPath(std::string &sandboxPath); #endif @@ -136,9 +137,4 @@ public: int LoadAppSandboxConfig(AppSpawnMgr *content); -typedef struct { - const char *sandboxPath; - const char *permission; -} MountSharedTemplate; - #endif // SANDBOX_UTILS_H diff --git a/modules/sysevent/hisysevent_adapter.cpp b/modules/sysevent/hisysevent_adapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..78711cf7444787a7a03c1ba41571e0dad4c07cd2 --- /dev/null +++ b/modules/sysevent/hisysevent_adapter.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "hisysevent_adapter.h" +#include "securec.h" +#include "hisysevent.h" +#include "appspawn_utils.h" + +using namespace OHOS::HiviewDFX; +namespace { +// fail event +constexpr const char* SPAWN_CHILD_PROCESS_FAIL = "SPAWN_CHILD_PROCESS_FAIL"; + +// behavior event +constexpr const char* SPAWN_KEY_EVENT = "SPAWN_KEY_EVENT"; +constexpr const char* SPAWN_ABNORMAL_DURATION = "SPAWN_ABNORMAL_DURATION"; + +// statistic event +constexpr const char* SPAWN_PROCESS_DURATION = "SPAWN_PROCESS_DURATION"; + +// param +constexpr const char* PROCESS_NAME = "PROCESS_NAME"; +constexpr const char* ERROR_CODE = "ERROR_CODE"; +constexpr const char* SPAWN_RESULT = "SPAWN_RESULT"; +constexpr const char* SRC_PATH = "SRC_PATH"; +constexpr const char* TARGET_PATH = "TARGET_PATH"; + +constexpr const char* EVENT_NAME = "EVENT_NAME"; + +constexpr const char* SCENE_NAME = "SCENE_NAME"; +constexpr const char* DURATION = "DURATION"; + +constexpr const char* MAXDURATION = "MAXDURATION"; +constexpr const char* MINDURATION = "MINDURATION"; +constexpr const char* TOTALDURATION = "TOTALDURATION"; +constexpr const char* EVENTCOUNT = "EVENTCOUNT"; +constexpr const char* STAGE = "STAGE"; +constexpr const char* BOOTSTAGE = "BOOTSTAGE"; +constexpr const char* BOOTFINISHEDSTAGE = "BOOTFINISHEDSTAGE"; +} + +static void AddStatisticEvent(AppSpawnHisysevent *event, uint32_t duration) +{ + event->eventCount++; + event->totalDuration += duration; + if (duration > event->maxDuration) { + event->maxDuration = duration; + } + if (duration < event->minDuration) { + event->minDuration = duration; + } + APPSPAWN_LOGV("event->maxDuration is: %{public}d, event->minDuration is: %{public}d", + event->maxDuration, event->minDuration); +} + +void AddStatisticEventInfo(AppSpawnHisyseventInfo *hisyseventInfo, uint32_t duration, bool stage) +{ + APPSPAWN_CHECK(hisyseventInfo != NULL, return, "fail to get AppSpawnHisyseventInfo"); + if (stage) { + AddStatisticEvent(&hisyseventInfo->bootEvent, duration); + } else { + AddStatisticEvent(&hisyseventInfo->manualEvent, duration); + } +} + +static void InitStatisticEvent(AppSpawnHisysevent *event) +{ + event->eventCount = 0; + event->maxDuration = 0; + event->minDuration = UINT32_MAX; + event->totalDuration = 0; +} + +static void InitStatisticEventInfo(AppSpawnHisyseventInfo *appSpawnHisysInfo) +{ + InitStatisticEvent(&appSpawnHisysInfo->bootEvent); + InitStatisticEvent(&appSpawnHisysInfo->manualEvent); +} + +static int CreateHisysTimerLoop(AppSpawnHisyseventInfo *hisyseventInfo) +{ + LoopHandle loop = LE_GetDefaultLoop(); + TimerHandle timer = NULL; + int ret = LE_CreateTimer(loop, &timer, ReportSpawnStatisticDuration, (void *)hisyseventInfo); + APPSPAWN_CHECK(ret == 0, return -1, "fail to create HisysTimer, ret is: %{public}d", ret); + // start a timer to report event every 24h + ret = LE_StartTimer(loop, timer, APPSPAWN_HISYSEVENT_REPORT_TIME, INT64_MAX); + APPSPAWN_CHECK(ret == 0, return -1, "fail to start HisysTimer, ret is: %{public}d", ret); + return ret; +} + +AppSpawnHisyseventInfo *GetAppSpawnHisyseventInfo(void) +{ + AppSpawnHisyseventInfo *hisyseventInfo = + static_cast(malloc(sizeof(AppSpawnHisyseventInfo))); + APPSPAWN_CHECK(hisyseventInfo != NULL, return NULL, "fail to alloc memory for hisyseventInfo"); + int ret = memset_s(hisyseventInfo, sizeof(AppSpawnHisyseventInfo), 0, sizeof(AppSpawnHisyseventInfo)); + if (ret != 0) { + free(hisyseventInfo); + hisyseventInfo = NULL; + APPSPAWN_LOGE("Failed to memset hisyseventInfo"); + return NULL; + } + InitStatisticEventInfo(hisyseventInfo); + return hisyseventInfo; +} + +void DeleteHisyseventInfo(AppSpawnHisyseventInfo *hisyseventInfo) +{ + APPSPAWN_CHECK_ONLY_EXPER(hisyseventInfo != NULL, return); + free(hisyseventInfo); + hisyseventInfo = NULL; +} + +AppSpawnHisyseventInfo *InitHisyseventTimer(void) +{ + AppSpawnHisyseventInfo *hisyseventInfo = GetAppSpawnHisyseventInfo(); + APPSPAWN_CHECK(hisyseventInfo != NULL, return NULL, "fail to init hisyseventInfo"); + int ret = CreateHisysTimerLoop(hisyseventInfo); + if (ret != 0) { + DeleteHisyseventInfo(hisyseventInfo); + hisyseventInfo = NULL; + APPSPAWN_LOGE("fail to create hisys timer loop, ret: %{public}d", ret); + } + return hisyseventInfo; +} + +void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode, int32_t spawnResult) +{ + if (spawnResult == APPSPAWN_SANDBOX_MOUNT_FAIL) { + return; + } + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_CHILD_PROCESS_FAIL, + HiSysEvent::EventType::FAULT, + PROCESS_NAME, processName, + ERROR_CODE, errorCode, + SPAWN_RESULT, spawnResult); + if (ret != 0) { + APPSPAWN_LOGE("ReportSpawnChildProcessFail error, ret: %{public}d", ret); + } +} + +void ReportMountFail(const char* bundleName, const char* srcPath, const char* targetPath, + int32_t spawnResult) +{ + if (srcPath == nullptr || (strstr(srcPath, "data/app/el1/") == nullptr && + strstr(srcPath, "data/app/el2/") == nullptr)) { + return; + } + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_CHILD_PROCESS_FAIL, + HiSysEvent::EventType::FAULT, + PROCESS_NAME, bundleName, + ERROR_CODE, ERR_APPSPAWN_CHILD_MOUNT_FAILED, + SRC_PATH, srcPath, + TARGET_PATH, targetPath, + SPAWN_RESULT, spawnResult); + if (ret != 0) { + APPSPAWN_LOGE("ReportMountFail error, ret: %{public}d", ret); + } +} + +void ReportKeyEvent(const char *eventName) +{ + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_KEY_EVENT, + HiSysEvent::EventType::BEHAVIOR, + EVENT_NAME, eventName); + if (ret != 0) { + APPSPAWN_LOGE("ReportKeyEvent error, ret: %{public}d", ret); + } +} + +void ReportAbnormalDuration(const char* scene, uint64_t duration) +{ + APPSPAWN_LOGI("ReportAbnormalDuration %{public}d with %{public}s %{public}" PRId64 " us", + getpid(), scene, duration); + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_ABNORMAL_DURATION, + HiSysEvent::EventType::BEHAVIOR, + SCENE_NAME, scene, + DURATION, duration); + if (ret != 0) { + APPSPAWN_LOGE("ReportAbnormalDuration error, ret: %{public}d", ret); + } +} + +void ReportSpawnProcessDuration(AppSpawnHisysevent *hisysevent, const char* stage) +{ + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_PROCESS_DURATION, + HiSysEvent::EventType::STATISTIC, + MAXDURATION, hisysevent->maxDuration, + MINDURATION, hisysevent->minDuration, + TOTALDURATION, hisysevent->totalDuration, + EVENTCOUNT, hisysevent->eventCount, + STAGE, stage); + if (ret != 0) { + APPSPAWN_LOGE("ReportSpawnProcessDuration error, ret: %{public}d", ret); + } +} + +void ReportSpawnStatisticDuration(const TimerHandle taskHandle, void *content) +{ + AppSpawnHisyseventInfo *hisyseventInfo = static_cast(content); + ReportSpawnProcessDuration(&hisyseventInfo->bootEvent, BOOTSTAGE); + ReportSpawnProcessDuration(&hisyseventInfo->manualEvent, BOOTFINISHEDSTAGE); + + InitStatisticEventInfo(hisyseventInfo); +} \ No newline at end of file diff --git a/modules/sysevent/hisysevent_adapter.h b/modules/sysevent/hisysevent_adapter.h new file mode 100644 index 0000000000000000000000000000000000000000..1e9fb62e6164c4b1cd8a3253e6b5836f6f964e9a --- /dev/null +++ b/modules/sysevent/hisysevent_adapter.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APPSPAWN_HISYSEVENT_ADAPTER_H +#define APPSPAWN_HISYSEVENT_ADAPTER_H + +#include "appspawn_utils.h" +#include "loop_event.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// 错误码定义规范:子系统ID(28-21位)| 模块ID(20-16位)| 具体错误ID(15-0位) +#define APPSPAWN_HISYSEVENT_REPORT_TIME (24 * 60 * 60 * 1000) // 24h +#define SUBSYS_STARTUP_ID 39 +#define SUBSYSTEM_BIT_NUM 21 +#define MODULE_BIT_NUM 16 +#define ERR_MODULE_APPSPAWN 0x00 +#define ERR_MODULE_INIT 0x10 +#define ERR_APPSPAWN_BASE ((SUBSYS_STARTUP_ID << SUBSYSTEM_BIT_NUM) | (ERR_MODULE_APPSPAWN << MODULE_BIT_NUM)) +#define ERR_INIT_BASE ((SUBSYS_STARTUP_ID << SUBSYSTEM_BIT_NUM) | (ERR_MODULE_INIT << MODULE_BIT_NUM)) + +typedef enum { + // errcode for handle msg, reserved 128, 0x0001-0x0080 + ERR_APPSPAWN_MSG_TOO_LONG = ERR_APPSPAWN_BASE + 0x0001, // 81788929 + ERR_APPSPAWN_MSG_INVALID_HANDLE, + ERR_APPSPAWN_MSG_CREATE_MSG_FAILED, + ERR_APPSPAWN_COPY_MSG_FAILED, + ERR_APPSPAWN_ALLOC_MEMORY_FAILED, + ERR_APPSPAWN_MSG_DECODE_MSG_FAILED, + + // errcode for hnp, reserved 128, 0x0081 - 0x0100 + ERR_APPSPAWN_HNP = ERR_APPSPAWN_BASE + 0x0081, + + // errcode for device_dug, reserved 128, 0x0101 - 0x0180 + ERR_APPSPAWN_DEVICE_DUG = ERR_APPSPAWN_BASE + 0x0101, + + // errcode for process_exit, reserved 128, 0x0181 - 0x0200 + ERR_APPSPAWN_PROCESS_EXIT = ERR_APPSPAWN_BASE + 0x0181, + + // errcode for prefork, reserved 128, 0x0201 - 0x0280 + ERR_APPSPAWN_PREFORK = ERR_APPSPAWN_BASE + 0x0201, + + // errcode for sandbox, reserved 128, 0x0281 - 0x0300 + ERR_APPSPAWN_SANDBOX = ERR_APPSPAWN_BASE + 0x0281, + + // errcode for set permission, reserved 128, 0x0301 - 0x0380 + ERR_APPSPAWN_SET_PERMISSION = ERR_APPSPAWN_BASE + 0x0301, + ERR_APPSPAWN_SET_INTE_PERMISSION_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_KEEP_CAP_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_XPM_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_PROCESSNAME_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_UIDGID_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_FD_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_CAP_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_SELINUXCON_FAIL, + + // errorcode for spawn child process fail, reserved 128, 0x0381 - 0x0400 + ERR_APPSPAWN_SPAWN_FAIL = ERR_APPSPAWN_BASE + 0x0381, + ERR_APPSPAWN_SPAWN_TIMEOUT, + ERR_APPSPAWN_CHILD_CRASH, + ERR_APPSPAWN_CHILD_MOUNT_FAILED, + ERR_APPSPAWN_MAX_FAILURES_EXCEEDED, +} AppSpawnHisysErrorCode; + +typedef struct { + uint32_t eventCount; + uint32_t maxDuration; + uint32_t minDuration; + uint32_t totalDuration; +} AppSpawnHisysevent; + +typedef struct { + AppSpawnHisysevent bootEvent; // bootStage + AppSpawnHisysevent manualEvent; // bootFinished +} AppSpawnHisyseventInfo; + +#define FUNC_REPORT_DURATION (20 * 1000) +#define SPAWN_DURATION (120 * 1000) +#define SPAWN_COLDRUN_DURATION (5 * 1000 * 1000) + +#define UNLOCK_SUCCESS "UNLOCK_SUCCESS" +#define LOCK_SUCCESS "LOCK_SUCCESS" +#define APPSPAWN_MAX_FAILURES_EXCEEDED "APPSPAWN_MAX_FAILURES_EXCEEDED" +AppSpawnHisyseventInfo *InitHisyseventTimer(void); +AppSpawnHisyseventInfo *GetAppSpawnHisyseventInfo(void); +void AddStatisticEventInfo(AppSpawnHisyseventInfo *hisyseventInfo, uint32_t duration, bool stage); +void DeleteHisyseventInfo(AppSpawnHisyseventInfo *hisyseventInfo); + +void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode, int32_t spawnResult); +void ReportMountFail(const char* bundleName, const char* srcPath, const char* targetPath, + int32_t spawnResult); +void ReportKeyEvent(const char *eventName); +void ReportAbnormalDuration(const char* funcName, uint64_t duration); +void ReportSpawnStatisticDuration(const TimerHandle taskHandle, void* content); + +#ifdef __cplusplus +} +#endif +#endif // APPSPAWN_HISYSEVENT_ADAPTER_H \ No newline at end of file diff --git a/service/devicedebug/devicedebug_main.c b/service/devicedebug/devicedebug_main.c index 5aa22a9c5d6b6520cbcc6e1870ebe1ff655a2f7b..72e6449733609b85abada99bfa1876faf43e9f14 100644 --- a/service/devicedebug/devicedebug_main.c +++ b/service/devicedebug/devicedebug_main.c @@ -38,7 +38,7 @@ APPSPAWN_STATIC int DeviceDebugShowHelp(int argc, char *argv[]) printf("\r\nusage: devicedebug \r\n" "\r\nThese are common devicedebug commands list:\r\n" "\r\n help list available commands" - "\r\n kill send a signal to a process\r\n"); + "\r\n kill send a signal(1-64) to a process\r\n"); return 0; } @@ -76,7 +76,9 @@ int main(int argc, char *argv[]) /* 检验用户命令,获取对应的处理函数 */ cmdInfo = DeviceDebugCmdCheck(argv[DEVICEDEBUG_NUM_1]); if (cmdInfo == NULL) { - DEVICEDEBUG_LOGE("invalid cmd!. cmd:%{public}s\r\n", argv[DEVICEDEBUG_NUM_1]); + printf("devicedebug: '%s' is not a valid devicedebug command. See 'devicedebug help'.", + argv[DEVICEDEBUG_NUM_1]); + DeviceDebugShowHelp(argc, argv); return DEVICEDEBUG_ERRNO_OPERATOR_TYPE_INVALID; } diff --git a/service/devicedebug/kill/src/devicedebug_kill.c b/service/devicedebug/kill/src/devicedebug_kill.c index 5bb0a1b78aa780fe5a29b46d4f8a0b23299d992b..bd6fcc54dc298a02298ac42cb1ae039dd53e477b 100644 --- a/service/devicedebug/kill/src/devicedebug_kill.c +++ b/service/devicedebug/kill/src/devicedebug_kill.c @@ -36,13 +36,14 @@ APPSPAWN_STATIC void DeviceDebugShowKillHelp(void) printf("\r\nusage: devicedebug kill [options] " "\r\noptions list:" "\r\n -h, --help list available commands" - "\r\n kill - send a signal to a process\r\n"); + "\r\n kill - send a signal(1-64) to a process\r\n"); } APPSPAWN_STATIC char* DeviceDebugJsonStringGeneral(int pid, const char *op, cJSON *args) { cJSON *root = cJSON_CreateObject(); if (root == NULL) { + cJSON_Delete(args); DEVICEDEBUG_LOGE("devicedebug json write create root object unsuccess"); return NULL; } @@ -56,22 +57,24 @@ APPSPAWN_STATIC char* DeviceDebugJsonStringGeneral(int pid, const char *op, cJSO return jsonString; } -APPSPAWN_STATIC int DeviceDebugKill(int pid, int signal) +APPSPAWN_STATIC void DevicedebugKillRetDeal(int result, int pid) { - AppSpawnClientHandle clientHandle; - int ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle); - if (ret != 0) { - DEVICEDEBUG_LOGE("devicedebug appspawn client init unsuccess, ret=%{public}d", ret); - return ret; - } - - AppSpawnReqMsgHandle reqHandle; - ret = AppSpawnReqMsgCreate(MSG_DEVICE_DEBUG, "devicedebug", &reqHandle); - if (ret != 0) { - DEVICEDEBUG_LOGE("devicedebug appspawn message create unsuccess, ret=%{public}d", ret); - return ret; + switch (result) { + case APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_EXIST: + printf("devicedebug: kill: %d: No such app process\r\n", pid); + break; + case APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_DEBUGGABLE: + printf("devicedebug: kill: process: %d is not debuggable app\r\n", pid); + break; + default: + printf("devicedebug: process: %d kill unsuccess ret=%d, please check the hilog for the cause\r\n", + pid, result); + break; } +} +APPSPAWN_STATIC int DeviceDebugKill(int pid, int signal) +{ cJSON *args = cJSON_CreateObject(); if (args == NULL) { DEVICEDEBUG_LOGE("devicedebug json write create args object unsuccess"); @@ -80,27 +83,45 @@ APPSPAWN_STATIC int DeviceDebugKill(int pid, int signal) cJSON_AddNumberToObject(args, "signal", signal); char *jsonString = DeviceDebugJsonStringGeneral(pid, "kill", args); if (jsonString == NULL) { - cJSON_Delete(args); return DEVICEDEBUG_ERRNO_JSON_CREATED_FAILED; } + AppSpawnReqMsgHandle reqHandle; + int ret = AppSpawnReqMsgCreate(MSG_DEVICE_DEBUG, "devicedebug", &reqHandle); + if (ret != 0) { + free(jsonString); + DEVICEDEBUG_LOGE("devicedebug appspawn message create unsuccess, ret=%{public}d", ret); + return ret; + } + ret = AppSpawnReqMsgAddExtInfo(reqHandle, "devicedebug", (uint8_t *)jsonString, strlen(jsonString) + 1); if (ret != 0) { DEVICEDEBUG_LOGE("devicedebug appspawn message add devicedebug[%{public}s] unsuccess, ret=%{public}d", jsonString, ret); + free(jsonString); + AppSpawnReqMsgFree(reqHandle); + return ret; + } + + AppSpawnClientHandle clientHandle; + ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle); + if (ret != 0) { + free(jsonString); + AppSpawnReqMsgFree(reqHandle); + DEVICEDEBUG_LOGE("devicedebug appspawn client init unsuccess, ret=%{public}d", ret); return ret; } AppSpawnResult result = {0}; ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); AppSpawnClientDestroy(clientHandle); + free(jsonString); if (ret != 0) { DEVICEDEBUG_LOGE("devicedebug appspawn send msg unsuccess, ret=%{public}d", ret); return ret; } if (result.result != 0) { - DEVICEDEBUG_LOGE("devicedebug appspawn kill process unsuccess, result=%{public}d", result.result); return result.result; } @@ -127,7 +148,7 @@ int DeviceDebugCmdKill(int argc, char *argv[]) int signal = atoi(argv[DEVICEDEBUG_KILL_CMD_SIGNAL_INDEX] + 1); if (signal > SIGRTMAX || signal <= 0) { - DEVICEDEBUG_LOGE("signal is %{public}d > %{public}d", signal, SIGRTMAX); + DEVICEDEBUG_LOGE("signal is %{public}d not in [1, %{public}d]", signal, SIGRTMAX); DeviceDebugShowKillHelp(); return DEVICEDEBUG_ERRNO_PARAM_INVALID; } @@ -135,7 +156,12 @@ int DeviceDebugCmdKill(int argc, char *argv[]) int pid = atoi(argv[DEVICEDEBUG_KILL_CMD_PID_INDEX]); DEVICEDEBUG_LOGI("devicedebug cmd kill start signal[%{public}d], pid[%{public}d]", signal, pid); - return DeviceDebugKill(pid, signal); + int ret = DeviceDebugKill(pid, signal); + if (ret != 0) { + DevicedebugKillRetDeal(ret, pid); + } + + return ret; } #ifdef __cplusplus diff --git a/service/hnp/BUILD.gn b/service/hnp/BUILD.gn index ff0d57b049674809b0a5fbe1ccc992cf96900be1..d2f675ea9a88b2d0b43074316abbed765a5024aa 100644 --- a/service/hnp/BUILD.gn +++ b/service/hnp/BUILD.gn @@ -33,14 +33,19 @@ if (!defined(ohos_lite)) { external_deps = [ "bounds_checking_function:libsec_shared", "cJSON:cjson", - "code_signature:libcode_sign_utils", "hilog:libhilog", "selinux_adapter:librestorecon", "zlib:shared_libz", ] + + if (appspawn_support_code_signature) { + external_deps += [ "code_signature:libcode_sign_utils" ] + } + defines = [] if (defined(global_parts_info) && - defined(global_parts_info.security_code_signature)) { + defined(global_parts_info.security_code_signature) && + appspawn_support_code_signature) { defines += [ "CODE_SIGNATURE_ENABLE" ] } install_enable = true diff --git a/service/hnp/base/hnp_base.h b/service/hnp/base/hnp_base.h index 1f57789034e34cec25aaad629a03597f8328af85..5129a0de0d9793e3c2b49818a23d972d41947b03 100644 --- a/service/hnp/base/hnp_base.h +++ b/service/hnp/base/hnp_base.h @@ -40,8 +40,12 @@ extern "C" { #endif #ifndef MAX_FILE_PATH_LEN +#if PATH_MAX > 4096 +#define MAX_FILE_PATH_LEN PATH_MAX +#else #define MAX_FILE_PATH_LEN 4096 #endif +#endif #define HNP_VERSION_LEN 32 #define BUFFER_SIZE 1024 @@ -255,6 +259,9 @@ enum { // 0x80111f 获取文件属性失败 #define HNP_ERRNO_BASE_STAT_FAILED HNP_ERRNO_COMMON(HNP_MID_BASE, 0x1f) +// 0x801120 二进制文件过多 +#define HNP_ERRNO_BASE_FILE_COUNT_OVER HNP_ERRNO_COMMON(HNP_MID_BASE, 0x20) + int GetFileSizeByHandle(FILE *file, int *size); int ReadFileToStream(const char *filePath, char **stream, int *streamLen); diff --git a/service/hnp/base/hnp_json.c b/service/hnp/base/hnp_json.c index 148809a7f15d1f095aad6217cbeaeebbf4f96ce4..6ce5bef22e60db5b2119864a77358f3d89ab35e9 100644 --- a/service/hnp/base/hnp_json.c +++ b/service/hnp/base/hnp_json.c @@ -257,6 +257,11 @@ static int HnpHapJsonWrite(cJSON *json) return HNP_ERRNO_BASE_FILE_OPEN_FAILED; } char *jsonStr = cJSON_Print(json); + if (jsonStr == NULL) { + HNP_LOGE("get json str unsuccess!"); + (void)fclose(fp); + return HNP_ERRNO_BASE_PARAMS_INVALID; + } size_t jsonStrSize = strlen(jsonStr); size_t writeLen = fwrite(jsonStr, sizeof(char), jsonStrSize, fp); (void)fclose(fp); @@ -478,6 +483,12 @@ int HnpPackageInfoGet(const char *packageName, HnpPackageInfo **packageInfoOut, hnpExist = HnpOtherPackageInstallCheck(name->valuestring, version->valuestring, hapIndex, json); // 当卸载当前版本未被其他hap使用或者存在安装版本的时候,需要卸载对应的当前版本或者安装版本 if (!hnpExist || strcmp(installVersion->valuestring, "none") != 0) { + if (sum >= MAX_PACKAGE_HNP_NUM - 1) { + HNP_LOGE("package info num over limit"); + cJSON_Delete(json); + return HNP_ERRNO_BASE_FILE_COUNT_OVER; + } + if ((strcpy_s(packageInfos[sum].name, MAX_FILE_PATH_LEN, name->valuestring) != EOK) || (strcpy_s(packageInfos[sum].currentVersion, HNP_VERSION_LEN, version->valuestring) != EOK) || (strcpy_s(packageInfos[sum].installVersion, HNP_VERSION_LEN, installVersion->valuestring) != EOK)) { @@ -586,9 +597,10 @@ static char *HnpNeedUnInstallHnpVersionGet(cJSON *hnpItemArr, const char *name) cJSON *nameItem = cJSON_GetObjectItem(hnpItem, "name"); cJSON *currentItem = cJSON_GetObjectItem(hnpItem, "current_version"); cJSON *installItem = cJSON_GetObjectItem(hnpItem, "install_version"); - if ((nameItem != NULL) && (currentItem != NULL) && (installItem != NULL) && (cJSON_IsString(nameItem)) && - (cJSON_IsString(currentItem)) && (cJSON_IsString(installItem)) && - (strcmp(nameItem->valuestring, name) == 0) && + if ((nameItem != NULL) && (currentItem != NULL) && (installItem != NULL) && + (cJSON_IsString(nameItem)) && (cJSON_IsString(currentItem)) && (cJSON_IsString(installItem)) && + (nameItem->valuestring != NULL) && (strcmp(nameItem->valuestring, name) == 0) && + (currentItem->valuestring != NULL) && (installItem->valuestring != NULL) && (strcmp(currentItem->valuestring, installItem->valuestring) == 0)) { version = strdup(currentItem->valuestring); return version; @@ -600,6 +612,9 @@ static char *HnpNeedUnInstallHnpVersionGet(cJSON *hnpItemArr, const char *name) char *HnpCurrentVersionGet(const char *name) { + if (name == NULL) { + return NULL; + } char *infoStream; int size; cJSON *hapItem = NULL; @@ -630,7 +645,8 @@ char *HnpCurrentVersionGet(const char *name) cJSON *nameItem = cJSON_GetObjectItem(hnpItem, "name"); cJSON *versionItem = cJSON_GetObjectItem(hnpItem, "current_version"); if ((nameItem != NULL) && (versionItem != NULL) && (cJSON_IsString(nameItem)) && - (cJSON_IsString(versionItem)) && (strcmp(nameItem->valuestring, name) == 0)) { + (cJSON_IsString(versionItem)) && (versionItem->valuestring != NULL) && + (nameItem->valuestring != NULL) && (strcmp(nameItem->valuestring, name) == 0)) { version = strdup(versionItem->valuestring); cJSON_Delete(json); return version; @@ -644,6 +660,9 @@ char *HnpCurrentVersionGet(const char *name) char *HnpCurrentVersionUninstallCheck(const char *name) { + if (name == NULL) { + return NULL; + } char *infoStream; int size; cJSON *hapItem = NULL; diff --git a/service/hnp/base/hnp_zip.c b/service/hnp/base/hnp_zip.c index 937265b94d22e1c10da4a4d5846447ff09b8a630..f9877d77b0ebc2438845d0b9ee0324aa97a1453c 100644 --- a/service/hnp/base/hnp_zip.c +++ b/service/hnp/base/hnp_zip.c @@ -399,6 +399,10 @@ int HnpFileCountGet(const char *path, int *count) int ret = unzGoToFirstFile(zipFile); while (ret == UNZ_OK) { + if (sum == INT_MAX) { + unzClose(zipFile); + return HNP_ERRNO_BASE_FILE_COUNT_OVER; + } sum++; ret = unzGetCurrentFileInfo(zipFile, NULL, NULL, 0, NULL, 0, NULL, 0); if (ret != UNZ_OK) { @@ -411,6 +415,9 @@ int HnpFileCountGet(const char *path, int *count) } unzClose(zipFile); + if (INT_MAX - sum < *count) { + return HNP_ERRNO_BASE_FILE_COUNT_OVER; + } *count += sum; return 0; } @@ -438,8 +445,8 @@ int HnpUnZip(const char *inputFile, const char *outputDir, const char *hnpSignKe unzClose(zipFile); return HNP_ERRNO_BASE_UNZIP_GET_INFO_FAILED; } - if (strstr(fileName, "../")) { - HNP_LOGE("unzip filename[%{public}s],does not allow the use of ../", fileName); + if (strstr(fileName, "..")) { + HNP_LOGE("unzip filename[%{public}s],does not allow the use of ..", fileName); unzClose(zipFile); return HNP_ERRNO_BASE_UNZIP_GET_INFO_FAILED; } diff --git a/service/hnp/installer/README_zh.md b/service/hnp/installer/README_zh.md index 1ba676e88517f5e9ba4d17290bbd7b1bb9f908b7..d06cda79743d787cb9f67e135deb054bc92611ad 100644 --- a/service/hnp/installer/README_zh.md +++ b/service/hnp/installer/README_zh.md @@ -6,7 +6,7 @@ ## 接口说明 - 针对安装卸载功能提供了以下API调用接口 + 针对安装卸载功能提供了以下API调用接口。 | 接口名 | 描述 | | :----------------------------------------------------------- | :--------------------------------------- | @@ -20,7 +20,7 @@ Native软件包安装就是将从应用市场下载解压出来的hnp包安装到鸿蒙PC设备上。当前提供接口调用以及hnp命令行两种方式进行安装。 - 1) hnp帮助命令 hnp -h +1) hnp帮助命令 hnp -h: ``` usage:hnp [-u ][-p ][-i ][-f][-s ][-a ] @@ -48,7 +48,7 @@ ``` hnp install -u [系统用户ID] -p [hap包名] <-i [hnp安装包所在路径]> <-f> ``` - -u [必选] 用户ID + -u [必选] 用户ID。 -p [必选] 指定hap应用软件名。 @@ -134,14 +134,14 @@ a. 安装时发现已经有同款软件相同版本则跳过安装,返回安装成功。 -b. 非强制安装模式下,安装时发现已经有同款软件不同版本会安装失败. +b. 非强制安装模式下,安装时发现已经有同款软件不同版本会安装失败。 b. 强制安装会将已安装的软件先卸载掉之后再安装当前新的软件。 c. 批量安装应用的hnp软件时如果中间安装出错,则直接退出安装流程返回,之前已安装的软件继续保留。 -3) 接口调用安装 +3) 接口调用安装: 安装接口原型: ``` @@ -166,28 +166,28 @@ c. 批量安装应用的hnp软件时如果中间安装出错,则直接退出 int ret = NativeInstallHnp(100, "./sample.hap", "./baidu_hnp_path", "baidu", 0x1); ... - 执行成功后输出件和上面命令行的一样 + 执行成功后输出件和上面命令行的一样。 ``` **2. Native软件包卸载** Native软件包卸载就是将已安装到系统上的Native软件进行卸载。当期望卸载的软件正在运行时,则卸载失败。当前提供接口调用以及命令行两种方式进行卸载。 - 1) hnp命令行卸载: +1) hnp命令行卸载: ``` hnp uninstall -u [系统用户ID] -p [hap包名] ``` 该命令根据用户传入的信息对已安装的属于对应hap应用下的所有hnp软件进行卸载。 - -u [必选] 系统用户ID,用于拼接软件的安装路径 + -u [必选] 系统用户ID,用于拼接软件的安装路径。 - -p [必选] 要卸载hnp包所属的hap包名(应用软件名) + -p [必选] 要卸载hnp包所属的hap包名(应用软件名)。 样例: ``` baidu应用下hnp软件卸载: hnp uninstall -u 100 -p baidu - 卸载之前已经安装的baidu应用下所有hnp软件。100为安装所在的系统用户ID。 + 卸载之前已经安装的baidu应用下所有hnp软件,100为安装所在的系统用户ID。 执行成功观察点: 观察点1:之前baidu应用安装的时候分别安装了公有和私有的hnpsample软件,所以本次卸载需要观察以下之前安装的软件目录“hnpsample.org”是否已删除。 公有软件: @@ -203,7 +203,7 @@ a. 如果公有hnp软件被其它应用所共有,则卸载本应用不会删 b. 公有hnp软件卸载前会判断该软件是否正在运行,如果正在运行则会卸载失败。私有hnp软件因为其所属应用已经卸载,不存在正在使用的情况,因此私有软件不用校验是否正在运行。 -2) 接口调用卸载 +2) 接口调用卸载: 卸载接口原型: ``` @@ -232,5 +232,5 @@ b. 公有hnp软件卸载前会判断该软件是否正在运行,如果正在 native包管理功能运行控制,需要在用户开启“开发者模式”场景下才能使用native包管理的安装卸载软件功能,否则命令会执行失败。在PC设备上打开“开发者模式”的方法如下: ``` - 点击“设置”按钮——》选择“系统和更新”界面——》选择“开发者选项”——》打开“开发者选项” + 点击“设置”按钮——》选择“系统和更新”界面——》选择“开发者选项”——》打开“开发者选项”。 ``` diff --git a/service/hnp/installer/api_hnp.md b/service/hnp/installer/api_hnp.md index c907eaa4d3451365f815d7178ec03d2622b1bf80..0ac512b86b9fe1307c23cbdf828c1062b6a94b86 100644 --- a/service/hnp/installer/api_hnp.md +++ b/service/hnp/installer/api_hnp.md @@ -6,20 +6,20 @@ ### 文件 -| 名称 | 描述 | -| -------- | -------- | +| 名称 | 描述 | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------- | | hnp_api.h | 提供支持Native软件的安装和卸载的函数。
**引用文件**:<hnp_api.h>
**库**:libhnpapi.z.so | - ### 结构体定义 -NA + +NA. ### 函数 -| 名称 | 描述 | -| -------- | -------- | -| [NativeInstallHnp](#nativeinstallhnp) | 安装Native软件到设备中 | -| [NativeUnInstallHnp](#nativeuninstallhnp)| 卸载设备中已安装的Native软件 | +| 名称 | 描述 | +| -------------------------------------- | ---------------------------- | +| [NativeInstallHnp](#nativeinstallhnp) | 安装Native软件到设备中 | +| [NativeUnInstallHnp](#nativeuninstallhnp) | 卸载设备中已安装的Native软件 | ## 函数说明 @@ -35,11 +35,11 @@ int NativeInstallHnp(const char *userId, const char *hnpRootPath, const HapInfo 参数: - userId:用户ID; + userId:用户ID。 - hapPath:hap包所在路径。用于签名校验 + hapPath:hap包所在路径。用于签名校验。 - hnpRootPath:hnp安装包存放路径; + hnpRootPath:hnp安装包存放路径。 hapInfo:hap应用软件信息,结构如下。 ``` @@ -55,16 +55,17 @@ int NativeInstallHnp(const char *userId, const char *hnpRootPath, const HapInfo ``` installOptions:安装选项。其中每一位对应的选项信息枚举如下。 - ``` + +``` typedef enum { OPTION_INDEX_FORCE = 0, /* installed forcely */ OPTION_INDEX_BUTT } HnpInstallOptionIndex; - ``` +``` **返回:** - -安装成功返回0;失败返回错误码 + +安装成功返回0;失败返回错误码。 ### NativeUnInstallHnp @@ -78,10 +79,10 @@ int NativeUnInstallHnp(const char *userId, const char *packageName); 参数: - userId:用户ID; + userId:用户ID。 - packageName:hap应用软件包名; + packageName:hap应用软件包名。 **返回:** -卸载成功返回0;失败返回错误码 +卸载成功返回0;失败返回错误码。 diff --git a/service/hnp/installer/errorcode-api.md b/service/hnp/installer/errorcode-api.md index 1c04e37e65f98676d173882271a149b497e7bedb..da8dd476789e8913e99f25ed4c579e17862d98d7 100644 --- a/service/hnp/installer/errorcode-api.md +++ b/service/hnp/installer/errorcode-api.md @@ -12,7 +12,7 @@ params is invalid. **错误描述** -参数非法 +参数非法。 **可能原因** @@ -20,7 +20,7 @@ params is invalid. **处理步骤** -检查传入的参数是否正确 +检查传入的参数是否正确。 ## 0x2002 fork子进程失败 @@ -63,7 +63,7 @@ wait pid unsuccess. **错误信息** -native package install/uninstall not in developer mode。 +native package install/uninstall not in developer mode. **错误描述** @@ -71,11 +71,11 @@ native package install/uninstall not in developer mode。 **可能原因** -当前为非开发者模式 +当前为非开发者模式。 **处理步骤** -打开开发者模式进行接口请求 +打开开发者模式进行接口请求。 ## 0x2005 创建管道失败 @@ -85,7 +85,7 @@ pipe fd unsuccess. **错误描述** -创建pipe管道失败 +创建pipe管道失败。 **可能原因** @@ -107,11 +107,11 @@ read stream unsuccess. **可能原因** -系统禁止管道输出 +系统禁止管道输出。 **处理步骤** -查看权限 +查看权限。 ## 0x2007 获取返回码失败 @@ -125,7 +125,7 @@ get return unsuccess. **可能原因** -输出影响 +输出影响。 **处理步骤** @@ -143,7 +143,7 @@ mem move unsuccess. **可能原因** -系统内部原因 +系统内部原因。 **处理步骤** diff --git a/service/hnp/installer/errorcode-hnp.md b/service/hnp/installer/errorcode-hnp.md index e339e9dc35c13d7444bf87f499708871e8839ac0..457ec415f36e3da82c6635e2c494388e03082e52 100644 --- a/service/hnp/installer/errorcode-hnp.md +++ b/service/hnp/installer/errorcode-hnp.md @@ -22,7 +22,7 @@ **处理步骤** - 检查传入的参数个数是否正确。可通过命令hnpcli help查询正确的参数格式 + 检查传入的参数个数是否正确。可通过命令hnpcli help查询正确的参数格式。 ## 0x801002 缺少必要的操作参数 @@ -40,7 +40,7 @@ **处理步骤** -检查传入的参数是否正确以及完整。可通过命令hnpcli help查询正确的参数格式 +检查传入的参数是否正确以及完整。可通过命令hnpcli help查询正确的参数格式。 ## 0x801101 打开文件失败 @@ -55,7 +55,7 @@ Open file failed. **可能原因** 1. 文件不存在。 -2. 没有权限 +2. 没有权限。 **处理步骤** @@ -75,8 +75,8 @@ Read file content failed. **可能原因** 1. 文件不存在。 -2. 没有权限 -3. 文件读出的内容大小和期望的大小不相等 +2. 没有权限。 +3. 文件读出的内容大小和期望的大小不相等。 **处理步骤** @@ -97,8 +97,8 @@ fseek设置失败。 **可能原因** 1. 文件不存在。 -2. 没有权限 -3. fseek系统报错 +2. 没有权限。 +3. fseek系统报错。 **处理步骤** @@ -119,8 +119,8 @@ ftell设置失败。 **可能原因** 1. 文件不存在。 -2. 没有权限 -3. ftell系统报错 +2. 没有权限。 +3. ftell系统报错。 **处理步骤** @@ -140,7 +140,7 @@ Get real path failed. **可能原因** -路径不存在 +路径不存在。 **处理步骤** @@ -158,7 +158,7 @@ Get file content size is 0. **可能原因** -文件内容为空 +文件内容为空。 **处理步骤** @@ -176,11 +176,11 @@ The len of string exceed limit. **可能原因** -用户传入的字符串超出了限制的大小 +用户传入的字符串超出了限制的大小。 **处理步骤** -根据错误信息检查参数是否存在问题 +根据错误信息检查参数是否存在问题。 ## 0x801108 目录打开失败 @@ -194,13 +194,13 @@ Open Dir failed. **可能原因** -1. 目录不存在 -2. 权限问题 +1. 目录不存在。 +2. 权限问题。 **处理步骤** -1. 检查传入的目录是否存在 -2. 检查目录权限是否本进程能够打开 +1. 检查传入的目录是否存在。 +2. 检查目录权限是否本进程能够打开。 ## 0x801109 sprintf拼接失败 @@ -214,11 +214,11 @@ sprintf拼接失败。 **可能原因** -sprintf接口返回错误 +sprintf接口返回错误。 **处理步骤** -查看sprintf错误码并检查参数是否正确 +查看sprintf错误码并检查参数是否正确。 ## 0x80110a 生成压缩文件失败 @@ -232,11 +232,11 @@ Create new file in zip failed. **可能原因** -压缩软件报错 +压缩软件报错。 **处理步骤** -查看压缩软件报错原因并修复 +查看压缩软件报错原因并修复。 ## 0x80110b 写文件失败 @@ -250,15 +250,15 @@ Write file failed. **可能原因** -1. 文件不存在 -2. 权限问题 -3. 写入的是压缩的内容 +1. 文件不存在。 +2. 权限问题。 +3. 写入的是压缩的内容。 **处理步骤** -1. 检查传入的文件是否存在 -2. 检查文件权限是否本进程能够打开 -3. 使用“wb”打开文件再进行写入 +1. 检查传入的文件是否存在。 +2. 检查文件权限是否本进程能够打开。 +3. 使用“wb”打开文件再进行写入。 ## 0x80110c strcpy拷贝失败 **错误信息** @@ -271,11 +271,11 @@ strcpy拷贝失败。 **可能原因** -strcpy接口返回错误 +strcpy接口返回错误。 **处理步骤** -查看strcpy错误码并检查参数是否正确 +查看strcpy错误码并检查参数是否正确。 ## 0x80110d 获取文件属性失败 @@ -289,15 +289,15 @@ Get file attr failed. **可能原因** -1. 文件不存在 -2. 权限问题 -3. 系统接口报错 +1. 文件不存在。 +2. 权限问题。 +3. 系统接口报错。 **处理步骤** -1. 检查传入的文件是否存在 -2. 检查文件权限是否本进程能够打开 -3. 查看具体的系统报错信息并修改 +1. 检查传入的文件是否存在。 +2. 检查文件权限是否本进程能够打开。 +3. 查看具体的系统报错信息并修改。 ## 0x80110e 解压缩打开文件失败 @@ -312,13 +312,13 @@ Unzip process open file failed. **可能原因** -1. 当前打开的文件不是zip格式的文件 -2. 文件不存在 +1. 当前打开的文件不是zip格式的文件。 +2. 文件不存在。 **处理步骤** -1. 检查文件是否为zip格式的文件 -2. 检查文件是否存在 +1. 检查文件是否为zip格式的文件。 +2. 检查文件是否存在。 ## 0x80110f 解压缩获取文件信息失败 @@ -332,12 +332,12 @@ Unzip process get file info failed. **可能原因** -zip里没有文件内容 +zip里没有文件内容。 **处理步骤** -检查zip压缩文件内是否有文件 +检查zip压缩文件内是否有文件。 ## 0x801110 解压缩读取文件内容失败 @@ -351,14 +351,14 @@ Unzip process read file failed. **可能原因** -1. 文件不存在 -2. zip压缩文件已损坏 +1. 文件不存在。 +2. zip压缩文件已损坏。 **处理步骤** -1. 检查文件是否存在 -2. 使用第三方工具检查zip压缩包是否损坏 +1. 检查文件是否存在。 +2. 使用第三方工具检查zip压缩包是否损坏。 ## 0x801111 生成软链接失败 @@ -371,14 +371,14 @@ Symlink failed. 生成软链接失败。 **可能原因** -1. 软链接源文件路径不存在 -2. 软链接目标文件路径不存在 +1. 软链接源文件路径不存在。 +2. 软链接目标文件路径不存在。 **处理步骤** -1. 检查软链接源文件路径是否存在 -2. 检查软连接目标文件路径是否存在 +1. 检查软链接源文件路径是否存在。 +2. 检查软连接目标文件路径是否存在。 ## 0x801112 进程正在运行 @@ -392,11 +392,11 @@ Uninstall failed because software is running. **可能原因** -卸载的软件正在运行中,不能卸载 +卸载的软件正在运行中,不能卸载。 **处理步骤** -检查期望卸载的软件是否正在运行,如果正在运行,则需停止后才能卸载 +检查期望卸载的软件是否正在运行,如果正在运行,则需停止后才能卸载。 ## 0x801113 入参失败 @@ -410,11 +410,11 @@ Arg check failed. **可能原因** -入参非法 +入参非法。 **处理步骤** -根据报错检查入参是否非法 +根据报错检查入参是否非法。 ## 0x801114 strdup失败 @@ -428,11 +428,11 @@ Strdup操作失败。 **可能原因** -申请内存失败 +申请内存失败。 **处理步骤** -根据报错检查内存是否不足 +根据报错检查内存是否不足。 ## 0x801115 设置权限失败 @@ -446,13 +446,13 @@ Chmod failed. Chmod操作失败。 **可能原因** -1. 权限不足 -2. 参数不正确 +1. 权限不足。 +2. 参数不正确。 **处理步骤** -1. 检查当前进程是否有权限执行chmod操作 -2. 检查chmod参数是否正确 +1. 检查当前进程是否有权限执行chmod操作。 +2. 检查chmod参数是否正确。 ## 0x801116 删除目录失败 @@ -466,11 +466,11 @@ Remove dir failed. **可能原因** -权限不足 +权限不足。 **处理步骤** -检查当前进程是否有权限执行unlink操作 +检查当前进程是否有权限执行unlink操作。 ## 0x801117 对应进程不存在 @@ -488,7 +488,7 @@ Process is not running. **处理步骤** -检查查询的进程是否正在运行 +检查查询的进程是否正在运行。 ## 0x801118 创建路径失败 @@ -507,7 +507,7 @@ mkdir创建目录失败。 **处理步骤** -检查当前进程是否有权限执行mkdir操作 +检查当前进程是否有权限执行mkdir操作。 ## 0x801119 读取配置文件流失败 @@ -525,7 +525,7 @@ Read cfg stream failed. **处理步骤** -检查配置文件是否存在 +检查配置文件是否存在。 ## 0x80111a 解析json信息失败 @@ -543,7 +543,7 @@ Parse json info failed. **处理步骤** -检查文件内容是否是json格式 +检查文件内容是否是json格式。 ## 0x80111b 未找到json项 @@ -562,7 +562,7 @@ Get json item failed. **处理步骤** -检查文件内容是否存在对应的item项 +检查文件内容是否存在对应的item项。 ## 0x80111c 解析json数组失败 @@ -580,7 +580,7 @@ json文件中不存在对应的数据信息。 **处理步骤** -检查json文件内容是否存在对应的数组信息 +检查json文件内容是否存在对应的数组信息。 @@ -603,7 +603,7 @@ The cmd arg num is invalid. **处理步骤** -检查传入的参数个数是否正确。可通过命令hnp help查询正确的参数格式 +检查传入的参数个数是否正确。可通过命令hnp help查询正确的参数格式。 ## 0x801302 组装安装路径失败 @@ -621,7 +621,7 @@ sprintf拼接路径时报错。 **处理步骤** -检查拼接的参数是否超出路径大小上限。根据sprintf报错处理 +检查拼接的参数是否超出路径大小上限。根据sprintf报错处理。 ## 0x801303 获取安装实际路径失败 **错误信息** @@ -634,12 +634,12 @@ Get real path failed. **可能原因** -1. 传入的hnp包所在路径非法 -2. 传入的安装路径非法 +1. 传入的hnp包所在路径非法。 +2. 传入的安装路径非法。 **处理步骤** -检查安装卸载传入的路径是否正确 +检查安装卸载传入的路径是否正确。 ## 0x801304 获取Hnp安装包名称失败 **错误信息** @@ -648,15 +648,15 @@ Get hnp file name failed. **错误描述** -获取不到hnp文件的名字信息 +获取不到hnp文件的名字信息。 **可能原因** -文件名不是.hnp结尾的名字 +文件名不是.hnp结尾的名字。 **处理步骤** -检查目录下是否存在非.hnp后缀名的文件 +检查目录下是否存在非.hnp后缀名的文件。 ## 0x801305 软件已安装 **错误信息** @@ -673,7 +673,7 @@ Software has been installed. **处理步骤** -1. 检查软件是否已被安装 +1. 检查软件是否已被安装。 2. 软件已安装,用户确认后可通过-f选项进行强制安装。 ## 0x801306 卸载命令参数错误 @@ -691,29 +691,29 @@ The cmd arg num is invalid. **处理步骤** -检查传入的参数个数是否正确。可通过命令hnp help查询正确的参数格式 +检查传入的参数个数是否正确。可通过命令hnp help查询正确的参数格式。 ## 0x801307 获取卸载路径失败 **错误信息** -Get uninstall path failed。 +Get uninstall path failed. **错误描述** 获取卸载路径失败。 **可能原因** -1. 传参错误 +1. 传参错误。 2. 要卸载的软件不存在。 **处理步骤** -1. 检查卸载的软件信息是否正确 -2. 检查卸载的软件是否已安装 +1. 检查卸载的软件信息是否正确。 +2. 检查卸载的软件是否已安装。 ## 0x801308 安装命令参数uid错误 **错误信息** -Get user id failed。 +Get user id failed. **错误描述** @@ -721,11 +721,11 @@ Get user id failed。 **可能原因** -用户传入的用户ID非数字 +用户传入的用户ID非数字。 **处理步骤** -检查用户传入的用户ID是否非数字 +检查用户传入的用户ID是否非数字。 ## 0x801309 获取版本目录失败 **错误信息** @@ -738,11 +738,11 @@ Get software version path failed. **可能原因** -软件安装路径下为空,外层安装路径残留 +软件安装路径下为空,外层安装路径残留。 **处理步骤** -检查安装路径是否残留一个空的.org文件夹。是的话需要删除 +检查安装路径是否残留一个空的.org文件夹。是的话需要删除。 ## 0x80130a 安装包个数超过阈值 **错误信息** @@ -751,15 +751,15 @@ Num of hnp file over limit. **错误描述** -安装包的个数超出了限制。阈值为32个 +安装包的个数超出了限制。阈值为32个。 **可能原因** -安装包的个数超出了32个 +安装包的个数超出了32个。 **处理步骤** -检查安装包的个数是否超出了32个。如果超出需要分批次安装 +检查安装包的个数是否超出了32个。如果超出需要分批次安装。 diff --git a/service/hnp/installer/src/hnp_installer.c b/service/hnp/installer/src/hnp_installer.c index 64a4a9e3350a671a0d98ff42b040bae554430a4e..c8bee46446842598bde023d918cd4f82c7f2b428 100644 --- a/service/hnp/installer/src/hnp_installer.c +++ b/service/hnp/installer/src/hnp_installer.c @@ -63,8 +63,8 @@ static int HnpGenerateSoftLinkAllByJson(const char *installPath, const char *dst } for (unsigned int i = 0; i < hnpCfg->linkNum; i++) { - if (strstr(currentLink->source, "../") || strstr(currentLink->target, "../")) { - HNP_LOGE("hnp json link source[%{public}s],target[%{public}s],does not allow the use of ../", + if (strstr(currentLink->source, "..") || strstr(currentLink->target, "..")) { + HNP_LOGE("hnp json link source[%{public}s],target[%{public}s],does not allow the use of ..", currentLink->source, currentLink->target); return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED; } @@ -375,6 +375,10 @@ static int HnpInstallPathGet(HnpCfgInfo *hnpCfgInfo, HnpInstallInfo *hnpInfo) HNP_LOGE("hnp install sprintf install path unsuccess."); return HNP_ERRNO_BASE_SPRINTF_FAILED; } + if (strstr(hnpInfo->hnpVersionPath, "..")) { + HNP_LOGE("hnp version path[%{public}s], does not allow the use of ..", hnpInfo->hnpVersionPath); + return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED; + } return 0; } @@ -391,6 +395,7 @@ static int HnpPublicDealAfterInstall(HnpInstallInfo *hnpInfo, HnpCfgInfo *hnpCfg } if (version != NULL) { free(version); + version = NULL; } hnpCfg->isInstall = true; @@ -636,10 +641,16 @@ static int HnpInstallHapFileCountGet(const char *root, int *count) { struct dirent *entry; char hnpPath[MAX_FILE_PATH_LEN]; + char realPath[MAX_FILE_PATH_LEN] = {0}; - DIR *dir = opendir(root); + if ((realpath(root, realPath) == NULL) || (strnlen(realPath, MAX_FILE_PATH_LEN) >= MAX_FILE_PATH_LEN)) { + HNP_LOGE("hnp root path:%{public}s invalid", root); + return HNP_ERRNO_BASE_PARAMS_INVALID; + } + + DIR *dir = opendir(realPath); if (dir == NULL) { - HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", root, errno); + HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", realPath, errno); return HNP_ERRNO_BASE_DIR_OPEN_FAILED; } @@ -647,7 +658,7 @@ static int HnpInstallHapFileCountGet(const char *root, int *count) if ((strcmp(entry->d_name, "public") != 0) && (strcmp(entry->d_name, "private") != 0)) { continue; } - if (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/%s", root, entry->d_name) < 0) { + if (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/%s", realPath, entry->d_name) < 0) { HNP_LOGE("hnp install private base path sprintf unsuccess."); closedir(dir); return HNP_ERRNO_BASE_SPRINTF_FAILED; @@ -859,4 +870,4 @@ int HnpCmdUnInstall(int argc, char *argv[]) #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/service/hnp/pack/README_zh.md b/service/hnp/pack/README_zh.md index ed029fbeb5d8bb6594288bcd5612c6978329f82c..6ebd0f8b0b73d72f6f5f1a9d2b25aa56fd3b6b02 100644 --- a/service/hnp/pack/README_zh.md +++ b/service/hnp/pack/README_zh.md @@ -125,5 +125,5 @@ Native包管理功能模块提供了对Native软件的打包、安装、卸载 ``` 1. 对hnpsample软件进行打包,由于hnpsample目录下存在hnp.json文件,不需要指定软件名和版本号。因此命令如下: hnpcli pack -i ./hnpsample -o ./out - 2. 命令返回成功,则在out目录下生成hnpsample.hnp文件 + 2. 命令返回成功,则在out目录下生成hnpsample.hnp文件。 ``` diff --git a/service/hnp/pack/errorcode-hnpcli.md b/service/hnp/pack/errorcode-hnpcli.md index 04014098c75d6c31c6a2225dbe46ae072cfc6c30..41e54d13f23184b8e4d23e01a1b7c31be77f258c 100644 --- a/service/hnp/pack/errorcode-hnpcli.md +++ b/service/hnp/pack/errorcode-hnpcli.md @@ -22,7 +22,7 @@ The cmd operate type is invalid. **处理步骤** -检查传入的参数个数是否正确。可通过命令hnpcli help查询正确的参数格式 +检查传入的参数个数是否正确。可通过命令hnpcli help查询正确的参数格式。 ## 0x801002 缺少必要的操作参数 @@ -41,7 +41,7 @@ The cmd operate required arg is miss. **处理步骤** -检查传入的参数是否正确以及完整。可通过命令hnpcli help查询正确的参数格式 +检查传入的参数是否正确以及完整。可通过命令hnpcli help查询正确的参数格式。 ## 0x801101 打开文件失败 @@ -56,7 +56,7 @@ Open file failed. **可能原因** 1. 文件不存在。 -2. 没有权限 +2. 没有权限。 **处理步骤** @@ -76,8 +76,8 @@ Read file content failed. **可能原因** 1. 文件不存在。 -2. 没有权限 -3. 文件读出的内容大小和期望的大小不相等 +2. 没有权限。 +3. 文件读出的内容大小和期望的大小不相等。 **处理步骤** @@ -98,8 +98,8 @@ fseek设置失败。 **可能原因** 1. 文件不存在。 -2. 没有权限 -3. fseek系统报错 +2. 没有权限。 +3. fseek系统报错。 **处理步骤** @@ -120,8 +120,8 @@ ftell设置失败。 **可能原因** 1. 文件不存在。 -2. 没有权限 -3. ftell系统报错 +2. 没有权限。 +3. ftell系统报错。 **处理步骤** @@ -141,7 +141,7 @@ Get real path failed. **可能原因** -路径不存在 +路径不存在。 **处理步骤** @@ -159,7 +159,7 @@ Get file content size is 0. **可能原因** -文件内容为空 +文件内容为空。 **处理步骤** @@ -177,11 +177,11 @@ The len of string exceed limit. **可能原因** -用户传入的字符串超出了限制的大小 +用户传入的字符串超出了限制的大小。 **处理步骤** -根据错误信息检查参数是否存在问题 +根据错误信息检查参数是否存在问题。 ## 0x801108 目录打开失败 @@ -195,13 +195,13 @@ Open Dir failed. **可能原因** -1. 目录不存在 -2. 权限问题 +1. 目录不存在。 +2. 权限问题。 **处理步骤** -1. 检查传入的目录是否存在 -2. 检查目录权限是否本进程能够打开 +1. 检查传入的目录是否存在。 +2. 检查目录权限是否本进程能够打开。 ## 0x801109 sprintf拼接失败 @@ -215,11 +215,11 @@ sprintf拼接失败。 **可能原因** -sprintf接口返回错误 +sprintf接口返回错误。 **处理步骤** -查看sprintf错误码并检查参数是否正确 +查看sprintf错误码并检查参数是否正确。 ## 0x80110a 生成压缩文件失败 @@ -233,11 +233,11 @@ Create new file in zip failed. **可能原因** -压缩软件报错 +压缩软件报错。 **处理步骤** -查看压缩软件报错原因并修复 +查看压缩软件报错原因并修复。 ## 0x80110b 写文件失败 @@ -251,15 +251,15 @@ Write file failed. **可能原因** -1. 文件不存在 -2. 权限问题 -3. 写入的是压缩的内容 +1. 文件不存在。 +2. 权限问题。 +3. 写入的是压缩的内容。 **处理步骤** -1. 检查传入的文件是否存在 -2. 检查文件权限是否本进程能够打开 -3. 使用“wb”打开文件再进行写入 +1. 检查传入的文件是否存在。 +2. 检查文件权限是否本进程能够打开。 +3. 使用“wb”打开文件再进行写入。 ## 0x80110c strcpy拷贝失败 **错误信息** @@ -272,11 +272,11 @@ strcpy拷贝失败。 **可能原因** -strcpy接口返回错误 +strcpy接口返回错误。 **处理步骤** -查看strcpy错误码并检查参数是否正确 +查看strcpy错误码并检查参数是否正确。 ## 0x80110d 获取文件属性失败 @@ -290,15 +290,15 @@ Get file attr failed. **可能原因** -1. 文件不存在 -2. 权限问题 -3. 系统接口报错 +1. 文件不存在。 +2. 权限问题。 +3. 系统接口报错。 **处理步骤** -1. 检查传入的文件是否存在 -2. 检查文件权限是否本进程能够打开 -3. 查看具体的系统报错信息并修改 +1. 检查传入的文件是否存在。 +2. 检查文件权限是否本进程能够打开。 +3. 查看具体的系统报错信息并修改。 @@ -318,7 +318,7 @@ Read cfg stream failed. **处理步骤** -检查配置文件是否存在 +检查配置文件是否存在。 ## 0x80111a 解析json信息失败 @@ -336,7 +336,7 @@ Parse json info failed. **处理步骤** -检查文件内容是否是json格式 +检查文件内容是否是json格式。 ## 0x80111b 未找到json项 @@ -355,7 +355,7 @@ Get json item failed. **处理步骤** -检查文件内容是否存在对应的item项 +检查文件内容是否存在对应的item项。 ## 0x80111c 解析json数组失败 @@ -373,7 +373,7 @@ json文件中不存在对应的数据信息。 **处理步骤** -检查json文件内容是否存在对应的数组信息 +检查json文件内容是否存在对应的数组信息。 # pack打包模块错误码 @@ -393,7 +393,7 @@ Get real path failed. **处理步骤** -检查传入的打包目录路径、输出路径以及配置项文件路径是否存在 +检查传入的打包目录路径、输出路径以及配置项文件路径是否存在。 ## 0x801202 组装输出文件路径失败 **错误信息** @@ -406,7 +406,7 @@ Get output file path failed。 **可能原因** -sprintf拼接文件名失败 +sprintf拼接文件名失败。 **处理步骤** @@ -423,13 +423,13 @@ Compress dir failed。 **可能原因** -1. 权限问题导致无法访问原目录或者输出目录 -2. 压缩软件报错 +1. 权限问题导致无法访问原目录或者输出目录。 +2. 压缩软件报错。 **处理步骤** -1. 查看原目录和输出目录的访问权限,确定本进程是否可以访问 -2. 查看对应的压缩软件错误信息进行定位 +1. 查看原目录和输出目录的访问权限,确定本进程是否可以访问。 +2. 查看对应的压缩软件错误信息进行定位。 diff --git a/standard/BUILD.gn b/standard/BUILD.gn index ec2ee283ff8cd0f0c54c25c5f9211745aa1915ba..06e355397d09c663544c8d3e04517d02872196d8 100644 --- a/standard/BUILD.gn +++ b/standard/BUILD.gn @@ -75,6 +75,7 @@ ohos_executable("appspawn") { "cJSON:cjson", "c_utils:utils", "config_policy:configpolicy_util", + "ffrt:libffrt", "hilog:libhilog", "hitrace:hitrace_meter", "init:libbegetutil", @@ -82,13 +83,14 @@ ohos_executable("appspawn") { if (enable_appspawn_dump_catcher) { external_deps += [ "faultloggerd:libdfx_dumpcatcher" ] } - if (appspawn_use_encaps) { - defines += [ "USE_ENCAPS" ] - } + if (appspawn_report_event) { defines += [ "APPSPAWN_HISYSEVENT" ] external_deps += [ "hisysevent:libhisysevent" ] - sources += [ "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp" ] + sources += [ + "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", + ] } if (build_selinux) { defines += [ "WITH_SELINUX" ] @@ -133,6 +135,7 @@ ohos_shared_library("appspawn_helper") { "-fstack-protector-all", ] external_deps = [ + "ffrt:libffrt", "hilog:libhilog", "init:libbegetutil", ] @@ -187,6 +190,7 @@ ohos_executable("cjappspawn") { "cJSON:cjson", "c_utils:utils", "config_policy:configpolicy_util", + "ffrt:libffrt", "hilog:libhilog", "hitrace:hitrace_meter", "init:libbegetutil", @@ -194,7 +198,10 @@ ohos_executable("cjappspawn") { if (appspawn_report_event) { defines += [ "APPSPAWN_HISYSEVENT" ] external_deps += [ "hisysevent:libhisysevent" ] - sources += [ "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp" ] + sources += [ + "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", + ] } if (build_selinux) { defines += [ "WITH_SELINUX" ] @@ -258,6 +265,7 @@ ohos_executable("nativespawn") { "cJSON:cjson", "c_utils:utils", "config_policy:configpolicy_util", + "ffrt:libffrt", "hilog:libhilog", "hitrace:hitrace_meter", "init:libbegetutil", @@ -265,7 +273,10 @@ ohos_executable("nativespawn") { if (appspawn_report_event) { defines += [ "APPSPAWN_HISYSEVENT" ] external_deps += [ "hisysevent:libhisysevent" ] - sources += [ "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp" ] + sources += [ + "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", + ] } if (build_selinux) { defines += [ "WITH_SELINUX" ] diff --git a/standard/appspawn_appmgr.c b/standard/appspawn_appmgr.c index ffdfa09098b90764acef84f21480de77f13376ef..18740ea95c796a0737a7805c7bfaba1e6bb74b13 100644 --- a/standard/appspawn_appmgr.c +++ b/standard/appspawn_appmgr.c @@ -55,9 +55,15 @@ AppSpawnMgr *CreateAppSpawnMgr(int mode) appMgr->servicePid = getpid(); appMgr->server = NULL; appMgr->sigHandler = NULL; +#ifdef APPSPAWN_HISYSEVENT + appMgr->hisyseventInfo = NULL; +#endif OH_ListInit(&appMgr->appQueue); OH_ListInit(&appMgr->diedQueue); OH_ListInit(&appMgr->appSpawnQueue); +#ifndef APPSPAWN_SANDBOX_NEW + OH_ListInit(&appMgr->dataGroupCtxQueue); +#endif appMgr->diedAppCount = 0; OH_ListInit(&appMgr->extData); g_appSpawnMgr = appMgr; @@ -98,6 +104,12 @@ void DeleteAppSpawnMgr(AppSpawnMgr *mgr) OH_ListRemoveAll(&mgr->diedQueue, NULL); OH_ListRemoveAll(&mgr->appSpawnQueue, SpawningQueueDestroy); OH_ListRemoveAll(&mgr->extData, ExtDataDestroy); +#ifndef APPSPAWN_SANDBOX_NEW + OH_ListRemoveAll(&mgr->dataGroupCtxQueue, NULL); +#endif +#ifdef APPSPAWN_HISYSEVENT + DeleteHisyseventInfo(mgr->hisyseventInfo); +#endif APPSPAWN_LOGV("DeleteAppSpawnMgr %{public}d %{public}d", mgr->servicePid, getpid()); free(mgr); @@ -226,8 +238,9 @@ int KillAndWaitStatus(pid_t pid, int sig, int *exitStatus) APPSPAWN_LOGE("unable to kill process, pid: %{public}d ret %{public}d", pid, errno); return -1; } - pid_t exitPid = 0; + int retry = 0; + pid_t exitPid = 0; while (retry * SLEEP_DURATION < EXIT_APP_TIMEOUT) { exitPid = waitpid(pid, exitStatus, WNOHANG); if (exitPid == pid) { @@ -307,7 +320,7 @@ void DeleteAppSpawningCtx(AppSpawningCtx *property) APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return); APPSPAWN_LOGV("DeleteAppSpawningCtx"); - DeleteAppSpawnMsg(property->message); + DeleteAppSpawnMsg(&property->message); OH_ListRemove(&property->node); if (property->forkCtx.timer) { @@ -315,6 +328,7 @@ void DeleteAppSpawningCtx(AppSpawningCtx *property) property->forkCtx.timer = NULL; } if (property->forkCtx.watcherHandle) { + APPSPAWN_LOGI("start clear watcher handle"); LE_RemoveWatcher(LE_GetDefaultLoop(), property->forkCtx.watcherHandle); property->forkCtx.watcherHandle = NULL; } @@ -364,9 +378,9 @@ void AppSpawningCtxTraversal(ProcessTraversal traversal, void *data) static int DumpAppSpawnQueue(ListNode *node, void *data) { AppSpawningCtx *property = ListEntry(node, AppSpawningCtx, node); - APPSPAPWN_DUMP("app property id: %{public}u flags: %{public}x", + APPSPAWN_DUMP("app property id: %{public}u flags: %{public}x", property->client.id, property->client.flags); - APPSPAPWN_DUMP("app property state: %{public}d", property->state); + APPSPAWN_DUMP("app property state: %{public}d", property->state); DumpAppSpawnMsg(property->message); return 0; @@ -376,8 +390,8 @@ static int DumpAppQueue(ListNode *node, void *data) { AppSpawnedProcess *appInfo = ListEntry(node, AppSpawnedProcess, node); uint64_t diff = DiffTime(&appInfo->spawnStart, &appInfo->spawnEnd); - APPSPAPWN_DUMP("App info uid: %{public}u pid: %{public}x", appInfo->uid, appInfo->pid); - APPSPAPWN_DUMP("App info name: %{public}s exitStatus: 0x%{public}x spawn time: %{public}" PRIu64 " us ", + APPSPAWN_DUMP("App info uid: %{public}u pid: %{public}x", appInfo->uid, appInfo->pid); + APPSPAWN_DUMP("App info name: %{public}s exitStatus: 0x%{public}x spawn time: %{public}" PRIu64 " us ", appInfo->name, appInfo->exitStatus, diff); return 0; } @@ -399,25 +413,26 @@ void ProcessAppSpawnDumpMsg(const AppSpawnMsgNode *message) char *ptyName = GetAppSpawnMsgExtInfo(message, "pty-name", &len); if (ptyName != NULL) { APPSPAWN_LOGI("Dump info to file '%{public}s'", ptyName); - char canonicalPtyPath[PATH_MAX] = {0}; + char canonicalPtyPath[PATH_MAX] = { 0 }; if (realpath(ptyName, canonicalPtyPath) == NULL) { return; } + stream = fopen(canonicalPtyPath, "w"); SetDumpToStream(stream); } else { SetDumpToStream(stdout); } - APPSPAPWN_DUMP("Dump appspawn info start ... "); - APPSPAPWN_DUMP("APP spawning queue: "); + APPSPAWN_DUMP("Dump appspawn info start ... "); + APPSPAWN_DUMP("APP spawning queue: "); OH_ListTraversal((ListNode *)&g_appSpawnMgr->appSpawnQueue, NULL, DumpAppSpawnQueue, 0); - APPSPAPWN_DUMP("APP queue: "); + APPSPAWN_DUMP("APP queue: "); OH_ListTraversal((ListNode *)&g_appSpawnMgr->appQueue, "App queue", DumpAppQueue, 0); - APPSPAPWN_DUMP("APP died queue: "); + APPSPAWN_DUMP("APP died queue: "); OH_ListTraversal((ListNode *)&g_appSpawnMgr->diedQueue, "App died queue", DumpAppQueue, 0); - APPSPAPWN_DUMP("Ext data: "); + APPSPAWN_DUMP("Ext data: "); OH_ListTraversal((ListNode *)&g_appSpawnMgr->extData, "Ext data", DumpExtData, 0); - APPSPAPWN_DUMP("Dump appspawn info finish "); + APPSPAWN_DUMP("Dump appspawn info finish "); if (stream != NULL) { (void)fflush(stream); fclose(stream); diff --git a/standard/appspawn_kickdog.c b/standard/appspawn_kickdog.c index b41c2ba670dfb389d772b8abe6b4956d93ef7808..8d2707498303b22a4544a88c3c30b23119d5deb8 100644 --- a/standard/appspawn_kickdog.c +++ b/standard/appspawn_kickdog.c @@ -34,7 +34,7 @@ static int OpenAndWriteToProc(const char *procName, const char *writeStr, size_t if (writeResult != (int)writeLen) { APPSPAWN_LOGE("write %{public}s fail,result:%{public}d", writeStr, writeResult); } else { - APPSPAWN_LOGI("write %{public}s success", writeStr); + APPSPAWN_LOGV("write %{public}s success", writeStr); } close(procFd); @@ -66,8 +66,6 @@ static const char *GetProcContent(bool isLinux, bool isOpen, int mode) static void DealSpawnWatchdog(AppSpawnContent *content, bool isOpen) { - APPSPAWN_LOGI("%{public}s %{public}s watchdog begin", - (content->mode == MODE_FOR_NWEB_SPAWN) ? "Nwebspawn" : "Appspawn", isOpen ? "enable" : "kick"); int result = 0; const char *procFile = GetProcFile(content->isLinux); const char *procContent = GetProcContent(content->isLinux, isOpen, content->mode); @@ -75,8 +73,9 @@ static void DealSpawnWatchdog(AppSpawnContent *content, bool isOpen) if (isOpen) { content->wdgOpened = (result != -1); } - APPSPAWN_LOGI("%{public}s %{public}s watchdog end, result:%{public}d", - (content->mode == MODE_FOR_NWEB_SPAWN) ? "Nwebspawn" : "Appspawn", isOpen ? "enable" : "kick", result); + APPSPAWN_LOGI("procFile: %{public}s procContent: %{public}s %{public}s %{public}s watchdog end, result:%{public}d", + procFile, procContent, (content->mode == MODE_FOR_NWEB_SPAWN) ? + "Nwebspawn" : "Appspawn", isOpen ? "enable" : "kick", result); } static void ProcessTimerHandle(const TimerHandle taskHandle, void *context) @@ -120,7 +119,7 @@ static int CheckKernelType(bool *isLinux) return 0; } -static int SpawnKickDogStart(AppSpawnMgr *mgrContent) +APPSPAWN_STATIC int SpawnKickDogStart(AppSpawnMgr *mgrContent) { APPSPAWN_CHECK(mgrContent != NULL, return 0, "content is null"); APPSPAWN_CHECK((mgrContent->content.mode == MODE_FOR_APP_SPAWN) || diff --git a/standard/appspawn_manager.h b/standard/appspawn_manager.h index 9c78948ce3221ef802b10b8f87ae0fdb29dfad01..3c16cb2ff448b60cc9c749ea9aa1b61bfe4571a2 100644 --- a/standard/appspawn_manager.h +++ b/standard/appspawn_manager.h @@ -27,6 +27,9 @@ #include "appspawn_utils.h" #include "list.h" #include "loop_event.h" +#ifdef APPSPAWN_HISYSEVENT +#include "hisysevent_adapter.h" +#endif #ifdef __cplusplus extern "C" { @@ -50,6 +53,8 @@ extern "C" { #define APP_STATE_IDLE 1 #define APP_STATE_SPAWNING 2 #define APPSPAWN_MAX_TIME 3000000 +#define UUID_MAX_LEN 37 +#define PATH_MAX_LEN 256 #define APPSPAWN_INLINE __attribute__((always_inline)) inline @@ -106,6 +111,21 @@ typedef struct SpawnTime { int maxAppspawnTime; } SpawnTime; +#ifndef APPSPAWN_SANDBOX_NEW +typedef struct TagPathBuffer { + uint32_t pathLen; + char path[PATH_MAX_LEN]; +} PathBuffer; + +typedef struct TagDataGroupCtx { + struct ListNode node; + int gid; + char dataGroupUuid[UUID_MAX_LEN]; + PathBuffer srcPath; + PathBuffer destPath; +} DataGroupCtx; +#endif + typedef struct TagAppSpawnMgr { AppSpawnContent content; TaskHandle server; @@ -120,6 +140,12 @@ typedef struct TagAppSpawnMgr { struct timespec perLoadEnd; struct ListNode extData; struct SpawnTime spawnTime; +#ifndef APPSPAWN_SANDBOX_NEW + struct ListNode dataGroupCtxQueue; +#endif +#ifdef APPSPAWN_HISYSEVENT + AppSpawnHisyseventInfo *hisyseventInfo; +#endif } AppSpawnMgr; /** @@ -161,7 +187,7 @@ void ProcessAppSpawnDumpMsg(const AppSpawnMsgNode *message); int ProcessTerminationStatusMsg(const AppSpawnMsgNode *message, AppSpawnResult *result); AppSpawnMsgNode *CreateAppSpawnMsg(void); -void DeleteAppSpawnMsg(AppSpawnMsgNode *msgNode); +void DeleteAppSpawnMsg(AppSpawnMsgNode **msgNode); int CheckAppSpawnMsg(const AppSpawnMsgNode *message); int DecodeAppSpawnMsg(AppSpawnMsgNode *message); int GetAppSpawnMsgFromBuffer(const uint8_t *buffer, uint32_t bufferLen, @@ -195,6 +221,12 @@ APPSPAWN_INLINE int IsNWebSpawnMode(const AppSpawnMgr *content) (content->content.mode == MODE_FOR_NWEB_SPAWN || content->content.mode == MODE_FOR_NWEB_COLD_RUN); } +APPSPAWN_INLINE int IsNativeSpawnMode(const AppSpawnMgr *content) +{ + return (content != NULL) && + (content->content.mode == MODE_FOR_NATIVE_SPAWN); +} + APPSPAWN_INLINE int IsColdRunMode(const AppSpawnMgr *content) { return (content != NULL) && diff --git a/standard/appspawn_msgmgr.c b/standard/appspawn_msgmgr.c index 27bc031e8322d164d475a7520a23917071fdc021..588693b7379ed0d025396a7f990cd8cd3143ee32 100644 --- a/standard/appspawn_msgmgr.c +++ b/standard/appspawn_msgmgr.c @@ -100,20 +100,21 @@ AppSpawnMsgNode *CreateAppSpawnMsg(void) return message; } -void DeleteAppSpawnMsg(AppSpawnMsgNode *msgNode) +void DeleteAppSpawnMsg(AppSpawnMsgNode **msgNode) { - if (msgNode == NULL) { + if (msgNode == NULL || *msgNode == NULL) { return; } - if (msgNode->buffer) { - free(msgNode->buffer); - msgNode->buffer = NULL; + if ((*msgNode)->buffer) { + free((*msgNode)->buffer); + (*msgNode)->buffer = NULL; } - if (msgNode->tlvOffset) { - free(msgNode->tlvOffset); - msgNode->tlvOffset = NULL; + if ((*msgNode)->tlvOffset) { + free((*msgNode)->tlvOffset); + (*msgNode)->tlvOffset = NULL; } - free(msgNode); + free(*msgNode); + *msgNode = NULL; } static inline int CheckRecvMsg(const AppSpawnMsg *msg) @@ -157,19 +158,19 @@ AppSpawnMsgNode *RebuildAppSpawnMsgNode(AppSpawnMsgNode *message, AppSpawnedProc AppSpawnMsgNode *node = CreateAppSpawnMsg(); APPSPAWN_CHECK(node != NULL, return NULL, "Failed to create AppSpawnMsgNode"); int ret = memcpy_s(&node->msgHeader, sizeof(AppSpawnMsg), &message->msgHeader, sizeof(AppSpawnMsg)); - APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(node); return NULL, "Failed to memcpy_s node->msgHeader"); + APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(&node); return NULL, "Failed to memcpy_s node->msgHeader"); bufferLen = message->msgHeader.msgLen + appInfo->message->msgHeader.msgLen - sizeof(AppSpawnMsg); node->msgHeader.msgLen = bufferLen; node->msgHeader.msgType = MSG_SPAWN_NATIVE_PROCESS; node->msgHeader.tlvCount += message->msgHeader.tlvCount; ret = AppSpawnMsgRebuild(node, &node->msgHeader); - APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(node); return NULL, "Failed to alloc memory for recv message"); + APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(&node); return NULL, "Failed to alloc memory for recv message"); uint32_t appInfoBufLen = appInfo->message->msgHeader.msgLen - sizeof(AppSpawnMsg); uint32_t msgBufLen = message->msgHeader.msgLen - sizeof(AppSpawnMsg); ret = memcpy_s(node->buffer, bufferLen, appInfo->message->buffer, appInfoBufLen); - APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(node); return NULL, "Failed to memcpy_s appInfo buffer"); + APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(&node); return NULL, "Failed to memcpy_s appInfo buffer"); ret = memcpy_s(node->buffer + appInfoBufLen, bufferLen - appInfoBufLen, message->buffer, msgBufLen); - APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(node); return NULL, "Failed to memcpy_s message->buffer"); + APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(&node); return NULL, "Failed to memcpy_s message->buffer"); return node; #endif return NULL; @@ -345,55 +346,57 @@ int GetAppSpawnMsgFromBuffer(const uint8_t *buffer, uint32_t bufferLen, return 0; } -static inline void DumpMsgFlags(const char *info, const AppSpawnMsgFlags *msgFlags) +static inline void DumpMsgFlags(const char *processName, const char *info, const AppSpawnMsgFlags *msgFlags) { for (uint32_t i = 0; i < msgFlags->count; i++) { - APPSPAPWN_DUMP("%{public}s flags: 0x%{public}x", info, msgFlags->flags[i]); + APPSPAWN_DUMP("processName: %{public}s %{public}d %{public}s flags: 0x%{public}x", + processName, i, info, msgFlags->flags[i]); } } static inline void DumpMsgExtInfo(const AppSpawnTlv *tlv) { if (tlv->tlvType != TLV_MAX) { - APPSPAPWN_DUMP("App tlv info: [%{public}d %{public}d]", tlv->tlvType, tlv->tlvLen); + APPSPAWN_DUMP("App tlv info: [%{public}d %{public}d]", tlv->tlvType, tlv->tlvLen); return; } AppSpawnTlvExt *tlvExt = (AppSpawnTlvExt *)(tlv); if (tlvExt->dataType == DATA_TYPE_STRING) { - APPSPAPWN_DUMP("App extend info name: %{public}s len: %{public}u value: '%{public}s'", + APPSPAWN_LOGV("App extend info name: %{public}s len: %{public}u value: '%{public}s'", tlvExt->tlvName, tlvExt->dataLen, (char *)(tlvExt + 1)); } else { - APPSPAPWN_DUMP("App extend info name: %{public}s len: %{public}u", tlvExt->tlvName, tlvExt->dataLen); + APPSPAWN_DUMP("App extend info name: %{public}s len: %{public}u", tlvExt->tlvName, tlvExt->dataLen); } } void DumpAppSpawnMsg(const AppSpawnMsgNode *message) { APPSPAWN_CHECK_ONLY_EXPER(message != NULL, return); - APPSPAPWN_DUMP("App spawn msg msgId: %{public}u msgLen: %{public}u tlvCount: %{public}u processName: %{public}s", + APPSPAWN_DUMP("App spawn msg msgId: %{public}u msgLen: %{public}u tlvCount: %{public}u processName: %{public}s", message->msgHeader.msgId, message->msgHeader.msgLen, message->tlvCount, message->msgHeader.processName); AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(message, TLV_MSG_FLAGS); - APPSPAWN_ONLY_EXPER(msgFlags != NULL, DumpMsgFlags("App flags", msgFlags)); + APPSPAWN_ONLY_EXPER(msgFlags != NULL, DumpMsgFlags(message->msgHeader.processName, "App flags", msgFlags)); msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(message, TLV_PERMISSION); - APPSPAWN_ONLY_EXPER(msgFlags != NULL, DumpMsgFlags("App permission bits", msgFlags)); + APPSPAWN_ONLY_EXPER(msgFlags != NULL, + DumpMsgFlags(message->msgHeader.processName, "App permission bits", msgFlags)); AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppSpawnMsgInfo(message, TLV_DAC_INFO); if (dacInfo != NULL) { - APPSPAPWN_DUMP("App dac info uid: %{public}d gid: %{public}d count: %{public}d", + APPSPAWN_DUMP("App dac info uid: %{public}d gid: %{public}d count: %{public}d", dacInfo->uid, dacInfo->gid, dacInfo->gidCount); for (uint32_t i = 0; i < dacInfo->gidCount; i++) { - APPSPAPWN_DUMP("gid group[%{public}d]: %{public}d", i, dacInfo->gidTable[i]); + APPSPAWN_DUMP("gid group[%{public}d]: %{public}d", i, dacInfo->gidTable[i]); } } AppSpawnMsgBundleInfo *bundleInfo = (AppSpawnMsgBundleInfo *)GetAppSpawnMsgInfo(message, TLV_BUNDLE_INFO); APPSPAWN_ONLY_EXPER(bundleInfo != NULL, - APPSPAPWN_DUMP("App bundle info name: \"%{public}s\" index: %{public}d", + APPSPAWN_DUMP("App bundle info name: \"%{public}s\" index: %{public}d", bundleInfo->bundleName, bundleInfo->bundleIndex)); AppSpawnMsgDomainInfo *domainInfo = (AppSpawnMsgDomainInfo *)GetAppSpawnMsgInfo(message, TLV_DOMAIN_INFO); APPSPAWN_ONLY_EXPER(domainInfo != NULL, - APPSPAPWN_DUMP("App domain info hap: 0x%{public}x apl: \"%{public}s\"", domainInfo->hapFlags, domainInfo->apl)); + APPSPAWN_DUMP("App domain info hap: 0x%{public}x apl: \"%{public}s\"", domainInfo->hapFlags, domainInfo->apl)); AppSpawnMgr *mgr = GetAppSpawnMgr(); if (mgr == NULL || ((mgr->flags & APP_DEVELOPER_MODE) != APP_DEVELOPER_MODE)) { @@ -401,11 +404,11 @@ void DumpAppSpawnMsg(const AppSpawnMsgNode *message) } AppSpawnMsgOwnerId *owner = (AppSpawnMsgOwnerId *)GetAppSpawnMsgInfo(message, TLV_OWNER_INFO); - APPSPAWN_ONLY_EXPER(owner != NULL, APPSPAPWN_DUMP("App owner info: \"%{public}s\" ", owner->ownerId)); + APPSPAWN_ONLY_EXPER(owner != NULL, APPSPAWN_LOGV("App owner info: \"%{public}s\" ", owner->ownerId)); AppSpawnMsgInternetInfo *info = (AppSpawnMsgInternetInfo *)GetAppSpawnMsgInfo(message, TLV_INTERNET_INFO); APPSPAWN_ONLY_EXPER(info != NULL, - APPSPAPWN_DUMP("App internet permission info [%{public}d %{public}d]", + APPSPAWN_LOGV("App internet permission info [%{public}d %{public}d]", info->setAllowInternet, info->allowInternet)); for (uint32_t i = TLV_MAX; i < TLV_MAX + message->tlvCount; i++) { diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 6958437036a4e58a411a780ed6475bfb00d184c8..3401316ce72d007bb1c39d4ef594d36b7e5d2641 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -29,13 +29,14 @@ #include #include #include - +#include #include "appspawn.h" #include "appspawn_hook.h" #include "appspawn_modulemgr.h" #include "appspawn_manager.h" #include "appspawn_msg.h" #include "appspawn_server.h" +#include "appspawn_trace.h" #include "appspawn_utils.h" #include "init_socket.h" #include "init_utils.h" @@ -45,12 +46,17 @@ #include "cJSON.h" #ifdef APPSPAWN_HISYSEVENT #include "appspawn_hisysevent.h" +#include "hisysevent_adapter.h" #endif #define PARAM_BUFFER_SIZE 10 #define PATH_SIZE 256 #define FD_PATH_SIZE 128 -#define MAX_MEM_SIZE (4 * 1024) -#define APPSPAWN_MSG_USER_CHECK_COUNT 3 + +#define PREFORK_PROCESS "apppool" +#define APPSPAWN_MSG_USER_CHECK_COUNT 4 +#define USER_ID_MIN_VALUE 100 +#define USER_ID_MAX_VALUE 10736 +#define LOCK_STATUS_PARAM_SIZE 64 #ifndef PIDFD_NONBLOCK #define PIDFD_NONBLOCK O_NONBLOCK #endif @@ -65,6 +71,7 @@ static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *mess static inline void SetFdCtrl(int fd, int opt) { int option = fcntl(fd, F_GETFD); + APPSPAWN_CHECK(option >= 0, return, "SetFdCtrl fcntl failed %{public}d, %{public}d", option, errno); int ret = fcntl(fd, F_SETFD, (unsigned int)option | (unsigned int)opt); if (ret < 0) { APPSPAWN_LOGI("Set fd %{public}d option %{public}d %{public}d result: %{public}d", fd, option, opt, errno); @@ -107,6 +114,14 @@ static void StopAppSpawn(void) OH_ListInit(&appInfo->node); free(appInfo); } + + AppSpawnContent *content = GetAppSpawnContent(); + if (content != NULL && content->reservedPid > 0) { + int ret = kill(content->reservedPid, SIGKILL); + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "kill reserved pid %{public}d failed %{public}d %{public}d", + content->reservedPid, ret, errno); + content->reservedPid = 0; + } TraversalSpawnedProcess(AppQueueDestroyProc, NULL); APPSPAWN_LOGI("StopAppSpawn "); #ifdef APPSPAWN_HISYSEVENT @@ -115,34 +130,70 @@ static void StopAppSpawn(void) LE_StopLoop(LE_GetDefaultLoop()); } -static inline void DumpStatus(const char *appName, pid_t pid, int status) +static inline void DumpStatus(const char *appName, pid_t pid, int status, int *signal) { if (WIFSIGNALED(status)) { - APPSPAWN_LOGW("%{public}s with pid %{public}d exit with signal:%{public}d", appName, pid, WTERMSIG(status)); + *signal = WTERMSIG(status); + APPSPAWN_LOGW("%{public}s with pid %{public}d exit with signal:%{public}d", appName, pid, *signal); } if (WIFEXITED(status)) { - APPSPAWN_LOGW("%{public}s with pid %{public}d exit with code:%{public}d", appName, pid, WEXITSTATUS(status)); + *signal = WEXITSTATUS(status); + APPSPAWN_LOGW("%{public}s with pid %{public}d exit with code:%{public}d", appName, pid, *signal); + } +} + +APPSPAWN_STATIC void WriteSignalInfoToFd(AppSpawnedProcess *appInfo, AppSpawnContent *content, int signal) +{ + APPSPAWN_CHECK(content->signalFd > 0, return, "Invalid signal fd[%{public}d]", content->signalFd); + APPSPAWN_CHECK(appInfo->pid > 0, return, "Invalid pid[%{public}d]", appInfo->pid); + APPSPAWN_CHECK(appInfo->uid > 0, return, "Invalid uid[%{public}d]", appInfo->uid); + APPSPAWN_CHECK(appInfo->name != NULL, return, "Invalid name"); + + cJSON *root = cJSON_CreateObject(); + if (root == NULL) { + APPSPAWN_LOGE("signal json write create root object unsuccess"); + return; } + cJSON_AddNumberToObject(root, "pid", appInfo->pid); + cJSON_AddNumberToObject(root, "uid", appInfo->uid); + cJSON_AddNumberToObject(root, "signal", signal); + cJSON_AddStringToObject(root, "bundleName", appInfo->name); + char *jsonString = cJSON_Print(root); + cJSON_Delete(root); + + int ret = write(content->signalFd, jsonString, strlen(jsonString) + 1); + if (ret < 0) { + free(jsonString); + APPSPAWN_LOGE("Spawn Listen failed to write signal info to fd errno %{public}d", errno); + return; + } + APPSPAWN_LOGI("Spawn Listen successfully write signal info[%{public}s] to fd", jsonString); + free(jsonString); } static void HandleDiedPid(pid_t pid, uid_t uid, int status) { AppSpawnContent *content = GetAppSpawnContent(); + APPSPAWN_CHECK(content != NULL, return, "Invalid content"); + if (pid == content->reservedPid) { APPSPAWN_LOGW("HandleDiedPid with reservedPid %{public}d", pid); content->reservedPid = 0; } + int signal = 0; AppSpawnedProcess *appInfo = GetSpawnedProcess(pid); if (appInfo == NULL) { // If an exception occurs during app spawning, kill pid, return failed WaitChildDied(pid); - DumpStatus("unknown", pid, status); + DumpStatus("unknown", pid, status, &signal); return; } appInfo->exitStatus = status; APPSPAWN_CHECK_ONLY_LOG(appInfo->uid == uid, "Invalid uid %{public}u %{public}u", appInfo->uid, uid); - DumpStatus(appInfo->name, pid, status); + DumpStatus(appInfo->name, pid, status, &signal); + WriteSignalInfoToFd(appInfo, content, signal); ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo); + ProcessMgrHookExecute(STAGE_SERVER_APP_UMOUNT, GetAppSpawnContent(), appInfo); // if current process of death is nwebspawn, restart appspawn if (strcmp(appInfo->name, NWEBSPAWN_SERVER_NAME) == 0) { @@ -210,7 +261,7 @@ static void OnClose(const TaskHandle taskHandle) } APPSPAWN_LOGI("OnClose connectionId: %{public}u socket %{public}d", connection->connectionId, LE_GetSocketFd(taskHandle)); - DeleteAppSpawnMsg(connection->receiverCtx.incompleteMsg); + DeleteAppSpawnMsg(&connection->receiverCtx.incompleteMsg); connection->receiverCtx.incompleteMsg = NULL; // connect close, to close spawning app AppSpawningCtxTraversal(AppSpawningCtxOnClose, connection); @@ -264,7 +315,7 @@ static void WaitMsgCompleteTimeOut(const TimerHandle taskHandle, void *context) { AppSpawnConnection *connection = (AppSpawnConnection *)context; APPSPAWN_LOGE("Long time no msg complete so close connectionId: %{public}u", connection->connectionId); - DeleteAppSpawnMsg(connection->receiverCtx.incompleteMsg); + DeleteAppSpawnMsg(&connection->receiverCtx.incompleteMsg); connection->receiverCtx.incompleteMsg = NULL; LE_CloseStreamTask(LE_GetDefaultLoop(), connection->stream); } @@ -324,6 +375,7 @@ APPSPAWN_STATIC bool OnConnectionUserCheck(uid_t uid) 0, // root 0 3350, // app_fwk_update 3350 5523, // foundation 5523 + 1090, //storage_manager 1090 }; for (int i = 0; i < APPSPAWN_MSG_USER_CHECK_COUNT; i++) { @@ -439,13 +491,15 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, // decode msg ret = DecodeAppSpawnMsg(message); APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); + StartAppspawnTrace("ProcessRecvMsg"); (void)ProcessRecvMsg(connection, message); + FinishAppspawnTrace(); message = NULL; currLen += buffLen - reminder; } while (reminder > 0); if (message) { - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); } if (ret != 0) { LE_CloseTask(LE_GetDefaultLoop(), taskHandle); @@ -456,7 +510,6 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, APPSPAWN_CHECK(ret == 0, LE_CloseStreamTask(LE_GetDefaultLoop(), taskHandle); return, "Failed to create time for connection"); } - return; } static char *GetMapMem(uint32_t clientId, const char *processName, uint32_t size, bool readOnly, bool isNweb) @@ -538,7 +591,7 @@ static void ProcessChildProcessFd(const WatcherHandle taskHandle, int fd, uint32 { APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return); pid_t pid = *(pid_t *)context; - APPSPAWN_LOGI("Kill process group with process group id %{public}d, pidFd %{public}d", pid, fd); + APPSPAWN_LOGI("Clear process group with pid %{public}d, pidFd %{public}d", pid, fd); AppSpawnedProcess *appInfo = GetSpawnedProcess(pid); if (appInfo == NULL) { APPSPAWN_LOGW("Cannot get app info by bundle name: %{public}d", pid); @@ -607,12 +660,14 @@ static int AddChildWatcher(AppSpawningCtx *property) { uint32_t defTimeout = IsChildColdRun(property) ? COLD_CHILD_RESPONSE_TIMEOUT : WAIT_CHILD_RESPONSE_TIMEOUT; uint32_t timeout = GetSpawnTimeout(defTimeout); + LE_WatchInfo watchInfo = {}; watchInfo.fd = property->forkCtx.fd[0]; watchInfo.flags = WATCHER_ONCE; watchInfo.events = EVENT_READ; watchInfo.processEvent = ProcessChildResponse; LE_STATUS status = LE_StartWatcher(LE_GetDefaultLoop(), &property->forkCtx.watcherHandle, &watchInfo, property); + APPSPAWN_LOGI("AddChildWatcher with timeout %{public}u fd %{public}d", timeout, watchInfo.fd); APPSPAWN_CHECK(status == LE_SUCCESS, return APPSPAWN_SYSTEM_ERROR, "Failed to watch child %{public}d", property->pid); status = LE_CreateTimer(LE_GetDefaultLoop(), &property->forkCtx.timer, WaitChildTimeout, property); @@ -648,7 +703,25 @@ static bool IsSupportRunHnp() return false; } -static int WritePreforkMsg(AppSpawningCtx *property) +static void ClearMMAP(int clientId, uint32_t memSize) +{ + char path[PATH_MAX] = {0}; + int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, APPSPAWN_MSG_DIR "appspawn/prefork_%d", clientId); + APPSPAWN_CHECK_ONLY_LOG(ret > 0, "snprintf failed with %{public}d %{public}d", ret, errno); + if (ret > 0 && access(path, F_OK) == 0) { + ret = unlink(path); + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "prefork unlink result %{public}d %{public}d", ret, errno); + } + + AppSpawnContent *content = GetAppSpawnContent(); + if (content != NULL && content->propertyBuffer != NULL) { + ret = munmap(content->propertyBuffer, memSize); + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "munmap failed %{public}d %{public}d", ret, errno); + content->propertyBuffer = NULL; + } +} + +static int WritePreforkMsg(AppSpawningCtx *property, uint32_t memSize) { AppSpawnContent *content = GetAppSpawnContent(); if (content == NULL || content->propertyBuffer == NULL) { @@ -656,22 +729,29 @@ static int WritePreforkMsg(AppSpawningCtx *property) return -1; } - int ret = memcpy_s(content->propertyBuffer, MAX_MEM_SIZE, &property->message->msgHeader, sizeof(AppSpawnMsg)); - APPSPAWN_CHECK(ret == 0, goto fail, "memcpys_s msgHeader failed"); - ret = memcpy_s((char *)content->propertyBuffer + sizeof(AppSpawnMsg), MAX_MEM_SIZE - sizeof(AppSpawnMsg), - property->message->buffer, property->message->msgHeader.msgLen - sizeof(AppSpawnMsg)); - APPSPAWN_CHECK(ret == 0, goto fail, "memcpys_s AppSpawnMsg failed"); - return ret; + int ret = memcpy_s(content->propertyBuffer, memSize, &property->message->msgHeader, sizeof(AppSpawnMsg)); + if (ret != 0) { + APPSPAWN_LOGE("memcpys_s msgHeader failed"); + ClearMMAP(property->client.id, memSize); + return ret; + } -fail: - munmap((char *)content->propertyBuffer, MAX_MEM_SIZE); + ret = memcpy_s((char *)content->propertyBuffer + sizeof(AppSpawnMsg), memSize - sizeof(AppSpawnMsg), + property->message->buffer, property->message->msgHeader.msgLen - sizeof(AppSpawnMsg)); + if (ret != 0) { + APPSPAWN_LOGE("memcpys_s AppSpawnMsg failed"); + ClearMMAP(property->client.id, memSize); + return ret; + } + ret = munmap((char *)content->propertyBuffer, memSize); + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "munmap failed %{public}d,%{public}d", ret, errno); content->propertyBuffer = NULL; return ret; } -static int GetAppSpawnMsg(AppSpawningCtx *property) +static int GetAppSpawnMsg(AppSpawningCtx *property, uint32_t memSize) { - uint8_t *buffer = (uint8_t *)GetMapMem(property->client.id, "prefork", MAX_MEM_SIZE, true, false); + uint8_t *buffer = (uint8_t *)GetMapMem(property->client.id, "prefork", memSize, true, false); if (buffer == NULL) { APPSPAWN_LOGE("prefork buffer is null can not write propery"); return -1; @@ -679,7 +759,7 @@ static int GetAppSpawnMsg(AppSpawningCtx *property) uint32_t msgRecvLen = 0; uint32_t remainLen = 0; property->forkCtx.childMsg = (char *)buffer; - property->forkCtx.msgSize = MAX_MEM_SIZE; + property->forkCtx.msgSize = memSize; AppSpawnMsgNode *message = NULL; int ret = GetAppSpawnMsgFromBuffer(buffer, ((AppSpawnMsg *)buffer)->msgLen, &message, &msgRecvLen, &remainLen); // release map @@ -692,23 +772,26 @@ static int GetAppSpawnMsg(AppSpawningCtx *property) return -1; } -static void ClearMMAP(int clientId) +static int SetPreforkProcessName(AppSpawnContent *content) { - char path[PATH_MAX] = {0}; - int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, APPSPAWN_MSG_DIR "appspawn/prefork_%d", clientId); - APPSPAWN_LOGV("prefork unlink %{public}s ret :%{public}d", path, ret); - if (ret > 0) { - errno = 0; - ret = unlink(path); - APPSPAWN_LOGV("prefork unlink result %{public}d %{public}d", ret, errno); + int ret = prctl(PR_SET_NAME, PREFORK_PROCESS); + if (ret == -1) { + return errno; } - AppSpawnContent *content = GetAppSpawnContent(); - if (content != NULL && content->propertyBuffer != NULL) { - ret = munmap(content->propertyBuffer, MAX_MEM_SIZE); - APPSPAWN_CHECK_ONLY_LOG(ret == 0, "munmap failed %{public}d", ret); - content->propertyBuffer = NULL; + ret = memset_s(content->longProcName, + (size_t)content->longProcNameLen, 0, (size_t)content->longProcNameLen); + if (ret != EOK) { + return EINVAL; + } + + ret = strncpy_s(content->longProcName, content->longProcNameLen, + PREFORK_PROCESS, strlen(PREFORK_PROCESS)); + if (ret != EOK) { + return EINVAL; } + + return 0; } static void ProcessPreFork(AppSpawnContent *content, AppSpawningCtx *property) @@ -727,29 +810,32 @@ static void ProcessPreFork(AppSpawnContent *content, AppSpawningCtx *property) if (content->reservedPid == 0) { (void)close(property->forkCtx.fd[0]); (void)close(property->forkCtx.fd[1]); - int isRet = prctl(PR_SET_NAME, "apppool"); - APPSPAWN_LOGI("prefork process start wait read msg with set processname %{public}d", isRet); - AppSpawnClient client = {0, 0}; - int infoSize = read(content->parentToChildFd[0], &client, sizeof(AppSpawnClient)); - if (infoSize != sizeof(AppSpawnClient)) { + int isRet = SetPreforkProcessName(content); + APPSPAWN_LOGV("prefork process start wait read msg with set processname %{public}d", isRet); + AppSpawnPreforkMsg preforkMsg = {0}; + int infoSize = read(content->parentToChildFd[0], &preforkMsg, sizeof(AppSpawnPreforkMsg)); + if (infoSize != sizeof(AppSpawnPreforkMsg) || preforkMsg.msgLen > MAX_MSG_TOTAL_LENGTH || + preforkMsg.msgLen < sizeof(AppSpawnMsg)) { APPSPAWN_LOGE("prefork process read msg failed %{public}d,%{public}d", infoSize, errno); ProcessExit(0); return; } - property->client.id = client.id; - property->client.flags = client.flags; + + property->client.id = preforkMsg.id; + property->client.flags = preforkMsg.flags; property->isPrefork = true; property->forkCtx.fd[0] = content->preforkFd[0]; property->forkCtx.fd[1] = content->preforkFd[1]; property->state = APP_STATE_SPAWNING; - if (GetAppSpawnMsg(property) == -1) { + const uint32_t memSize = (preforkMsg.msgLen / MAX_MSG_BLOCK_LEN + 1) * MAX_MSG_BLOCK_LEN; + if (GetAppSpawnMsg(property, memSize) == -1) { APPSPAWN_LOGE("prefork child read GetAppSpawnMsg failed"); - ClearMMAP(property->client.id); + ClearMMAP(property->client.id, memSize); content->notifyResToParent(content, &property->client, APPSPAWN_MSG_INVALID); ProcessExit(0); return; } - ClearMMAP(property->client.id); + ClearMMAP(property->client.id, memSize); // Inherit the error level of the original process (void)fdsan_set_error_level(errorLevel); ProcessExit(AppSpawnChild(content, &property->client)); @@ -758,38 +844,57 @@ static void ProcessPreFork(AppSpawnContent *content, AppSpawningCtx *property) } } +static int NormalSpawnChild(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid) +{ + APPSPAWN_CHECK(client != NULL, return APPSPAWN_ARG_INVALID, "client is null"); + int ret = InitForkContext((AppSpawningCtx *)client); + APPSPAWN_CHECK(ret == 0, return ret, "init fork context failed"); + return AppSpawnProcessMsg(content, client, childPid); +} + static int AppSpawnProcessMsgForPrefork(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid) { int ret = 0; AppSpawningCtx *property = (AppSpawningCtx *)client; - if (content->reservedPid <= 0) { - APPSPAWN_CHECK(client != NULL, return ret, "client is null"); - ret = InitForkContext((AppSpawningCtx *)client); - APPSPAWN_CHECK(ret == 0, return ret, "init fork context failed"); - ret = AppSpawnProcessMsg(content, client, childPid); + ret = NormalSpawnChild(content, client, childPid); } else { - APPSPAWN_CHECK_ONLY_EXPER(content->propertyBuffer == NULL, ClearMMAP(client->id)); - content->propertyBuffer = GetMapMem(property->client.id, "prefork", MAX_MEM_SIZE, false, false); - APPSPAWN_CHECK(content->propertyBuffer != NULL, return -1, "GetPreforkMem failed"); - ret = WritePreforkMsg(property); - APPSPAWN_CHECK(ret == 0, return ret, "WritePreforkMsg failed"); - + const uint32_t memSize = (property->message->msgHeader.msgLen / MAX_MSG_BLOCK_LEN + 1) * + MAX_MSG_BLOCK_LEN; + content->propertyBuffer = GetMapMem(property->client.id, "prefork", memSize, false, false); + if (content->propertyBuffer == NULL) { + ClearMMAP(property->client.id, memSize); + return NormalSpawnChild(content, client, childPid); + } + ret = WritePreforkMsg(property, memSize); + if (ret != 0) { + ClearMMAP(property->client.id, memSize); + return NormalSpawnChild(content, client, childPid); + } *childPid = content->reservedPid; property->forkCtx.fd[0] = content->preforkFd[0]; property->forkCtx.fd[1] = content->preforkFd[1]; - int option = fcntl(property->forkCtx.fd[0], F_GETFD); if (option > 0) { ret = fcntl(property->forkCtx.fd[0], F_SETFD, (unsigned int)option | O_NONBLOCK); APPSPAWN_CHECK_ONLY_LOG(ret == 0, "fcntl failed %{public}d,%{public}d", ret, errno); } + AppSpawnPreforkMsg *preforkMsg = (AppSpawnPreforkMsg *)calloc(1, sizeof(AppSpawnPreforkMsg)); + if (preforkMsg == NULL) { + APPSPAWN_LOGE("calloc failed"); + ClearMMAP(property->client.id, memSize); + return NormalSpawnChild(content, client, childPid); + } - ssize_t writesize = write(content->parentToChildFd[1], client, sizeof(AppSpawnClient)) ; - APPSPAWN_CHECK(writesize == sizeof(AppSpawnClient), kill(*childPid, SIGKILL); + preforkMsg->id = client->id; + preforkMsg->flags = client->flags; + preforkMsg->msgLen = property->message->msgHeader.msgLen; + ssize_t writesize = write(content->parentToChildFd[1], preforkMsg, sizeof(AppSpawnPreforkMsg)) ; + APPSPAWN_CHECK(writesize == sizeof(AppSpawnPreforkMsg), kill(*childPid, SIGKILL); *childPid = 0; ret = -1, "write msg to child failed %{public}d", errno); + free(preforkMsg); } ProcessPreFork(content, property); return ret; @@ -802,6 +907,7 @@ static bool IsSupportPrefork(AppSpawnContent *content, AppSpawnClient *client) return false; } if (!content->enablePerfork) { + APPSPAWN_LOGV("g_enablePrefork %{public}d", content->enablePerfork); return false; } AppSpawningCtx *property = (AppSpawningCtx *)client; @@ -814,7 +920,7 @@ static bool IsSupportPrefork(AppSpawnContent *content, AppSpawnClient *client) return false; } -static bool IsBootFinished() +static bool IsBootFinished(void) { char buffer[32] = {0}; // 32 max int ret = GetParameter("bootevent.boot.completed", "false", buffer, sizeof(buffer)); @@ -822,6 +928,7 @@ static bool IsBootFinished() return isBootCompleted; } + static int RunAppSpawnProcessMsg(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid) { int ret = 0; @@ -829,10 +936,7 @@ static int RunAppSpawnProcessMsg(AppSpawnContent *content, AppSpawnClient *clien if (IsBootFinished() && IsSupportPrefork(content, client)) { ret = AppSpawnProcessMsgForPrefork(content, client, childPid); } else { - APPSPAWN_CHECK(client != NULL, return ret, "client is null"); - ret = InitForkContext((AppSpawningCtx *)client); - APPSPAWN_CHECK(ret == 0, return ret, "init fork context failed"); - ret = AppSpawnProcessMsg(content, client, childPid); + ret = NormalSpawnChild(content, client, childPid); } return ret; } @@ -842,7 +946,7 @@ static void ProcessSpawnReqMsg(AppSpawnConnection *connection, AppSpawnMsgNode * int ret = CheckAppSpawnMsg(message); if (ret != 0) { SendResponse(connection, &message->msgHeader, ret, 0); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); return; } @@ -850,14 +954,14 @@ static void ProcessSpawnReqMsg(AppSpawnConnection *connection, AppSpawnMsgNode * if (IsSupportRunHnp()) { SetAppSpawnMsgFlag(message, TLV_MSG_FLAGS, APP_FLAGS_DEVELOPER_MODE); } else { - APPSPAWN_LOGI("Not support execute hnp file!"); + APPSPAWN_LOGV("Not support execute hnp file!"); } } AppSpawningCtx *property = CreateAppSpawningCtx(); if (property == NULL) { SendResponse(connection, &message->msgHeader, APPSPAWN_SYSTEM_ERROR, 0); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); return; } @@ -891,9 +995,13 @@ static uint32_t g_crashTimes = 0; static void WaitChildDied(pid_t pid) { AppSpawningCtx *property = GetAppSpawningCtxByPid(pid); - if (property != NULL && property->state == APP_STATE_SPAWNING) { + if (property != NULL && property->message != NULL && property->state == APP_STATE_SPAWNING) { + const char *processName = GetProcessName(property); APPSPAWN_LOGI("Child process %{public}s fail \'child crash \'pid %{public}d appId: %{public}d", - GetProcessName(property), property->pid, property->client.id); + processName, property->pid, property->client.id); +#ifdef APPSPAWN_HISYSEVENT + ReportSpawnChildProcessFail(processName, ERR_APPSPAWN_CHILD_CRASH, APPSPAWN_CHILD_CRASH); +#endif if (property->client.id == g_lastDiedAppId + 1) { g_crashTimes++; } else { @@ -906,6 +1014,9 @@ static void WaitChildDied(pid_t pid) if (g_crashTimes >= MAX_CRASH_TIME) { APPSPAWN_LOGW("Continuous failures in spawning the app, restart appspawn"); +#ifdef APPSPAWN_HISYSEVENT + ReportKeyEvent(APPSPAWN_MAX_FAILURES_EXCEEDED); +#endif StopAppSpawn(); } } @@ -922,11 +1033,14 @@ static void WaitChildTimeout(const TimerHandle taskHandle, void *context) #endif kill(property->pid, SIGKILL); } +#ifdef APPSPAWN_HISYSEVENT + ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_TIMEOUT, APPSPAWN_SPAWN_TIMEOUT); +#endif SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_SPAWN_TIMEOUT, 0); DeleteAppSpawningCtx(property); } -static int ProcessChildFdCheck(int fd, AppSpawningCtx *property, int *pResult) +static int ProcessChildFdCheck(int fd, AppSpawningCtx *property) { int result = 0; (void)read(fd, &result, sizeof(result)); @@ -935,12 +1049,14 @@ static int ProcessChildFdCheck(int fd, AppSpawningCtx *property, int *pResult) APPSPAWN_CHECK(property->message != NULL, return -1, "Invalid message in ctx %{public}d", property->client.id); if (result != 0) { +#ifdef APPSPAWN_HISYSEVENT + ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_FAIL, result); +#endif SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid); DeleteAppSpawningCtx(property); return -1; } - *pResult = result; - + return 0; } @@ -950,13 +1066,12 @@ static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_ property->forkCtx.watcherHandle = NULL; // delete watcher LE_RemoveWatcher(LE_GetDefaultLoop(), (WatcherHandle)taskHandle); - int result = 0; - if (ProcessChildFdCheck(fd, property, &result) != 0) { + if (ProcessChildFdCheck(fd, property) != 0) { return; } // success - bool isDebuggable = CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE) == 1 ? true : false; + bool isDebuggable = CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE); AppSpawnedProcess *appInfo = AddSpawnedProcess(property->pid, GetBundleName(property), isDebuggable); if (appInfo) { AppSpawnMsgDacInfo *dacInfo = GetAppProperty(property, TLV_DAC_INFO); @@ -970,12 +1085,29 @@ static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_ #endif clock_gettime(CLOCK_MONOTONIC, &appInfo->spawnEnd); // add max info + +#ifdef APPSPAWN_HISYSEVENT + //add process spawn duration into hisysevent,(ms) + uint32_t spawnProcessDuration = (uint32_t)((appInfo->spawnEnd.tv_sec - appInfo->spawnStart.tv_sec) * + (APPSPAWN_USEC_TO_NSEC)) +(uint32_t)((appInfo->spawnEnd.tv_nsec - appInfo->spawnStart.tv_nsec) / + (APPSPAWN_MSEC_TO_NSEC)); + AppSpawnMgr *appspawnMgr = GetAppSpawnMgr(); + if (appspawnMgr != NULL) { + AddStatisticEventInfo(appspawnMgr->hisyseventInfo, spawnProcessDuration, IsBootFinished()); + } +#ifndef ASAN_DETECTOR + uint64_t diff = DiffTime(&appInfo->spawnStart, &appInfo->spawnEnd); + APPSPAWN_CHECK_ONLY_EXPER(diff < (IsChildColdRun(property) ? SPAWN_COLDRUN_DURATION : SPAWN_DURATION), + ReportAbnormalDuration("SPAWNCHILD", diff)); +#endif +#endif } + WatchChildProcessFd(property); ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, GetAppSpawnContent(), appInfo); // response AppSpawnHookExecute(STAGE_PARENT_PRE_RELY, 0, GetAppSpawnContent(), &property->client); - SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid); + SendResponse(property->message->connection, &property->message->msgHeader, 0, property->pid); AppSpawnHookExecute(STAGE_PARENT_POST_RELY, 0, GetAppSpawnContent(), &property->client); #ifdef DEBUG_BEGETCTL_BOOT if (IsDeveloperModeOpen()) { @@ -1041,9 +1173,9 @@ void AppSpawnDestroyContent(AppSpawnContent *content) LE_CloseStreamTask(LE_GetDefaultLoop(), appSpawnContent->server); appSpawnContent->server = NULL; } + DeleteAppSpawnMgr(appSpawnContent); LE_StopLoop(LE_GetDefaultLoop()); LE_CloseLoop(LE_GetDefaultLoop()); - DeleteAppSpawnMgr(appSpawnContent); } APPSPAWN_STATIC int AppSpawnColdStartApp(struct AppSpawnContent *content, AppSpawnClient *client) @@ -1072,7 +1204,6 @@ APPSPAWN_STATIC int AppSpawnColdStartApp(struct AppSpawnContent *content, AppSpa APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format shmId "); len = sprintf_s(buffer[3], sizeof(buffer[3]), " %u ", property->client.id); // 3 3 index for client id APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format shmId "); - #ifndef APPSPAWN_TEST char *mode = IsNWebSpawnMode((AppSpawnMgr *)content) ? "nweb_cold" : "app_cold"; // 2 2 index for dest path @@ -1130,7 +1261,7 @@ static AppSpawningCtx *GetAppSpawningCtxFromArg(AppSpawnMgr *content, int argc, return property; } NotifyResToParent(&content->content, &property->client, APPSPAWN_MSG_INVALID); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); DeleteAppSpawningCtx(property); return NULL; } @@ -1182,6 +1313,12 @@ static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[]) (void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGTERM); } + if (IsAppSpawnMode(appSpawnContent)) { + struct sched_param param = { 0 }; + param.sched_priority = 1; + int ret = sched_setscheduler(0, SCHED_FIFO, ¶m); + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "UpdateSchedPrio failed ret: %{public}d, %{public}d", ret, errno); + } LE_RunLoop(LE_GetDefaultLoop()); APPSPAWN_LOGI("AppSpawnRun exit mode: %{public}d ", content->mode); @@ -1198,11 +1335,11 @@ APPSPAWN_STATIC int AppSpawnClearEnv(AppSpawnMgr *content, AppSpawningCtx *prope return 0; } -static int IsEnablePerfork() +static int IsEnablePrefork(void) { char buffer[32] = {0}; int ret = GetParameter("persist.sys.prefork.enable", "true", buffer, sizeof(buffer)); - APPSPAWN_LOGV("IsEnablePerfork result %{public}d, %{public}s", ret, buffer); + APPSPAWN_LOGV("IsEnablePrefork result %{public}d, %{public}s", ret, buffer); return strcmp(buffer, "true") == 0; } @@ -1213,6 +1350,9 @@ AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcNam AppSpawnMgr *appSpawnContent = CreateAppSpawnMgr(mode); APPSPAWN_CHECK(appSpawnContent != NULL, return NULL, "Failed to alloc memory for appspawn"); +#ifdef APPSPAWN_HISYSEVENT + appSpawnContent->hisyseventInfo = InitHisyseventTimer(); +#endif appSpawnContent->content.longProcName = longProcName; appSpawnContent->content.longProcNameLen = nameLen; appSpawnContent->content.notifyResToParent = NotifyResToParent; @@ -1226,7 +1366,7 @@ AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcNam APPSPAWN_CHECK(ret == 0, AppSpawnDestroyContent(&appSpawnContent->content); return NULL, "Failed to create server"); } - appSpawnContent->content.enablePerfork = IsEnablePerfork(); + appSpawnContent->content.enablePerfork = IsEnablePrefork(); return &appSpawnContent->content; } @@ -1293,7 +1433,7 @@ static AppSpawnMsgNode *ProcessSpawnBegetctlMsg(AppSpawnConnection *connection, APPSPAWN_CHECK(msgNode != NULL, return NULL, "Failed to rebuild app message node"); int ret = DecodeAppSpawnMsg(msgNode); if (ret != 0) { - DeleteAppSpawnMsg(msgNode); + DeleteAppSpawnMsg(&msgNode); return NULL; } return msgNode; @@ -1304,18 +1444,18 @@ static void ProcessBegetCmdMsg(AppSpawnConnection *connection, AppSpawnMsgNode * AppSpawnMsg *msg = &message->msgHeader; if (!IsDeveloperModeOpen()) { SendResponse(connection, msg, APPSPAWN_DEBUG_MODE_NOT_SUPPORT, 0); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); return; } AppSpawnMsgNode *msgNode = ProcessSpawnBegetctlMsg(connection, message); if (msgNode == NULL) { SendResponse(connection, msg, APPSPAWN_DEBUG_MODE_NOT_SUPPORT, 0); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); return; } ProcessSpawnReqMsg(connection, msgNode); - DeleteAppSpawnMsg(message); - DeleteAppSpawnMsg(msgNode); + DeleteAppSpawnMsg(&message); + DeleteAppSpawnMsg(&msgNode); } static int GetArkWebInstallPath(const char *key, char *value) @@ -1448,24 +1588,28 @@ static void ProcessSpawnRestartMsg(AppSpawnConnection *connection, AppSpawnMsgNo AppSpawnContent *content = GetAppSpawnContent(); if (!IsNWebSpawnMode((AppSpawnMgr *)content)) { SendResponse(connection, &message->msgHeader, APPSPAWN_MSG_INVALID, 0); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); APPSPAWN_LOGE("Restart msg only support nwebspawn"); return; } TraversalSpawnedProcess(AppQueueDestroyProc, NULL); SendResponse(connection, &message->msgHeader, 0, 0); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); (void) ServerStageHookExecute(STAGE_SERVER_EXIT, content); errno = 0; int fd = GetControlSocket(NWEBSPAWN_SOCKET_NAME); APPSPAWN_CHECK(fd >= 0, return, "Get fd failed %{public}d, errno %{public}d", fd, errno); + int ret = 0; int op = fcntl(fd, F_GETFD); - int ret = fcntl(fd, F_SETFD, (unsigned int)op & ~FD_CLOEXEC); - if (ret < 0) { - APPSPAWN_LOGE("Set fd failed %{public}d, %{public}d, ret %{public}d, errno %{public}d", fd, op, ret, errno); + APPSPAWN_CHECK_ONLY_LOG(op >= 0, "fcntl failed %{public}d", op); + if (op > 0) { + ret = fcntl(fd, F_SETFD, (unsigned int)op & ~FD_CLOEXEC); + if (ret < 0) { + APPSPAWN_LOGE("Set fd failed %{public}d, %{public}d, ret %{public}d, errno %{public}d", fd, op, ret, errno); + } } char *path = "/system/bin/appspawn"; @@ -1475,6 +1619,23 @@ static void ProcessSpawnRestartMsg(AppSpawnConnection *connection, AppSpawnMsgNo APPSPAWN_LOGE("Failed to execv, ret %{public}d, errno %{public}d", ret, errno); } +APPSPAWN_STATIC void ProcessUninstallDebugHap(AppSpawnConnection *connection, AppSpawnMsgNode *message) +{ + APPSPAWN_LOGI("ProcessUninstallDebugHap start"); + AppSpawningCtx *property = CreateAppSpawningCtx(); + if (property == NULL) { + SendResponse(connection, &message->msgHeader, APPSPAWN_SYSTEM_ERROR, 0); + DeleteAppSpawnMsg(&message); + return; + } + + property->message = message; + property->message->connection = connection; + int ret = AppSpawnHookExecute(STAGE_PARENT_UNINSTALL, 0, GetAppSpawnContent(), &property->client); + SendResponse(connection, &message->msgHeader, ret, 0); + DeleteAppSpawningCtx(property); +} + APPSPAWN_STATIC int AppspawpnDevicedebugKill(int pid, cJSON *args) { cJSON *signal = cJSON_GetObjectItem(args, "signal"); @@ -1486,12 +1647,12 @@ APPSPAWN_STATIC int AppspawpnDevicedebugKill(int pid, cJSON *args) AppSpawnedProcess *appInfo = GetSpawnedProcess(pid); if (appInfo == NULL) { APPSPAWN_LOGE("appspawn devicedebug get app info unsuccess, pid=%{public}d", pid); - return -1; + return APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_EXIST; } if (!appInfo->isDebuggable) { APPSPAWN_LOGE("appspawn devicedebug process is not debuggable, pid=%{public}d", pid); - return -1; + return APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_DEBUGGABLE; } APPSPAWN_LOGI("appspawn devicedebug debugable=%{public}d, pid=%{public}d, signal=%{public}d", @@ -1510,7 +1671,7 @@ APPSPAWN_STATIC int AppspawnDevicedebugDeal(const char* op, int pid, cJSON *args if (strcmp(op, "kill") == 0) { return AppspawpnDevicedebugKill(pid, args); } - + APPSPAWN_LOGE("appspawn devicedebug op:%{public}s invaild", op); return -1; @@ -1536,22 +1697,123 @@ APPSPAWN_STATIC int ProcessAppSpawnDeviceDebugMsg(AppSpawnMsgNode *message) cJSON *app = cJSON_GetObjectItem(json, "app"); if (!cJSON_IsNumber(app)) { APPSPAWN_LOGE("appspawn devicedebug json get app fail"); + cJSON_Delete(json); return -1; } cJSON *op = cJSON_GetObjectItem(json, "op"); if (!cJSON_IsString(op) || op->valuestring == NULL) { APPSPAWN_LOGE("appspawn devicedebug json get op fail"); + cJSON_Delete(json); return -1; } cJSON *args = cJSON_GetObjectItem(json, "args"); if (!cJSON_IsObject(args)) { APPSPAWN_LOGE("appspawn devicedebug json get args fail"); + cJSON_Delete(json); return -1; } - return AppspawnDevicedebugDeal(op->valuestring, app->valueint, args); + int result = AppspawnDevicedebugDeal(op->valuestring, app->valueint, args); + cJSON_Delete(json); + return result; +} + +static void ProcessAppSpawnLockStatusMsg(AppSpawnMsgNode *message) +{ + APPSPAWN_CHECK_ONLY_EXPER(message != NULL, return); + uint32_t len = 0; + char *lockstatus = (char *)GetAppSpawnMsgExtInfo(message, "lockstatus", &len); + APPSPAWN_CHECK(lockstatus != NULL, return, "failed to get lockstatus"); + APPSPAWN_LOGI("appspawn get lockstatus %{public}s from storage_manager", lockstatus); + char *userLockStatus = NULL; + // userLockStatus format example: 100:0 100 for userid 0:unlock 1:lock + char *userIdStr = strtok_r(lockstatus, ":", &userLockStatus); + APPSPAWN_CHECK(userIdStr != NULL && userLockStatus != NULL, return, + "lockstatus not satisfied format, failed to get userLockStatus"); + int userId = atoi(userIdStr); + if (userId < USER_ID_MIN_VALUE || userId > USER_ID_MAX_VALUE) { + APPSPAWN_LOGE("userId err %{public}s", userIdStr); + return; + } + if (strcmp(userLockStatus, "0") != 0 && strcmp(userLockStatus, "1") != 0) { + APPSPAWN_LOGE("userLockStatus err %{public}s", userLockStatus); + return; + } + char lockStatusParam[LOCK_STATUS_PARAM_SIZE] = {0}; + int ret = snprintf_s(lockStatusParam, sizeof(lockStatusParam), sizeof(lockStatusParam) - 1, + "startup.appspawn.lockstatus_%d", userId); + APPSPAWN_CHECK(ret > 0, return, "get lock status param failed, errno %{public}d", errno); + ret = SetParameter(lockStatusParam, userLockStatus); + APPSPAWN_CHECK(ret == 0, return, "failed to set lockstatus param value ret %{public}d", ret); +#ifdef APPSPAWN_HISYSEVENT + ReportKeyEvent(strcmp(userLockStatus, "0") == 0 ? UNLOCK_SUCCESS : LOCK_SUCCESS); +#endif +#ifndef APPSPAWN_SANDBOX_NEW + if (strcmp(userLockStatus, "0") == 0) { + ServerStageHookExecute(STAGE_SERVER_LOCK, GetAppSpawnContent()); + } +#endif +} + +APPSPAWN_STATIC int AppSpawnReqMsgFdGet(AppSpawnConnection *connection, AppSpawnMsgNode *message, + const char *fdName, int *fd) +{ + APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL && connection != NULL, return -1); + APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset != NULL, return -1); + int findFdIndex = 0; + AppSpawnMsgReceiverCtx recvCtx = connection->receiverCtx; + APPSPAWN_CHECK(recvCtx.fds != NULL && recvCtx.fdCount > 0, return 0, + "no need get fd info %{public}d, %{public}d", recvCtx.fds != NULL, recvCtx.fdCount); + + for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) { + if (message->tlvOffset[index] == INVALID_OFFSET) { + return APPSPAWN_SYSTEM_ERROR; + } + uint8_t *data = message->buffer + message->tlvOffset[index]; + if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) { + continue; + } + AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data; + if (strcmp(tlv->tlvName, MSG_EXT_NAME_APP_FD) != 0) { + continue; + } + APPSPAWN_CHECK(findFdIndex < recvCtx.fdCount && recvCtx.fds[findFdIndex] > 0, return -1, + "check get fd args failed %{public}d, %{public}d, %{public}d", + findFdIndex, recvCtx.fdCount, recvCtx.fds[findFdIndex]); + + if (strcmp((const char *)(data + sizeof(AppSpawnTlvExt)), fdName) == 0 && recvCtx.fds[findFdIndex] > 0) { + *fd = recvCtx.fds[findFdIndex]; + APPSPAWN_LOGI("Spawn Listen fd %{public}s get success %{public}d", fdName, recvCtx.fds[findFdIndex]); + break; + } + findFdIndex++; + if (findFdIndex >= recvCtx.fdCount) { + break; + } + } + return 0; +} + +APPSPAWN_STATIC void ProcessObserveProcessSignalMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) +{ + APPSPAWN_CHECK_ONLY_EXPER(message != NULL, return); + int fd = 0; + int ret = AppSpawnReqMsgFdGet(connection, message, SPAWN_LISTEN_FD_NAME, &fd); + if (fd <= 0 || ret != 0) { + APPSPAWN_LOGE("Spawn Listen appspawn signal fd get unsuccess"); + SendResponse(connection, &message->msgHeader, APPSPAWN_SYSTEM_ERROR, 0); + DeleteAppSpawnMsg(&message); + return; + } + + AppSpawnContent *content = GetAppSpawnContent(); + APPSPAWN_CHECK(content != NULL, return, "Spawn Listen appspawn content is null"); + content->signalFd = fd; + connection->receiverCtx.fdCount = 0; + SendResponse(connection, &message->msgHeader, 0, 0); + DeleteAppSpawnMsg(&message); } static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) @@ -1569,7 +1831,7 @@ static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *mess AppSpawnResult result = {0}; ret = ProcessTerminationStatusMsg(message, &result); SendResponse(connection, msg, ret == 0 ? result.result : ret, result.pid); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); break; } case MSG_SPAWN_NATIVE_PROCESS: // spawn msg @@ -1580,7 +1842,7 @@ static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *mess case MSG_DUMP: ProcessAppSpawnDumpMsg(message); SendResponse(connection, msg, 0, 0); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); break; case MSG_BEGET_CMD: { ProcessBegetCmdMsg(connection, message); @@ -1589,7 +1851,7 @@ static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *mess case MSG_BEGET_SPAWNTIME: SendResponse(connection, msg, GetAppSpawnMgr()->spawnTime.minAppspawnTime, GetAppSpawnMgr()->spawnTime.maxAppspawnTime); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); break; case MSG_UPDATE_MOUNT_POINTS: ret = ProcessSpawnRemountMsg(connection, message); @@ -1601,11 +1863,22 @@ static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *mess case MSG_DEVICE_DEBUG: ret = ProcessAppSpawnDeviceDebugMsg(message); SendResponse(connection, msg, ret, 0); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); + break; + case MSG_UNINSTALL_DEBUG_HAP: + ProcessUninstallDebugHap(connection, message); + break; + case MSG_LOCK_STATUS: + ProcessAppSpawnLockStatusMsg(message); + SendResponse(connection, msg, 0, 0); + DeleteAppSpawnMsg(&message); + break; + case MSG_OBSERVE_PROCESS_SIGNAL_STATUS: + ProcessObserveProcessSignalMsg(connection, message); break; default: SendResponse(connection, msg, APPSPAWN_MSG_INVALID, 0); - DeleteAppSpawnMsg(message); + DeleteAppSpawnMsg(&message); break; } -} \ No newline at end of file +} diff --git a/standard/appspawn_service.h b/standard/appspawn_service.h index 4e91ba17f803dfc221907b18ca530694a434c772..76f4a8e6ce27543bdbe3f3e4c5d5a3f2d3922196 100644 --- a/standard/appspawn_service.h +++ b/standard/appspawn_service.h @@ -32,7 +32,11 @@ extern "C" { #endif -#ifdef APPSPAWN_TEST +#ifdef ASAN_DETECTOR +#define MAX_WAIT_MSG_COMPLETE (5 * 1000) // 5s +#define COLD_CHILD_RESPONSE_TIMEOUT 60 +#define WAIT_CHILD_RESPONSE_TIMEOUT 60 //60s +#elif APPSPAWN_TEST #define MAX_WAIT_MSG_COMPLETE (5 * 100) // 500ms #define COLD_CHILD_RESPONSE_TIMEOUT 5 #define WAIT_CHILD_RESPONSE_TIMEOUT 3 //3s diff --git a/test/BUILD.gn b/test/BUILD.gn index 25fcacb68d2e25953f1a4902b6f17b779bf31c96..faf729d9c56f1840fdcbd2fe15711d336a872169 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -27,6 +27,8 @@ group("unittest") { deps = [ "unittest/app_spawn_client_test:AppSpawn_client_ut" ] if (!use_libfuzzer) { deps += [ "unittest/app_spawn_standard_test:AppSpawn_ut" ] + deps += [ "unittest/app_spawn_standard_test:AppSpawn_common_ut" ] + deps += [ "unittest/app_spawn_standard_test:AppSpawn_coldrun_ut" ] } deps += [ "unittest/hnp_test:HnpTest" ] deps += [ "unittest/devicedebug_test:DevicedebugTest" ] diff --git a/test/appspawn_hap_test/AppScope/resources/base/element/string.json b/test/appspawn_hap_test/AppScope/resources/base/element/string.json deleted file mode 100644 index 62d29ea35c743c099c93bd7203d0922bc4308ae4..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/AppScope/resources/base/element/string.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "string": [ - { - "name": "app_name", - "value": "ArkTSComponents" - } - ] -} diff --git a/test/appspawn_hap_test/AppScope/resources/base/media/app_icon.png b/test/appspawn_hap_test/AppScope/resources/base/media/app_icon.png deleted file mode 100644 index ce307a8827bd75456441ceb57d530e4c8d45d36c..0000000000000000000000000000000000000000 Binary files a/test/appspawn_hap_test/AppScope/resources/base/media/app_icon.png and /dev/null differ diff --git a/test/appspawn_hap_test/LICENSE b/test/appspawn_hap_test/LICENSE deleted file mode 100644 index 338e5b0bc22082e0ffcc7121c2ed3897a3ddccb0..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/LICENSE +++ /dev/null @@ -1,78 +0,0 @@ - Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -Apache License, Version 2.0 -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. - -"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. - -2. Grant of Copyright License. - -Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. - -Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. - -You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: -1.You must give any other recipients of the Work or Derivative Works a copy of this License; and -2.You must cause any modified files to carry prominent notices stating that You changed the files; and -3.You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and -4.If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. - -You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. - -5. Submission of Contributions. - -Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. - -6. Trademarks. - -This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. - -Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. - -In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. - -While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/test/appspawn_hap_test/build-profile.json5 b/test/appspawn_hap_test/build-profile.json5 deleted file mode 100644 index dee0edaea15c26b3c9be05e9eb6be4875e56eb44..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/build-profile.json5 +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -{ - "app": { - "signingConfigs": [], - "compileSdkVersion": 9, - "compatibleSdkVersion": 9, - "products": [ - { - "name": "default", - "signingConfig": "default", - } - ] - }, - "modules": [ - { - "name": "entry", - "srcPath": "./entry", - "targets": [ - { - "name": "default", - "applyToProducts": [ - "default" - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/build-profile.json5 b/test/appspawn_hap_test/entry/build-profile.json5 deleted file mode 100644 index f17a2d379e39a373fe36ea3a103cd0a8ea73b342..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/build-profile.json5 +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -{ - "apiType": 'stageMode', - "buildOption": { - }, - "targets": [ - { - "name": "default", - "runtimeOS": "HarmonyOS" - }, - { - "name": "ohosTest", - } - ] -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/oh-package.json5 b/test/appspawn_hap_test/entry/oh-package.json5 deleted file mode 100644 index 72dc6b6790fa8999eca24f667fa6899300667982..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/oh-package.json5 +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -{ - "license": "", - "devDependencies": {}, - "author": "", - "name": "entry", - "description": "Please describe the basic information.", - "main": "", - "version": "1.0.0", - "dependencies": {} -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/ets/common/constants/CommonConstants.ets b/test/appspawn_hap_test/entry/src/main/ets/common/constants/CommonConstants.ets deleted file mode 100644 index 16f3fe9ccc9e4b9c98c9ef5229163d4555bbe4c4..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/ets/common/constants/CommonConstants.ets +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Common constants for all features. - */ -export default class CommonConstants { - /** - * Input length of the account. - */ - static readonly INPUT_ACCOUNT_LENGTH = 11; - - /** - * Input length of the password. - */ - static readonly INPUT_PASSWORD_LENGTH = 8; - - /** - * Left padding of the input box - */ - static readonly INPUT_PADDING_LEFT = 0; - - /** - * Delay time of simulated login - */ - static readonly LOGIN_DELAY_TIME = 2000; - - /** - * Common Spacing of Components - */ - static readonly COMMON_SPACE = 12; - - /** - * Title text of the home page - */ - static readonly HOME_TITLE = '首页'; - - /** - * Title text of the setting page - */ - static readonly MINE_TITLE = '我的'; - - /** - * Spacing of other login methods - */ - static readonly LOGIN_METHODS_SPACE = 44; - - /** - * The width or height of the component is spread across the parent component. - */ - static readonly FULL_PARENT = '100%'; - - /** - * The width of button - */ - static readonly BUTTON_WIDTH = '90%'; - - /** - * The width of setting list - */ - static readonly SET_LIST_WIDTH = '42%'; - - /** - * Home tab index - */ - static readonly HOME_TAB_INDEX = 0; - - /** - * Mine tab index - */ - static readonly MINE_TAB_INDEX = 1; -} - diff --git a/test/appspawn_hap_test/entry/src/main/ets/entryability/EntryAbility.ts b/test/appspawn_hap_test/entry/src/main/ets/entryability/EntryAbility.ts deleted file mode 100644 index 72ccbd8e15758ccdfb50c9809c44f36b4ec86cda..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/ets/entryability/EntryAbility.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import hilog from '@ohos.hilog'; -import Ability from '@ohos.app.ability.UIAbility'; -import Window from '@ohos.window'; - -/** - * Lift cycle management of Ability. - */ -export default class entryAbility extends Ability { - onCreate(want, launchParam) { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); - hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); - hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); - } - - onDestroy() { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); - } - - onWindowStageCreate(windowStage: Window.WindowStage) { - // Main window is created, set main page for this ability - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); - - windowStage.loadContent('pages/LoginPage', (err, data) => { - if (err.code) { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.ERROR); - hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); - return; - } - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); - }); - } - - onWindowStageDestroy() { - // Main window is destroyed, release UI related resources - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); - } - - onForeground() { - // Ability has brought to foreground - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); - } - - onBackground() { - // Ability has back to background - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); - } -} diff --git a/test/appspawn_hap_test/entry/src/main/ets/pages/LoginPage.ets b/test/appspawn_hap_test/entry/src/main/ets/pages/LoginPage.ets deleted file mode 100644 index cd674d332b364878d6bdf3ac9f1bf5dd8a2e3dda..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/ets/pages/LoginPage.ets +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import prompt from '@ohos.promptAction'; -import router from '@ohos.router'; -import CommonConstants from '../common/constants/CommonConstants'; - -@Extend(TextInput) -function inputStyle() { - .placeholderColor($r('app.color.placeholder_color')) - .height($r('app.float.login_input_height')) - .fontSize($r('app.float.big_text_size')) - .backgroundColor($r('app.color.background')) - .width(CommonConstants.FULL_PARENT) - .padding({ left: CommonConstants.INPUT_PADDING_LEFT }) - .margin({ top: $r('app.float.input_margin_top') }) -} - -@Extend(Line) -function lineStyle() { - .width(CommonConstants.FULL_PARENT) - .height($r('app.float.line_height')) - .backgroundColor($r('app.color.line_color')) -} - -@Extend(Text) -function blueTextStyle() { - .fontColor($r('app.color.login_blue_text_color')) - .fontSize($r('app.float.small_text_size')) - .fontWeight(FontWeight.Medium) -} - -/** - * Login page - */ -@Entry -@Component -struct LoginPage { - @State account: string = ''; - @State password: string = ''; - @State isShowProgress: boolean = false; - private timeOutId: number = -1; - - @Builder - imageButton(src: Resource) { - Button({ type: ButtonType.Circle, stateEffect: true }) { - Image(src) - } - .height($r('app.float.other_login_image_size')) - .width($r('app.float.other_login_image_size')) - .backgroundColor($r('app.color.background')) - } - - login(): void { - if (this.account === '' || this.password === '') { - prompt.showToast({ - message: $r('app.string.input_empty_tips') - }) - } else { - this.isShowProgress = true; - if (this.timeOutId === -1) { - this.timeOutId = setTimeout(() => { - this.isShowProgress = false; - this.timeOutId = -1; - router.replaceUrl({ url: 'pages/MainPage' }); - }, CommonConstants.LOGIN_DELAY_TIME); - } - } - } - - aboutToDisappear() { - clearTimeout(this.timeOutId); - this.timeOutId = -1; - } - - build() { - Column() { - Image($r('app.media.logo')) - .width($r('app.float.logo_image_size')) - .height($r('app.float.logo_image_size')) - .margin({ top: $r('app.float.logo_margin_top'), bottom: $r('app.float.logo_margin_bottom') }) - Text($r('app.string.login_page')) - .fontSize($r('app.float.page_title_text_size')) - .fontWeight(FontWeight.Medium) - .fontColor($r('app.color.title_text_color')) - Text($r('app.string.login_more')) - .fontSize($r('app.float.normal_text_size')) - .fontColor($r('app.color.login_more_text_color')) - .margin({ bottom: $r('app.float.login_more_margin_bottom'), top: $r('app.float.login_more_margin_top') }) - - TextInput({ placeholder: $r('app.string.account') }) - .maxLength(CommonConstants.INPUT_ACCOUNT_LENGTH) - .type(InputType.Number) - .inputStyle() - .onChange((value: string) => { - this.account = value; - }) - Line().lineStyle() - - TextInput({ placeholder: $r('app.string.password') }) - .maxLength(CommonConstants.INPUT_PASSWORD_LENGTH) - .type(InputType.Password) - .inputStyle() - .onChange((value: string) => { - this.password = value; - }) - Line().lineStyle() - - Row() { - Text($r('app.string.message_login')).blueTextStyle() - Text($r('app.string.forgot_password')).blueTextStyle() - } - .justifyContent(FlexAlign.SpaceBetween) - .width(CommonConstants.FULL_PARENT) - .margin({ top: $r('app.float.forgot_margin_top') }) - - Button($r('app.string.login'), { type: ButtonType.Capsule }) - .width(CommonConstants.BUTTON_WIDTH) - .height($r('app.float.login_button_height')) - .fontSize($r('app.float.normal_text_size')) - .fontWeight(FontWeight.Medium) - .backgroundColor($r('app.color.login_button_color')) - .margin({ top: $r('app.float.login_button_margin_top'), bottom: $r('app.float.login_button_margin_bottom') }) - .onClick(() => { - this.login(); - }) - Text($r('app.string.register_account')) - .fontColor($r('app.color.login_blue_text_color')) - .fontSize($r('app.float.normal_text_size')) - .fontWeight(FontWeight.Medium) - - if (this.isShowProgress) { - LoadingProgress() - .color($r('app.color.loading_color')) - .width($r('app.float.login_progress_size')) - .height($r('app.float.login_progress_size')) - .margin({ top: $r('app.float.login_progress_margin_top') }) - } - - Blank() - Text($r('app.string.other_login_method')) - .fontColor($r('app.color.other_login_text_color')) - .fontSize($r('app.float.little_text_size')) - .fontWeight(FontWeight.Medium) - .margin({ top: $r('app.float.other_login_margin_top'), bottom: $r('app.float.other_login_margin_bottom') }) - Row({ space: CommonConstants.LOGIN_METHODS_SPACE }) { - this.imageButton($r('app.media.login_method1')) - this.imageButton($r('app.media.login_method2')) - this.imageButton($r('app.media.login_method3')) - } - } - .backgroundColor($r('app.color.background')) - .height(CommonConstants.FULL_PARENT) - .width(CommonConstants.FULL_PARENT) - .padding({ - left: $r('app.float.page_padding_hor'), - right: $r('app.float.page_padding_hor'), - bottom: $r('app.float.login_page_padding_bottom') - }) - } -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/ets/pages/MainPage.ets b/test/appspawn_hap_test/entry/src/main/ets/pages/MainPage.ets deleted file mode 100644 index 128cd80cd120e502d01be10279fca56609567451..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/ets/pages/MainPage.ets +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import CommonConstants from '../common/constants/CommonConstants'; -import Home from "../view/Home" -import Setting from "../view/Setting" - -/** - * Main page - */ -@Entry -@Component -struct MainPage { - @State currentIndex: number = CommonConstants.HOME_TAB_INDEX; - private tabsController: TabsController = new TabsController(); - - @Builder TabBuilder(title: string, index: number, selectedImg: Resource, normalImg: Resource) { - Column() { - Image(this.currentIndex === index ? selectedImg : normalImg) - .width($r('app.float.mainPage_baseTab_size')) - .height($r('app.float.mainPage_baseTab_size')) - Text(title) - .margin({ top: $r('app.float.mainPage_baseTab_top') }) - .fontSize($r('app.float.main_tab_fontSize')) - .fontColor(this.currentIndex === index ? $r('app.color.mainPage_selected') : $r('app.color.mainPage_normal')) - } - .justifyContent(FlexAlign.Center) - .height($r('app.float.mainPage_barHeight')) - .width(CommonConstants.FULL_PARENT) - .onClick(() => { - this.currentIndex = index; - this.tabsController.changeIndex(this.currentIndex); - }) - } - - build() { - Tabs({ - barPosition: BarPosition.End, - controller: this.tabsController - }) { - TabContent() { - Home() - } - .padding({ left: $r('app.float.mainPage_padding'), right: $r('app.float.mainPage_padding') }) - .backgroundColor($r('app.color.mainPage_backgroundColor')) - .tabBar(this.TabBuilder(CommonConstants.HOME_TITLE, CommonConstants.HOME_TAB_INDEX, - $r('app.media.home_selected'), $r('app.media.home_normal'))) - - TabContent() { - Setting() - } - .padding({ left: $r('app.float.mainPage_padding'), right: $r('app.float.mainPage_padding') }) - .backgroundColor($r('app.color.mainPage_backgroundColor')) - .tabBar(this.TabBuilder(CommonConstants.MINE_TITLE, CommonConstants.MINE_TAB_INDEX, - $r('app.media.mine_selected'), $r('app.media.mine_normal'))) - } - .width(CommonConstants.FULL_PARENT) - .backgroundColor(Color.White) - .barHeight($r('app.float.mainPage_barHeight')) - .barMode(BarMode.Fixed) - .onChange((index: number) => { - this.currentIndex = index; - }) - } -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/ets/viewmodel/ItemData.ets b/test/appspawn_hap_test/entry/src/main/ets/viewmodel/ItemData.ets deleted file mode 100644 index b1580cc28a731a61eb670e80d0c63544973fec5a..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/ets/viewmodel/ItemData.ets +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * List item data entity. - */ -export default class PageResource { - /** - * Text of list item. - */ - title: Resource; - /** - * Image of list item. - */ - img: Resource; - /** - * Other resource of list item. - */ - others?: Resource; - - constructor(title: Resource, img: Resource, others?: Resource) { - this.title = title; - this.img = img; - this.others = others; - } -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/ets/viewmodel/MainViewModel.ets b/test/appspawn_hap_test/entry/src/main/ets/viewmodel/MainViewModel.ets deleted file mode 100644 index 491deb019779d9deac5a78111a8e694c4b594055..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/ets/viewmodel/MainViewModel.ets +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import ItemData from './ItemData'; - -/** - * Binds data to components and provides interfaces. - */ -export class MainViewModel { - - /** - * Get swiper image data. - * - * @return {Array} swiperImages. - */ - getSwiperImages(): Array { - let swiperImages: Resource[] = [ - $r('app.media.fig1'), - $r('app.media.fig2'), - $r('app.media.fig3'), - $r('app.media.fig4') - ]; - return swiperImages; - } - - /** - * Get data of the first grid. - * - * @return {Array} firstGridData. - */ - getFirstGridData(): Array { - let firstGridData: ItemData[] = [ - new ItemData($r('app.string.my_love'), $r('app.media.love')), - new ItemData($r('app.string.history_record'), $r('app.media.record')), - new ItemData($r('app.string.message'), $r('app.media.message')), - new ItemData($r('app.string.shopping_cart'), $r('app.media.shopping')), - new ItemData($r('app.string.my_goal'), $r('app.media.target')), - new ItemData($r('app.string.group'), $r('app.media.circle')), - new ItemData($r('app.string.favorites'), $r('app.media.favorite')), - new ItemData($r('app.string.recycle_bin'), $r('app.media.recycle')) - ]; - return firstGridData; - } - - - /** - * Get data of the second grid. - * - * @return {Array} secondGridData. - */ - getSecondGridData(): Array { - let secondGridData: ItemData[] = [ - new ItemData($r('app.string.mainPage_top'), $r('app.media.top'), $r('app.string.mainPage_text_top')), - new ItemData($r('app.string.mainPage_new'), $r('app.media.new'), $r('app.string.mainPage_text_new')), - new ItemData($r('app.string.mainPage_brand'), $r('app.media.brand'), $r('app.string.mainPage_text_brand')), - new ItemData($r('app.string.mainPage_found'), $r('app.media.found'), $r('app.string.mainPage_text_found')) - ]; - return secondGridData; - } - - - /** - * Get data of the setting list. - * - * @return {Array} settingListData. - */ - getSettingListData(): Array { - let settingListData: ItemData[] = [ - new ItemData($r('app.string.setting_list_news'), $r('app.media.news'), $r("app.string.setting_toggle")), - new ItemData($r('app.string.setting_list_data'), $r('app.media.data')), - new ItemData($r('app.string.setting_list_menu'), $r('app.media.menu')), - new ItemData($r('app.string.setting_list_about'), $r('app.media.about')), - new ItemData($r('app.string.setting_list_storage'), $r('app.media.storage')), - new ItemData($r('app.string.setting_list_privacy'), $r('app.media.privacy')) - ]; - return settingListData; - } -} - -export default new MainViewModel(); \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/module.json5 b/test/appspawn_hap_test/entry/src/main/module.json5 deleted file mode 100644 index 8046ec1921e25a173d951bae53df64898a5c7edc..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/module.json5 +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -{ - "module": { - "name": "entry", - "type": "entry", - "description": "$string:module_desc", - "mainElement": "EntryAbility", - "deviceTypes": [ - "phone" - ], - "deliveryWithInstall": true, - "installationFree": false, - "pages": "$profile:main_pages", - "abilities": [ - { - "name": "EntryAbility", - "srcEntry": "./ets/entryability/EntryAbility.ts", - "description": "$string:EntryAbility_desc", - "icon": "$media:icon", - "label": "$string:EntryAbility_label", - "startWindowIcon": "$media:icon", - "startWindowBackground": "$color:start_window_background", - "exported": true, - "skills": [ - { - "entities": [ - "entity.system.home" - ], - "actions": [ - "action.system.home" - ] - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/resources/base/element/color.json b/test/appspawn_hap_test/entry/src/main/resources/base/element/color.json deleted file mode 100644 index 145c2ba2aff9e2894940aa4fef34091891ade20b..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/resources/base/element/color.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "color": [ - { - "name": "start_window_background", - "value": "#FFFFFF" - }, - { - "name": "white", - "value": "#FFFFFF" - }, - { - "name": "background", - "value": "#F1F3F5" - }, - { - "name": "title_text_color", - "value": "#182431" - }, - { - "name": "login_more_text_color", - "value": "#99182431" - }, - { - "name": "placeholder_color", - "value": "#99182431" - }, - { - "name": "line_color", - "value": "#33182431" - }, - { - "name": "login_button_color", - "value": "#007DFF" - }, - { - "name": "login_blue_text_color", - "value": "#007DFF" - }, - { - "name": "other_login_text_color", - "value": "#838D97" - }, - { - "name": "loading_color", - "value": "#182431" - }, - { - "name": "mainPage_selected", - "value": "#1698CE" - }, - { - "name": "mainPage_normal", - "value": "#6B6B6B" - }, - { - "name": "mainPage_backgroundColor", - "value": "#F1F3F5" - }, - { - "name": "home_grid_fontColor", - "value": "#99182431" - }, - { - "name": "setting_button_backgroundColor", - "value": "#E5E8EA" - }, - { - "name": "setting_button_fontColor", - "value": "#FA2A2D" - } - ] -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/resources/base/element/float.json b/test/appspawn_hap_test/entry/src/main/resources/base/element/float.json deleted file mode 100644 index c39c6a637d17f954da11cde2325b343eea3a144c..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/resources/base/element/float.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "float": [ - { - "name": "logo_image_size", - "value": "78vp" - }, - { - "name": "logo_margin_top", - "value": "100vp" - }, - { - "name": "logo_margin_bottom", - "value": "8vp" - }, - { - "name": "page_title_text_size", - "value": "24fp" - }, - { - "name": "normal_text_size", - "value": "16fp" - }, - { - "name": "big_text_size", - "value": "18fp" - }, - { - "name": "small_text_size", - "value": "14fp" - }, - { - "name": "little_text_size", - "value": "12fp" - }, - { - "name": "login_more_margin_bottom", - "value": "30vp" - }, - { - "name": "login_more_margin_top", - "value": "8vp" - }, - { - "name": "login_input_height", - "value": "45vp" - }, - { - "name": "forgot_margin_top", - "value": "8vp" - }, - { - "name": "input_margin_top", - "value": "12vp" - }, - { - "name": "line_height", - "value": "1vp" - }, - { - "name": "login_button_height", - "value": "40vp" - }, - { - "name": "login_button_margin_top", - "value": "87vp" - }, - { - "name": "login_button_margin_bottom", - "value": "12vp" - }, - { - "name": "vertical_line_margin", - "value": "15vp" - }, - { - "name": "login_progress_size", - "value": "30vp" - }, - { - "name": "login_progress_margin_top", - "value": "20vp" - }, - { - "name": "other_login_margin_top", - "value": "50vp" - } - ] -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/resources/base/element/string.json b/test/appspawn_hap_test/entry/src/main/resources/base/element/string.json deleted file mode 100644 index 33a721370347360af94a04c47d11a59284978d06..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/resources/base/element/string.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "string": [ - { - "name": "module_desc", - "value": "description" - }, - { - "name": "EntryAbility_desc", - "value": "description" - }, - { - "name": "EntryAbility_label", - "value": "ArkTSComponents" - }, - { - "name": "login_page", - "value": "Login page" - }, - { - "name": "login_more", - "value": "Log in to your account to use more services" - }, - { - "name": "account", - "value": "Account" - }, - { - "name": "password", - "value": "Password" - }, - { - "name": "login", - "value": "Log in" - }, - { - "name": "register_account", - "value": "Registering an Account" - }, - { - "name": "forgot_password", - "value": "Forgot Password" - }, - { - "name": "message_login", - "value": "SMS verification code login" - }, - { - "name": "other_login_method", - "value": "Other login methods" - }, - { - "name": "vertical_line", - "value": " | " - }, - { - "name": "input_empty_tips", - "value": "The input cannot be empty." - }, - { - "name": "login_success", - "value": "The login is successful." - }, - { - "name": "my_love", - "value": "My favorite" - }, - { - "name": "history_record", - "value": "History" - }, - { - "name": "message", - "value": "Message" - }, - { - "name": "shopping_cart", - "value": "Shopping cart" - }, - { - "name": "my_goal", - "value": "My goal" - } - ] -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/resources/base/profile/main_pages.json b/test/appspawn_hap_test/entry/src/main/resources/base/profile/main_pages.json deleted file mode 100644 index 39b6bfffe2fe1324f7bd6cf384556da26aa0c40a..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/resources/base/profile/main_pages.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "src": [ - "pages/LoginPage", - "pages/MainPage" - ] -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/resources/en_US/element/string.json b/test/appspawn_hap_test/entry/src/main/resources/en_US/element/string.json deleted file mode 100644 index b21fa8582a947fa1b776d4ba4089f731cc2d7482..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/resources/en_US/element/string.json +++ /dev/null @@ -1,224 +0,0 @@ -{ - "string": [ - { - "name": "module_desc", - "value": "description" - }, - { - "name": "EntryAbility_desc", - "value": "description" - }, - { - "name": "EntryAbility_label", - "value": "ArkTSComponents" - }, - { - "name": "login_page", - "value": "Login page" - }, - { - "name": "login_more", - "value": "Log in to your account to use more services" - }, - { - "name": "account", - "value": "Account" - }, - { - "name": "password", - "value": "Password" - }, - { - "name": "login", - "value": "Log in" - }, - { - "name": "register_account", - "value": "Registering an Account" - }, - { - "name": "forgot_password", - "value": "Forgot Password" - }, - { - "name": "message_login", - "value": "SMS verification code login" - }, - { - "name": "other_login_method", - "value": "Other login methods" - }, - { - "name": "vertical_line", - "value": " | " - }, - { - "name": "input_empty_tips", - "value": "The input cannot be empty." - }, - { - "name": "login_success", - "value": "The login is successful." - }, - { - "name": "my_love", - "value": "My favorite" - }, - { - "name": "history_record", - "value": "History" - }, - { - "name": "message", - "value": "Message" - }, - { - "name": "shopping_cart", - "value": "Shopping cart" - }, - { - "name": "my_goal", - "value": "My goal" - }, - { - "name": "group", - "value": "Group" - }, - { - "name": "favorites", - "value": "Favorites" - }, - { - "name": "recycle_bin", - "value": "Recycle Bin" - }, - { - "name": "rankings", - "value": "Rankings" - }, - { - "name": "new_product_debut", - "value": "New product debut" - }, - { - "name": "big_name_flash", - "value": "Big name flash" - }, - { - "name": "find_good", - "value": "Find good things" - }, - { - "name": "xiamen_station", - "value": "Xiamen Station, we'll see you." - }, - { - "name": "more_big_names", - "value": "More Big Names" - }, - { - "name": "push_notifications", - "value": "Push Notifications" - }, - { - "name": "data_management", - "value": "Data Management" - }, - { - "name": "menu_settings", - "value": "Menu Settings" - }, - { - "name": "about", - "value": "About" - }, - { - "name": "clear_cache", - "value": "Clear Cache" - }, - { - "name": "mainPage_tabTitles_home", - "value": "Home" - }, - { - "name": "mainPage_tabTitles_mine", - "value": "Mine" - }, - { - "name": "mainPage_top", - "value": "Rankings" - }, - { - "name": "mainPage_text_top", - "value": "Xiamen Station, we'll see you." - }, - { - "name": "mainPage_new", - "value": "New product debut" - }, - { - "name": "mainPage_text_new", - "value": "Xiamen Station, we'll see you." - }, - { - "name": "mainPage_brand", - "value": "Big name flash" - }, - { - "name": "mainPage_text_brand", - "value": "More Big Names" - }, - { - "name": "mainPage_found", - "value": "Find good things" - }, - { - "name": "mainPage_text_found", - "value": "Xiamen Station, we'll see you." - }, - { - "name": "setting_account_name", - "value": "Mr. Lee" - }, - { - "name": "setting_account_email", - "value": "2000000@shenhua.cc" - }, - { - "name": "setting_list_news", - "value": "Push Notifications" - }, - { - "name": "setting_list_data", - "value": "Data Management" - }, - { - "name": "setting_list_menu", - "value": "Menu Settings" - }, - { - "name": "setting_list_about", - "value": "Clear Cache" - }, - { - "name": "setting_list_storage", - "value": "清除缓存" - }, - { - "name": "setting_list_privacy", - "value": "Privacy Agreement" - }, - { - "name": "setting_button", - "value": "Logout" - }, - { - "name": "home_list", - "value": "List" - }, - { - "name": "setting_toggle", - "value": "switch" - } - ] -} \ No newline at end of file diff --git a/test/appspawn_hap_test/entry/src/main/resources/zh_CN/element/string.json b/test/appspawn_hap_test/entry/src/main/resources/zh_CN/element/string.json deleted file mode 100644 index bae69c0800855c4e13b8842c0cd3baebcced265d..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/entry/src/main/resources/zh_CN/element/string.json +++ /dev/null @@ -1,224 +0,0 @@ -{ - "string": [ - { - "name": "module_desc", - "value": "description" - }, - { - "name": "EntryAbility_desc", - "value": "description" - }, - { - "name": "EntryAbility_label", - "value": "ArkTSComponents" - }, - { - "name": "login_page", - "value": "登录界面" - }, - { - "name": "login_more", - "value": "登录帐号以使用更多服务" - }, - { - "name": "account", - "value": "帐号" - }, - { - "name": "password", - "value": "密码" - }, - { - "name": "login", - "value": "登录" - }, - { - "name": "register_account", - "value": "注册帐号" - }, - { - "name": "forgot_password", - "value": "忘记密码" - }, - { - "name": "message_login", - "value": "短信验证码登录" - }, - { - "name": "other_login_method", - "value": "其他登录方式" - }, - { - "name": "vertical_line", - "value": " | " - }, - { - "name": "input_empty_tips", - "value": "输入不能为空" - }, - { - "name": "login_success", - "value": "登录成功" - }, - { - "name": "my_love", - "value": "我的最爱" - }, - { - "name": "history_record", - "value": "历史记录" - }, - { - "name": "message", - "value": "消息" - }, - { - "name": "shopping_cart", - "value": "购物车" - }, - { - "name": "my_goal", - "value": "我的目标" - }, - { - "name": "group", - "value": "圈子" - }, - { - "name": "favorites", - "value": "收藏" - }, - { - "name": "recycle_bin", - "value": "回收站" - }, - { - "name": "rankings", - "value": "排行榜" - }, - { - "name": "new_product_debut", - "value": "新品首发" - }, - { - "name": "big_name_flash", - "value": "大牌闪购" - }, - { - "name": "find_good", - "value": "发现好物" - }, - { - "name": "xiamen_station", - "value": "厦门站,我们不见不散" - }, - { - "name": "more_big_names", - "value": "更多大牌" - }, - { - "name": "push_notifications", - "value": "推送通知" - }, - { - "name": "data_management", - "value": "数据管理" - }, - { - "name": "menu_settings", - "value": "菜单设置" - }, - { - "name": "about", - "value": "关于" - }, - { - "name": "clear_cache", - "value": "清除缓存" - }, - { - "name": "mainPage_tabTitles_home", - "value": "首页" - }, - { - "name": "mainPage_tabTitles_mine", - "value": "我的" - }, - { - "name": "mainPage_top", - "value": "排行榜" - }, - { - "name": "mainPage_text_top", - "value": "厦门站,我们不见不散" - }, - { - "name": "mainPage_new", - "value": "新品首发" - }, - { - "name": "mainPage_text_new", - "value": "厦门站,我们不见不散" - }, - { - "name": "mainPage_brand", - "value": "大牌闪购" - }, - { - "name": "mainPage_text_brand", - "value": "更多大牌" - }, - { - "name": "mainPage_found", - "value": "发现好物" - }, - { - "name": "mainPage_text_found", - "value": "厦门站,我们不见不散" - }, - { - "name": "setting_account_name", - "value": "李先生" - }, - { - "name": "setting_account_email", - "value": "2000000@shenhua.cc" - }, - { - "name": "setting_list_news", - "value": "推送通知" - }, - { - "name": "setting_list_data", - "value": "数据管理" - }, - { - "name": "setting_list_menu", - "value": "菜单设置" - }, - { - "name": "setting_list_about", - "value": "关于" - }, - { - "name": "setting_list_storage", - "value": "清除缓存" - }, - { - "name": "setting_list_privacy", - "value": "隐私协议" - }, - { - "name": "setting_button", - "value": "退出登录" - }, - { - "name": "home_list", - "value": "列表" - }, - { - "name": "setting_toggle", - "value": "开关" - } - ] -} \ No newline at end of file diff --git a/test/appspawn_hap_test/hvigor/hvigor-config.json5 b/test/appspawn_hap_test/hvigor/hvigor-config.json5 deleted file mode 100644 index acf887c285e4812e8fa4dd03a89e2105e9f7d900..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/hvigor/hvigor-config.json5 +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -{ - "hvigorVersion": "2.0.0", - "dependencies": { - "@ohos/hvigor-ohos-plugin": "2.0.0" - } -} diff --git a/test/appspawn_hap_test/oh-package.json5 b/test/appspawn_hap_test/oh-package.json5 deleted file mode 100644 index ee07c28adca5ed1a34fa3ab696f784b2a04bca3f..0000000000000000000000000000000000000000 --- a/test/appspawn_hap_test/oh-package.json5 +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -{ - "license": "", - "devDependencies": { - "@ohos/hypium": "1.0.6" - }, - "author": "", - "name": "arktscomponents", - "description": "Please describe the basic information.", - "main": "", - "version": "1.0.0", - "dependencies": {} -} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0100.json b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0100.json new file mode 100644 index 0000000000000000000000000000000000000000..260d6b731f6f7e5bfa4aef37acbd23837fe83beb --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0100.json @@ -0,0 +1,13 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": ["sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0100.py"] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0100.py b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0100.py new file mode 100644 index 0000000000000000000000000000000000000000..02b7cf070c974570576614ccd6c439c17382817f --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0100.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import time +from devicetest.core.test_case import TestCase, Step, CheckPoint +from hypium import UiDriver +from hypium.action.os_hypium.device_logger import DeviceLogger +from hypium.model import UiParam, WindowFilter + + +class SubStartupAppspawnAppclone0100(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + self.driver = UiDriver(self.device1) + Step("预置工作:唤醒屏幕.................") + self.driver.enable_auto_wakeup(self.device1) + Step("预置工作:滑动解锁.................") + self.driver.swipe(UiParam.UP, side=UiParam.BOTTOM) + Step('设置屏幕常亮') + self.driver.Screen.enable_stay_awake() + + def test_step1(self): + Step("步骤1:安装测试hap包") + ishap = self.driver.has_app("com.ohos.mytest") + if(ishap): + self.driver.uninstall_app("com.ohos.mytest") + path = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) + hap = os.path.abspath( + os.path.join(os.path.join(path, "testFile"), + 'sub_startup_appspawn_appclone/entry-signed-release.hap')) + self.driver.install_app(hap) + Step("步骤2:打开测试应用") + self.driver.start_app("com.ohos.mytest", "EntryAbility") + time.sleep(2) + self.driver.check_window_exist(WindowFilter().bundle_name("com.ohos.mytest")) + Step("步骤3:点击安装克隆应用") + self.driver.touch(BY.text("安装克隆应用")) + self.driver.touch(BY.text("startAbilityByAppIndex")) + Step("步骤4:分身应用的源目录新建123.txt") + self.driver.shell("touch ../data/app/el2/100/database/+clone-1+com.ohos.mytest/123.txt") + Step("步骤5:分身应用沙盒路径是否存在123.txt") + cpid = self.driver.System.get_pid("com.ohos.mytest1") + result1 = self.driver.shell("ls ../proc/%d/root/data/storage/el2/database" % cpid) + Step("步骤6:预期结果校验") + self.driver.Assert.contains(result1, "123.txt") + Step("步骤7:主应用沙盒路径是否存在123.txt") + pid = self.driver.System.get_pid("com.ohos.mytest") + result2 = self.driver.shell("ls ../proc/%d/root/data/storage/el2/database" % pid) + Step("步骤6:预期结果校验") + if ("123.txt" in result2): + raise AssertionError() + else: + pass + + def teardown(self): + Step("收尾工作:删除hap") + self.driver.uninstall_app("com.ohos.mytest") diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0200.json b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0200.json new file mode 100644 index 0000000000000000000000000000000000000000..91d041bf6ad1c8658a8391694a85c24c489f49b3 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0200.json @@ -0,0 +1,13 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": ["sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0200.py"] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0200.py b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0200.py new file mode 100644 index 0000000000000000000000000000000000000000..9b3d61fab32f82bfbd7e4b4cef560225b7300ab6 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0200.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import time +from devicetest.core.test_case import TestCase, Step, CheckPoint +from hypium import UiDriver +from hypium.action.os_hypium.device_logger import DeviceLogger +from hypium.model import UiParam, WindowFilter + + +class SubStartupAppspawnAppclone0200(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + self.driver = UiDriver(self.device1) + Step("预置工作:唤醒屏幕.................") + self.driver.enable_auto_wakeup(self.device1) + Step("预置工作:滑动解锁.................") + self.driver.swipe(UiParam.UP, side=UiParam.BOTTOM) + Step('设置屏幕常亮') + self.driver.Screen.enable_stay_awake() + + def test_step1(self): + Step("步骤1:安装测试hap包") + ishap = self.driver.has_app("com.ohos.mytest") + if(ishap): + self.driver.uninstall_app("com.ohos.mytest") + path = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) + hap = os.path.abspath( + os.path.join(os.path.join(path, "testFile"), + 'sub_startup_appspawn_appclone/entry-signed-release.hap')) + self.driver.install_app(hap) + Step("步骤2:打开测试应用") + self.driver.start_app("com.ohos.mytest", "EntryAbility") + time.sleep(2) + self.driver.check_window_exist(WindowFilter().bundle_name("com.ohos.mytest")) + Step("步骤3:点击安装克隆应用") + self.driver.touch(BY.text("安装克隆应用")) + self.driver.touch(BY.text("startAbilityByAppIndex")) + Step("步骤4:分身应用的源目录新建123.txt") + self.driver.shell("touch ../data/app/el2/100/database/com.ohos.mytest/abc.txt") + Step("步骤5:主应用沙盒路径是否存在abc.txt") + cpid = self.driver.System.get_pid("com.ohos.mytest") + result1 = self.driver.shell("ls ../proc/%d/root/data/storage/el2/database" % cpid) + Step("步骤6:预期结果校验") + self.driver.Assert.contains(result1, "abc.txt") + Step("步骤7:分身应用沙盒路径是否存在abc.txt") + pid = self.driver.System.get_pid("com.ohos.mytest1") + result2 = self.driver.shell("ls ../proc/%d/root/data/storage/el2/database" % pid) + Step("步骤6:预期结果校验") + if ("abc.txt" in result2): + raise AssertionError() + else: + pass + + def teardown(self): + Step("收尾工作:删除hap") + self.driver.uninstall_app("com.ohos.mytest") diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0300.json b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0300.json new file mode 100644 index 0000000000000000000000000000000000000000..845ff596920e16cb1f4925a4f2822f701675787a --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0300.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0300.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0300.py b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0300.py new file mode 100644 index 0000000000000000000000000000000000000000..50104a8d852dbbe35f494f21a5e011ae636b3a83 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0300.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from hypium.model import UiParam +from hypium.action.os_hypium.device_logger import DeviceLogger +from aw import Common + + +class SubStartupAppspawnAppclone0300(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def build_shell_command(i, path, bundle_name, j): + if bundle_name == "com.example.intaketest": + result01 = self.driver.shell("ls ../data/app/el%d/100/%s/%s" % (i, path, bundle_name)) + elif bundle_name == "com.example.intaketest%d" % j: + result01 = self.driver.shell("ls ../data/app/el%d/100/%s/+clone-%d+com.example.intaketest" + % (i, path, j)) + return None + + def process(self): + Step("安装测试hap并打开") + pid_bundlename_dict = {} + bundle_name = "com.example.intaketest" + hap_path = Common.sourcepath('intaketest.hap', "sub_startup_appspawn_appclone") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.clear_app_data(bundle_name) + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + pid = self.driver.System.get_pid(bundle_name) + pid_bundlename_dict.update({bundle_name: pid}) + + self.driver.AppManager.stop_app("com.example.settings") + self.driver.AppManager.start_app("com.example.settings") + self.driver.swipe(UiParam.UP) + for text in ["系统", "应用分身", "IntakeTest"]: + self.driver.touch(BY.text(text)) + for i in range(5): + self.driver.touch(BY.text("创建分身")) + time.sleep(1) + self.driver.AppManager.stop_app("com.example.settings") + + for i in range(1, 7): + self.driver.AppManager.start_app(bundle_name) + if i == 1: + self.driver.touch(BY.text("IntakeTest")) + pid = self.driver.System.get_pid(bundle_name) + pid_bundlename_dict.update({bundle_name: pid}) + else: + self.driver.touch(BY.text("更多打开方式")) + self.driver.touch(BY.text("IntakeTest%d" % (i - 1))) + pid = self.driver.System.get_pid("%s%d" % (bundle_name, i - 1)) + pid_bundlename_dict.update({"%s%d" % (bundle_name, i - 1) : pid}) + self.driver.go_home() + + for i in range(1, 5): + for j in range(1, 6): + for bundle_name, pid in pid_bundlename_dict.items(): + result01 = build_shell_command(i, "base", bundle_name, j) + result02 = self.driver.shell("ls ../proc/%d/root/data/storage/el%d/%s" % (pid, i, "base")) + self.driver.Assert.equal(result01, result02) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.uninstall_app("com.example.intaketest") diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0400.json b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0400.json new file mode 100644 index 0000000000000000000000000000000000000000..a3e3431afdde3818bb49308ccdf26ab9b9864c66 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0400.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0400.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0400.py b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0400.py new file mode 100644 index 0000000000000000000000000000000000000000..ab2bc2f3d3baf0915f18e183e095e0e7e8a1d66b --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0400.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from hypium.model import UiParam +from hypium.action.os_hypium.device_logger import DeviceLogger +from aw import Common + + +class SubStartupAppspawnAppclone0400(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + Step("安装测试hap并打开") + bundle_name = "com.example.intaketest" + hap_path = Common.sourcepath('intaketest.hap', "sub_startup_appspawn_appclone") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.clear_app_data(bundle_name) + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + + self.driver.AppManager.stop_app("com.example.settings") + self.driver.AppManager.start_app("com.example.settings") + self.driver.swipe(UiParam.UP) + for text in ["系统", "应用分身", "IntakeTest"]: + self.driver.touch(BY.text(text)) + for i in range(5): + self.driver.touch(BY.text("创建分身")) + time.sleep(1) + self.driver.AppManager.stop_app("com.example.settings") + + for i in range(1, 7): + self.driver.AppManager.start_app(bundle_name) + if i == 1: + self.driver.touch(BY.text("IntakeTest")) + else: + self.driver.touch(BY.text("更多打开方式")) + self.driver.touch(BY.text("IntakeTest%d" % (i - 1))) + self.driver.go_home() + + self.driver.shell("touch ../data/app/el2/100/base/%s/test.txt" % bundle_name) + has_file01 = self.driver.Storage.has_file("/data/app/el2/100/base/%s/test.txt" % bundle_name) + self.driver.Assert.equal(has_file01, True) + for i in range(1, 6): + has_file02 = self.driver.Storage.has_file("/data/app/el2/100/base/+clone-%d+%s/test.txt" % (i, bundle_name)) + self.driver.Assert.equal(has_file02, False) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.uninstall_app(bundle_name) diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0600.json b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0600.json new file mode 100644 index 0000000000000000000000000000000000000000..ce0e0df9a02c1d4e8b364a8912598224412ea61d --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0600.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0600.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0600.py b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0600.py new file mode 100644 index 0000000000000000000000000000000000000000..86b739a518c43a614b217e979a0736ca14fbe137 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0600.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import random +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from hypium.model import UiParam +from hypium.action.os_hypium.device_logger import DeviceLogger +from aw import Common + + +class SubStartupAppspawnAppclone0600(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + Step("安装测试hap并打开") + bundle_name = "com.example.intaketest" + hap_path = Common.sourcepath('intaketest.hap', "sub_startup_appspawn_appclone") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.clear_app_data(bundle_name) + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + + self.driver.AppManager.stop_app("com.example.settings") + self.driver.AppManager.start_app("com.example.settings") + self.driver.swipe(UiParam.UP) + for text in ["系统", "应用分身", "IntakeTest"]: + self.driver.touch(BY.text(text)) + for i in range(5): + self.driver.touch(BY.text("创建分身")) + time.sleep(1) + + self.driver.check_component_exist(BY.text("最多可以创建 5 个分身"), expect_exist=True) + + comps01 = self.driver.find_all_components(BY.type("Button")) + self.driver.touch(comps01[random.randint(0, len(comps01) - 1)]) + comps02 = self.driver.find_all_components(BY.type("Button")) + self.driver.touch(comps02[-1]) + self.driver.check_component_exist(BY.text("最多可以创建 5 个分身"), expect_exist=False) + self.driver.touch(BY.text("创建分身")) + self.driver.check_component_exist(BY.text("最多可以创建 5 个分身"), expect_exist=True) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.stop_app("com.example.settings") + self.driver.AppManager.uninstall_app(bundle_name) diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0700.json b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0700.json new file mode 100644 index 0000000000000000000000000000000000000000..a5ad1a2e2e84fc81ea5522b877b1b5e55f8a8caf --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0700.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0700.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0700.py b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0700.py new file mode 100644 index 0000000000000000000000000000000000000000..80968a3fef02d9d9ac389ea368a5f51f7c93a082 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0700.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from hypium.model import UiParam +from hypium.action.os_hypium.device_logger import DeviceLogger +from aw import Common + + +class SubStartupAppspawnAppclone0700(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + Step("安装测试hap并打开") + bundle_name = "com.example.intaketest" + hap_path = Common.sourcepath('intaketest.hap', "sub_startup_appspawn_appclone") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.clear_app_data(bundle_name) + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + + self.driver.AppManager.stop_app("com.example.settings") + self.driver.AppManager.start_app("com.example.settings") + self.driver.swipe(UiParam.UP) + for text in ["系统", "应用分身", "IntakeTest"]: + self.driver.touch(BY.text(text)) + for i in range(5): + self.driver.touch(BY.text("创建分身")) + time.sleep(1) + self.driver.AppManager.stop_app("com.example.settings") + + for i in range(1, 7): + self.driver.AppManager.start_app(bundle_name) + if i == 1: + self.driver.touch(BY.text("IntakeTest")) + else: + self.driver.touch(BY.text("更多打开方式")) + self.driver.touch(BY.text("IntakeTest%d" % (i - 1))) + + for i in range(1, 5): + for j in range(1, 6): + for path in ["base", "database"]: + has_dir = self.driver.Storage.has_dir("/data/app/el%d/100/%s/+clone-%d+%s" + % (i, path, j, bundle_name)) + self.driver.Assert.equal(has_dir, True) + + self.driver.AppManager.stop_app("com.example.settings") + self.driver.AppManager.start_app("com.example.settings") + self.driver.swipe(UiParam.UP) + for text in ["系统", "应用分身", "IntakeTest"]: + self.driver.touch(BY.text(text)) + comps01 = self.driver.find_all_components(BY.type("Button")) + self.driver.touch(comps01[0]) + comps02 = self.driver.find_all_components(BY.type("Button")) + self.driver.touch(comps02[-1]) + for i in range(1, 5): + for path in ["base", "database"]: + has_dir = self.driver.Storage.has_dir("/data/app/el%d/100/%s/+clone-1+%s" % (i, path, bundle_name)) + self.driver.Assert.equal(has_dir, False) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.stop_app("com.example.settings") + self.driver.AppManager.uninstall_app(bundle_name) diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0900.json b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0900.json new file mode 100644 index 0000000000000000000000000000000000000000..e029c9d716f6ec25a3b9b9a8b949694bfdb99b84 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0900.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0900.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0900.py b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0900.py new file mode 100644 index 0000000000000000000000000000000000000000..5323640900e512dfa4740d8156aec2bd0bd257fb --- /dev/null +++ b/test/autotest/sub_startup_appspawn_appclone/sub_startup_appspawn_appclone_0900.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from hypium.model import UiParam +from hypium.action.os_hypium.device_logger import DeviceLogger +from aw import Common + + +class SubStartupAppspawnAppclone0900(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + Step("安装测试hap并打开") + bundle_name = "com.example.intaketest" + hap_path = Common.sourcepath('intaketest.hap', "sub_startup_appspawn_appclone") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.clear_app_data(bundle_name) + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + + self.driver.AppManager.stop_app("com.example.settings") + self.driver.AppManager.start_app("com.example.settings") + self.driver.swipe(UiParam.UP) + for text in ["系统", "应用分身", "IntakeTest"]: + self.driver.touch(BY.text(text)) + for i in range(5): + self.driver.touch(BY.text("创建分身")) + time.sleep(1) + self.driver.AppManager.stop_app("com.example.settings") + + for i in range(1, 7): + self.driver.AppManager.start_app(bundle_name) + if i == 1: + self.driver.touch(BY.text("IntakeTest")) + pid = self.driver.System.get_pid(bundle_name) + else: + self.driver.touch(BY.text("更多打开方式")) + self.driver.touch(BY.text("IntakeTest%d" % (i - 1))) + pid = self.driver.System.get_pid("%s%d" % (bundle_name, i - 1)) + self.driver.Assert.equal(type(pid), int) + + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.start_app("com.example.settings") + self.driver.swipe(UiParam.UP) + for text in ["系统", "应用分身"]: + self.driver.touch(BY.text(text)) + self.driver.check_component_exist(BY.text("IntakeTest"), expect_exist=False) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.stop_app("com.example.settings") diff --git a/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0100.json b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0100.json new file mode 100644 index 0000000000000000000000000000000000000000..a69713ef05f2d25440f98d8eefc5d5fbd6a71e8a --- /dev/null +++ b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0100.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0100.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0100.py b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0100.py new file mode 100644 index 0000000000000000000000000000000000000000..8ed54e46203ec044b2814f3d356e9cae69434c1d --- /dev/null +++ b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0100.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from aw import Common + + +class SubStartupAppspawnAtomservice0100(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + hap_info01, hap_info02 = [], [] + bundle_name = "com.atomicservice.5765880207854649689" + bundle_name_start = "+auid-ohosAnonymousUid+com.atomicservice.5765880207854649689" + hap_path = Common.sourcepath('atomicservice.hap', "sub_startup_appspawn_atomservice") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.clear_app_data(bundle_name) + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + + for path in ["base", "database"]: + for i in range(1, 5): + has_dir = self.driver.Storage.has_dir("/data/app/el%d/100/%s/%s" % (i, path, bundle_name)) + has_dir_login = self.driver.Storage.has_dir("/data/app/el%d/100/%s/%s" % (i, path, bundle_name_start)) + self.driver.Assert.equal(has_dir, True) + self.driver.Assert.equal(has_dir_login, False) + + log_has_dir = self.driver.Storage.has_dir("/data/app/el2/100/log/%s" % bundle_name) + log_has_dir_login = self.driver.Storage.has_dir("/data/app/el2/100/log/%s" % bundle_name_start) + self.driver.Assert.equal(log_has_dir, True) + self.driver.Assert.equal(log_has_dir_login, False) + + mnt_has_dir = self.driver.Storage.has_dir("/mnt/share/100/%s" % bundle_name) + mnt_has_dir_login = self.driver.Storage.has_dir("/mnt/share/100/%s" % bundle_name_start) + self.driver.Assert.equal(mnt_has_dir, True) + self.driver.Assert.equal(mnt_has_dir_login, False) + + self.driver.shell("aa start -a EntryAbility -b %s" % bundle_name) + for path in ["base", "database"]: + for i in range(1, 5): + has_dir_login = self.driver.Storage.has_dir("/data/app/el%d/100/%s/%s" % (i, path, bundle_name_start)) + self.driver.Assert.equal(has_dir_login, True) + + mnt_has_dir_login = self.driver.Storage.has_dir("/mnt/share/100/%s" % bundle_name_start) + self.driver.Assert.equal(mnt_has_dir_login, True) + + for i in range(1, 5): + hap_detail = self.driver.shell("ls -lZ ../data/app/el%d/100/%s" % (i, "base")).split("\n") + for hap in hap_detail[1:-2]: + if hap.split()[-1] == bundle_name: + hap_info01 = hap + if hap.split()[-1] == bundle_name_start: + hap_info02 = hap + for index in range(2, 5): + self.driver.Assert.equal(hap_info01.split()[index], hap_info02.split()[index]) + + hap_detail = self.driver.shell("ls -lZ ../mnt/share/100").split("\n") + for hap in hap_detail[1:-2]: + if hap.split()[-1] == bundle_name: + hap_info01 = hap + if hap.split()[-1] == bundle_name_start: + hap_info02 = hap + for index in range(2, 5): + self.driver.Assert.equal(hap_info01.split()[index], hap_info02.split()[index]) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.uninstall_app("com.atomicservice.5765880207854649689") diff --git a/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0200.json b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0200.json new file mode 100644 index 0000000000000000000000000000000000000000..0e23f9091684c9455b315bd3019e10d8087cecd3 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0200.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0200.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0200.py b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0200.py new file mode 100644 index 0000000000000000000000000000000000000000..f420255115aa2e65bfb4c094bb0192cee7bb4f1e --- /dev/null +++ b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0200.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from hypium.model import UiParam +from aw import Common + + +class SubStartupAppspawnAtomservice0200(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + + Step("解锁屏幕") + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def login_account(self): + Step("登录帐号") + setting_name = "com.example.settings" + with open(r"config/userLogin.json", 'r', encoding='UTF-8') as f: + account = json.load(f) + self.driver.AppManager.stop_app(setting_name) + self.driver.AppManager.start_app(setting_name) + self.driver.touch(BY.key("entry_image_account")) + comps1 = self.driver.find_component(BY.key("inp_hwid_login_account_name_before")) + if comps1: + self.driver.input_text(comps1, account["userName"]) + self.driver.close_soft_keyboard() + self.driver.touch(BY.key("button_text")) + comps2 = self.driver.find_component(BY.key("inp_hwid_login_password")) + self.driver.input_text(comps2, account["passWord"]) + else: + comps3 = self.driver.find_component(BY.key("inp_hwid_login_account_name")) + self.driver.clear_text(comps3) + self.driver.input_text(comps3, account["userName"]) + comps4 = self.driver.find_component(BY.key("inp_hwid_login_password")) + self.driver.input_text(comps4, account["passWord"]) + self.driver.touch(BY.key("button_text")) + self.driver.wait_for_component(BY.text("继续"), timeout=15) + self.driver.touch(BY.text("继续")) + + def exit_account(self): + Step("退出帐号") + setting_name = "com.example.settings" + self.driver.AppManager.stop_app(setting_name) + self.driver.AppManager.start_app(setting_name) + self.driver.touch(BY.key("entry_image_account")) + self.driver.swipe(UiParam.UP) + comp = self.driver.find_component(BY.key("hwid_account_center_logout_text"), scroll_target=BY.type("Scroll")) + self.driver.touch(comp) + self.driver.touch(BY.key("button_text")) + comps5 = self.driver.find_component(BY.key("advanced_dialog_button_1")) + if comps5: + self.driver.touch(comps5) + time.sleep(5) + else: + pass + + def process(self): + self.login_account() + hap_info01, hap_info02 = [], [] + bundle_name = "com.atomicservice.5765880207854649689" + bundle_name_start = "+auid-9E1E70ABFF4AAFE1E18AF18E0F75703713D" + "8678F9F9AB06C3B64C1CB1080615A+com.atomicservice.5765880207854649689" + hap_path = Common.sourcepath('atomicservice.hap', "sub_startup_appspawn_atomservice") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.clear_app_data(bundle_name) + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + + for path in ["base", "database"]: + for i in range(1, 5): + has_dir = self.driver.Storage.has_dir("/data/app/el%d/100/%s/%s" % (i, path, bundle_name)) + has_dir_login = self.driver.Storage.has_dir("/data/app/el%d/100/%s/%s" % (i, path, bundle_name_start)) + self.driver.Assert.equal(has_dir, True) + self.driver.Assert.equal(has_dir_login, False) + + log_has_dir = self.driver.Storage.has_dir("/data/app/el2/100/log/%s" % bundle_name) + self.driver.Assert.equal(log_has_dir, True) + + mnt_has_dir = self.driver.Storage.has_dir("/mnt/share/100/%s" % bundle_name) + mnt_has_dir_login = self.driver.Storage.has_dir("/mnt/share/100/%s" % bundle_name_start) + self.driver.Assert.equal(mnt_has_dir, True) + self.driver.Assert.equal(mnt_has_dir_login, False) + + self.driver.shell("aa start -a EntryAbility -b %s" % bundle_name) + for path in ["base", "database"]: + for i in range(1, 5): + has_dir_login = self.driver.Storage.has_dir("/data/app/el%d/100/%s/%s" % (i, path, bundle_name_start)) + self.driver.Assert.equal(has_dir_login, True) + + Step("校验UGO、所有者、所属组、selinux标签一致") + for i in range(1, 5): + hap_detail = self.driver.shell("ls -lZ ../data/app/el%d/100/%s" % (i, "base")).split("\n") + for hap in hap_detail[1:-2]: + if hap.split()[-1] == bundle_name: + hap_info01 = hap + if hap.split()[-1] == bundle_name_start: + hap_info02 = hap + #校验用户字符串长度为64 + self.driver.Assert.equal(len(hap_info02.split()[-1].split("-")[1].split("+")[0]), 64) + for index in range(2, 5): + self.driver.Assert.equal(hap_info01.split()[index], hap_info02.split()[index]) + + hap_detail = self.driver.shell("ls -lZ ../mnt/share/100/").split("\n") + for hap in hap_detail[1:-2]: + if hap.split()[-1] == bundle_name: + hap_info01 = hap + if hap.split()[-1] == bundle_name_start: + hap_info02 = hap + self.driver.Assert.equal(len(hap_info02.split()[-1].split("-")[1].split("+")[0]), 64) + for index in range(2, 5): + self.driver.Assert.equal(hap_info01.split()[index], hap_info02.split()[index]) + self.exit_account() + + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.uninstall_app("com.atomicservice.5765880207854649689") diff --git a/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0300.json b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0300.json new file mode 100644 index 0000000000000000000000000000000000000000..c5a1372fea521480ac4de270230291d44b950fee --- /dev/null +++ b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0300.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0300.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0300.py b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0300.py new file mode 100644 index 0000000000000000000000000000000000000000..9001688ab2f637ed1daa3e847efc327c6b24c265 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0300.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from aw import Common + + +class SubStartupAppspawnAtomservice0300(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + bundle_name = "com.atomicservice.5765880207854649689" + bundle_name_start = "+auid-ohosAnonymousUid+com.atomicservice.5765880207854649689" + hap_path = Common.sourcepath('atomicservice.hap', "sub_startup_appspawn_atomservice") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.clear_app_data(bundle_name) + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + self.driver.shell("aa start -a EntryAbility -b %s" % bundle_name) + pid = self.driver.System.get_pid(bundle_name) + + for path in ["base", "database"]: + for i in range(1, 5): + result1 = self.driver.shell("ls ../proc/%d/root/data/storage/el%d/%s" % (pid, i, path)) + result2 = self.driver.shell("ls ../data/app/el%d/100/%s/%s" % (i, path, bundle_name_start)) + self.driver.Assert.equal(result1, result2) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.uninstall_app(bundle_name) diff --git a/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0400.json b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0400.json new file mode 100644 index 0000000000000000000000000000000000000000..fac1fba735e2baa056f2ff78f159a7a30f7e6ebe --- /dev/null +++ b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0400.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0400.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0400.py b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0400.py new file mode 100644 index 0000000000000000000000000000000000000000..8d8a0ea7cc249362ea2b96b490d5e56eedd3c6bf --- /dev/null +++ b/test/autotest/sub_startup_appspawn_atomservice/sub_startup_appspawn_atomservice_0400.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from hypium.model import UiParam +from aw import Common + + +class SubStartupAppspawnAtomservice0400(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def login_account(self): + Step("登录帐号") + setting_name = "com.example.settings" + with open(r"config/userLogin.json", 'r', encoding='UTF-8') as f: + account = json.load(f) + self.driver.AppManager.stop_app(setting_name) + self.driver.AppManager.start_app(setting_name) + self.driver.touch(BY.key("entry_image_account")) + + def exit_account(self): + Step("退出帐号") + setting_name = "com.example.settings" + self.driver.AppManager.stop_app(setting_name) + self.driver.AppManager.start_app(setting_name) + self.driver.touch(BY.key("entry_image_account")) + self.driver.swipe(UiParam.UP) + comp = self.driver.find_component(BY.key("hwid_account_center_logout_text"), scroll_target=BY.type("Scroll")) + self.driver.touch(comp) + self.driver.touch(BY.key("button_text")) + comps5 = self.driver.find_component(BY.key("advanced_dialog_button_1")) + if comps5: + self.driver.touch(comps5) + time.sleep(5) + else: + pass + + def process(self): + self.login_account() + comps1 = self.driver.find_component(BY.key("inp_hwid_login_account_name_before")) + if comps1: + self.driver.input_text(comps1, account["userName"]) + self.driver.close_soft_keyboard() + self.driver.touch(BY.text("下一步")) + comps2 = self.driver.find_component(BY.key("inp_hwid_login_password")) + self.driver.input_text(comps2, account["passWord"]) + else: + comps3 = self.driver.find_component(BY.key("inp_hwid_login_account_name")) + self.driver.clear_text(comps3) + self.driver.input_text(comps3, account["userName"]) + comps4 = self.driver.find_component(BY.key("inp_hwid_login_password")) + self.driver.input_text(comps4, account["passWord"]) + self.driver.touch(BY.key("button_text")) + self.driver.wait_for_component(BY.text("继续"), timeout=10) + self.driver.touch(BY.text("继续")) + + Step("启动元服务应用,检查目标路径是否存在") + bundle_name = "com.atomicservice.5765880207854649689" + bundle_name_start = "+auid-9E1E70ABFF4AAFE1E18AF18E0F75703713D" + "8678F9F9AB06C3B64C1CB1080615A+com.atomicservice.5765880207854649689" + hap_path = Common.sourcepath('atomicservice.hap', "sub_startup_appspawn_atomservice") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.clear_app_data(bundle_name) + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + self.driver.shell("aa start -a EntryAbility -b %s" % bundle_name) + pid = self.driver.System.get_pid(bundle_name) + + for path in ["base", "database"]: + for i in range(1, 5): + result1 = self.driver.shell("ls ../proc/%d/root/data/storage/el%d/%s" % (pid, i, path)) + result2 = self.driver.shell("ls ../data/app/el%d/100/%s/%s" % (i, path, bundle_name_start)) + self.driver.Assert.equal(result1, result2) + self.exit_account() + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.uninstall_app(bundle_name) diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0100.json b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0100.json new file mode 100644 index 0000000000000000000000000000000000000000..1e0f7a449ba2f8b7e20c2b8c975a21780f686a09 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0100.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_APPSPAWN_BASE/SubStartupAppspawnBase0100.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0100.py b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0100.py new file mode 100644 index 0000000000000000000000000000000000000000..71e6c7a1ea59ce31560b740c1f8654f77e31dcd3 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0100.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver + + +class SubStartupAppspawnBase0100(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.shell("power-shell timeout -o 86400000") + + def process(self): + process_list = ["appspawn", "nwebspawn"] + for process in process_list: + pid = self.driver.System.get_pid(process) + self.driver.Assert.equal(type(pid), int) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0200.json b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0200.json new file mode 100644 index 0000000000000000000000000000000000000000..87570d7fd58c08bd52442995c7d32e54310312b0 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0200.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_APPSPAWN_BASE/SubStartupAppspawnBase0200.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0200.py b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0200.py new file mode 100644 index 0000000000000000000000000000000000000000..2fb7a9887862c63b211e721e7d87f8251f0ea13a --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0200.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from aw import Common + + +class SubStartupAppspawnBase0200(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.shell("power-shell timeout -o 86400000") + + def process(self): + Step("安装测试hap并打开") + bundle_name = "com.example.myapplication" + hap_path = Common.sourcepath('test.hap', "SUB_STARTUP_APPSPAWN_BASE") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + self.driver.AppManager.start_app(bundle_name) + + result = self.driver.shell("ps -efZ|grep %s|grep -v grep" % bundle_name).split() + for i in ["u:r:debug_hap:s0", bundle_name]: + self.driver.Assert.contains(result, i) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.uninstall_app(bundle_name) \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0300.json b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0300.json new file mode 100644 index 0000000000000000000000000000000000000000..22c6ede8905641c129b0b617c9cbb82ae66dbf58 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0300.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_APPSPAWN_BASE/SubStartupAppspawnBase0300.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0300.py b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0300.py new file mode 100644 index 0000000000000000000000000000000000000000..d376968c1d106ce3ea2a6e72dae1acf6745b8760 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0300.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from aw import Common + + +class SubStartupAppspawnBase0300(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.shell("power-shell timeout -o 86400000") + + def process(self): + Step("安装测试hap并打开") + bundle_name = "com.example.myapplication" + hap_path = Common.sourcepath('asan.hap', "SUB_STARTUP_APPSPAWN_BASE") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + self.driver.AppManager.start_app(bundle_name) + + result = self.driver.shell("ps -efZ|grep %s|grep -v grep" % bundle_name).split() + for i in ["u:r:debug_hap:s0", bundle_name]: + self.driver.Assert.contains(result, i) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.uninstall_app(bundle_name) \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0400.json b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0400.json new file mode 100644 index 0000000000000000000000000000000000000000..3830b0009691a1a54ec4a3000503297e5d4f7c92 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0400.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_APPSPAWN_BASE/SubStartupAppspawnBase0400.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0400.py b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0400.py new file mode 100644 index 0000000000000000000000000000000000000000..77ca024b7674843e07de7bce4882f157c954e1e5 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0400.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from aw import Common + + +class SubStartupAppspawnBase0400(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.shell("power-shell timeout -o 86400000") + + def process(self): + Step("安装测试hap并打开") + bundle_name = "com.example.myapplication" + for hap in ['nweb.hap', 'nweb_asan.hap']: + hap_path = Common.sourcepath(hap, "SUB_STARTUP_APPSPAWN_BASE") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + self.driver.AppManager.start_app(bundle_name) + + result_dict = self.driver.shell("ps -efZ|grep %s|grep -v grep" % bundle_name).split("\n") + for result in result_dict: + if result.endswith("%s:render" % bundle_name): + result_render = result + self.driver.Assert.contains(result_render.split(), "u:r:isolated_render:s0") + self.driver.AppManager.uninstall_app(bundle_name) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0500.json b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0500.json new file mode 100644 index 0000000000000000000000000000000000000000..b825cf197f4a17071e82580eaa122f75622fb57d --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0500.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_APPSPAWN_BASE/SubStartupAppspawnBase0500.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0500.py b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0500.py new file mode 100644 index 0000000000000000000000000000000000000000..efec5734f4c8b45c95015e1a6f00a0eddf0e5c46 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0500.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from aw import Common + + +class SubStartupAppspawnBase0500(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.shell("power-shell timeout -o 86400000") + + def process(self): + Step("安装测试hap并打开") + bundle_name = "com.app.hmos.inputmethod" + self.driver.AppManager.start_app(bundle_name) + pid = self.driver.System.get_pid(bundle_name) + for path in ["base", "database"]: + for i in range(1, 5): + result01 = self.driver.Storage.has_dir("/proc/%d/root/data/storage/el%d/%s" % (pid, i, path)) + result02 = self.driver.Storage.has_dir("/data/app/el%d/100/%s" % (i, path)) + self.driver.Assert.equal(result01, True) + self.driver.Assert.equal(result02, True) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.stop_app(bundle_name) \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0600.json b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0600.json new file mode 100644 index 0000000000000000000000000000000000000000..1b007eb5b4c7898b89074c514d1156b40b6d759f --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0600.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_APPSPAWN_BASE/SubStartupAppspawnBase0600.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0600.py b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0600.py new file mode 100644 index 0000000000000000000000000000000000000000..112c9a1871ee5b39630b031859b3da58e6c6bd16 --- /dev/null +++ b/test/autotest/sub_startup_appspawn_base/sub_startup_appspawn_base_0600.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from aw import Common + + +class SubStartupAppspawnBase0600(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.shell("power-shell timeout -o 86400000") + + def process(self): + Step("安装测试hap并打开") + bundle_name = "com.ohos.mytest" + clone_bundle_name = "com.ohos.mytest1" + hap_path = Common.sourcepath("mytest.hap", "SUB_STARTUP_APPSPAWN_BASE") + hap = self.driver.AppManager.has_app(bundle_name) + if hap: + self.driver.AppManager.uninstall_app(bundle_name) + self.driver.AppManager.install_app(hap_path) + else: + self.driver.AppManager.install_app(hap_path) + self.driver.AppManager.start_app(bundle_name) + + for text in ["安装克隆应用", "startAbilityByAppIndex"]: + self.driver.touch(BY.text(text)) + + dict01 = { + bundle_name: "master.txt", + clone_bundle_name: "slave.txt" + } + + dict02 = { + bundle_name: "slave.txt", + clone_bundle_name: "master.txt" + } + + for i, txt in dict01.items(): + pid = self.driver.System.get_pid(i) + if i == clone_bundle_name: + self.driver.shell("touch ../data/app/el2/100/base/+clone-1+%s/%s" % (bundle_name, txt)) + else: + self.driver.shell("touch ../data/app/el2/100/base/%s/%s" % (i, txt)) + result = self.driver.Storage.has_file("/proc/%d/root/data/storage/el2/base/%s" % (pid, txt)) + self.driver.Assert.equal(result, True) + + for i, txt in dict02.items(): + pid = self.driver.System.get_pid(i) + result = self.driver.Storage.has_file("/proc/%d/root/data/storage/el2/base/%s" % (pid, txt)) + self.driver.Assert.equal(result, False) + + def teardown(self): + Step("收尾工作.................") + self.driver.AppManager.uninstall_app(bundle_name) \ No newline at end of file diff --git a/test/fuzztest/appspawnclient_fuzzer/appspawnclient_fuzzer.cpp b/test/fuzztest/appspawnclient_fuzzer/appspawnclient_fuzzer.cpp index 84749c8869886501b43eecad1467d25fb6de0c37..39e6553df23d6668eb6f0b8bccfd87963f0dc238 100644 --- a/test/fuzztest/appspawnclient_fuzzer/appspawnclient_fuzzer.cpp +++ b/test/fuzztest/appspawnclient_fuzzer/appspawnclient_fuzzer.cpp @@ -20,16 +20,16 @@ namespace OHOS { int FuzzAppSpawnClientInit(const uint8_t *data, size_t size) { - const char *name = APPSPAWN_SERVER_NAME; + std::string serviceName(reinterpret_cast(data), size); AppSpawnClientHandle handle = nullptr; - return AppSpawnClientInit(name, &handle); + return AppSpawnClientInit(serviceName.c_str(), &handle); } int FuzzAppSpawnClientDestroy(const uint8_t *data, size_t size) { - const char *name = APPSPAWN_SERVER_NAME; + std::string serviceName(reinterpret_cast(data), size); AppSpawnClientHandle handle = nullptr; - if (AppSpawnClientInit(name, &handle) != 0) { + if (AppSpawnClientInit(serviceName.c_str(), &handle) != 0) { return -1; } return AppSpawnClientDestroy(handle); @@ -277,12 +277,21 @@ namespace OHOS { int FuzzGetMaxPermissionIndex(const uint8_t *data, size_t size) { - return GetMaxPermissionIndex(nullptr); + std::string serviceName(reinterpret_cast(data), size); + AppSpawnClientHandle handle = nullptr; + if (AppSpawnClientInit(serviceName.c_str(), &handle) != 0) { + return -1; + } + return GetMaxPermissionIndex(handle); } int FuzzGetPermissionByIndex(const uint8_t *data, size_t size) { - int32_t index = static_cast(size); + if ((data == nullptr) || (size < sizeof(int32_t))) { + return -1; + } + + int32_t index = *(reinterpret_cast(data)); if (GetPermissionByIndex(nullptr, index) == nullptr) { return -1; } diff --git a/test/mock/app_spawn_stub.h b/test/mock/app_spawn_stub.h index 144e601a4b40bfa30e133ef4e9b14bb719c69e45..b3a4d6a753db19e677fe98f7e5f07ae87c831673 100644 --- a/test/mock/app_spawn_stub.h +++ b/test/mock/app_spawn_stub.h @@ -112,6 +112,7 @@ int RunBegetctlBootApp(AppSpawnMgr *content, AppSpawningCtx *property); void SetSystemEnv(void); void RunAppSandbox(const char *ptyName); HOOK_MGR *GetAppSpawnHookMgr(void); +int SpawnKickDogStart(AppSpawnMgr *mgrContent); #define STUB_NEED_CHECK 0x01 typedef int (*ExecvFunc)(const char *pathname, char *const argv[]); enum { @@ -131,4 +132,5 @@ StubNode *GetStubNode(int type); } #endif int SetSelinuxConNweb(const AppSpawnMgr *content, const AppSpawningCtx *property); +void InitAppCommonEnv(const AppSpawningCtx *property); #endif // APPSPAWN_TEST_STUB_H diff --git a/test/mock/app_system_stub.c b/test/mock/app_system_stub.c index 1db876201930d6ee6f28b90b38dea0e242fe7fb6..d9eb03aec2967d9366b7849a2e714ee314b932db 100644 --- a/test/mock/app_system_stub.c +++ b/test/mock/app_system_stub.c @@ -108,6 +108,9 @@ void *DlsymStub(void *handle, const char *symbol) if (strcmp(symbol, "NWebRenderMain") == 0) { return ((g_dlsymResultFlags & DLSYM_FAIL_NWEB_MAIN) == 0) ? (void *)(NWebRenderMainStub) : NULL; } + if (strcmp(symbol, "GetPermissionIndex") == 0) { + return (void *) (GetPermissionIndex); + } return NULL; } diff --git a/test/moduletest/appspawn_client_test.cpp b/test/moduletest/appspawn_client_test.cpp index eedc2050a19e67299b205f2feb85c7dd7f31efda..3272b03d0322ce0c3d18e8b0bbb21c5cdf3687fa 100644 --- a/test/moduletest/appspawn_client_test.cpp +++ b/test/moduletest/appspawn_client_test.cpp @@ -120,5 +120,45 @@ HWTEST_F(AppSpawnClientTest, AppSpawn_Client_test002, TestSize.Level0) AppSpawnClientDestroy(clientHandle); } +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_test003, TestSize.Level0) +{ + AppSpawnClientHandle clientHandle = CreateClient(APPSPAWN_SERVER_NAME); + ASSERT_EQ(clientHandle != NULL, 1); + + AppSpawnReqMsgHandle reqHandle = 0; + int ret = AppSpawnReqMsgCreate(MSG_UNINSTALL_DEBUG_HAP, "test.uninstall", &reqHandle); + ASSERT_EQ(ret, 0); + + ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 100, "test.uninstall"); + ASSERT_EQ(ret, 0); + + AppSpawnResult result = {}; + ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); + if (ret == 0 && result.pid > 0) { + kill(result.pid, SIGKILL); + } + AppSpawnClientDestroy(clientHandle); +} + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_test004, TestSize.Level0) +{ + AppSpawnClientHandle clientHandle = CreateClient(APPSPAWN_SERVER_NAME); + ASSERT_EQ(clientHandle != NULL, 1); + + AppSpawnReqMsgHandle reqHandle = 0; + int ret = AppSpawnReqMsgCreate(MSG_UNINSTALL_DEBUG_HAP, "test.uninstall", &reqHandle); + ASSERT_EQ(ret, 0); + + ret = AppSpawnReqMsgAddStringInfo(reqHandle, MSG_EXT_NAME_USERID, "100"); + ASSERT_EQ(ret, 0); + + AppSpawnResult result = {}; + ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); + if (ret == 0 && result.pid > 0) { + kill(result.pid, SIGKILL); + } + AppSpawnClientDestroy(clientHandle); +} + } // namespace AppSpawn } // namespace OHOS diff --git a/test/test_app_info/datagroup/test_app_info.json b/test/test_app_info/datagroup/test_app_info.json new file mode 100644 index 0000000000000000000000000000000000000000..5be72afa36ae5568bb5a758abc13f59f189cf017 --- /dev/null +++ b/test/test_app_info/datagroup/test_app_info.json @@ -0,0 +1,38 @@ +{ + "msg-type": 0, + "msg-flags": [1, 2, 14], + "process-name" : "ohos.samples.etsclock", + "pid": 328018, + "dac-info" : { + "uid" : 20010043, + "gid" : 20010043, + "gid-table" : [20010043], + "user-name" : "" + }, + "access-token": { + "accessTokenIdEx": 537854093 + }, + "permission": [ + "ohos.permission.PROTECT_SCREEN_LOCK_DATA" + ], + "internet-permission": { + "set-allow-internet": 0, + "allow-internet": 0 + }, + "bundle-info": { + "bundle-index": 0, + "bundle-name": "ohos.samples.etsclock" + }, + "owner-id": "", + "render-cmd": "1234567890", + "domain-info": { + "hap-flags": 0, + "apl": "normal" + }, + "ext-info": [ + { + "name": "DataGroup", + "value": "[{\"gid\": \"1002\", \"dir\": \"data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840\", \"dataGroupId\": \"43200\", \"uuid\": \"49c016e6-065a-abd1-5867-b1f91114f840\"}, {\"gid\": \"1002\", \"dir\": \"data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840\", \"dataGroupId\": \"43200\", \"uuid\": \"49c016e6-065a-abd1-5867-b1f91114f840\"}, {\"gid\": \"1002\", \"dir\": \"data/app/el3/100/group/49c016e6-065a-abd1-5867-b1f91114f840\", \"dataGroupId\": \"43200\", \"uuid\": \"49c016e6-065a-abd1-5867-b1f91114f840\"}, {\"gid\": \"1002\", \"dir\": \"data/app/el4/100/group/49c016e6-065a-abd1-5867-b1f91114f840\", \"dataGroupId\": \"43200\", \"uuid\": \"49c016e6-065a-abd1-5867-b1f91114f840\"}, { \"gid\": \"1002\", \"dir\": \"data/app/el5/100/group/49c016e6-065a-abd1-5867-b1f91114f840\", \"dataGroupId\": \"43200\", \"uuid\": \"49c016e6-065a-abd1-5867-b1f91114f840\"}]" + } + ] +} diff --git a/test/unittest/app_spawn_client_test/BUILD.gn b/test/unittest/app_spawn_client_test/BUILD.gn index 1a027dfab1bbc72873a54e836938872993f55f25..7f2beb0cfc2f10ed09c97f3859594409614ab87d 100644 --- a/test/unittest/app_spawn_client_test/BUILD.gn +++ b/test/unittest/app_spawn_client_test/BUILD.gn @@ -87,6 +87,7 @@ ohos_unittest("AppSpawn_client_ut") { "cJSON:cjson", "c_utils:utils", "config_policy:configpolicy_util", + "ffrt:libffrt", "hilog:libhilog", "hitrace:hitrace_meter", "init:libbegetutil", diff --git a/test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp b/test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp index fa1547d1938d5237b746ed3bb5b6d1ebe6a90ca5..3edef90a182186d18fc8327b501a3b45d0d7cfe1 100644 --- a/test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp +++ b/test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp @@ -584,6 +584,7 @@ HWTEST_F(AppSpawnInterfaceTest, App_Spawn_Interface_ClientSocket_001, TestSize.L socketId = CreateClientSocket(CLIENT_MAX, 2); CloseClientSocket(socketId); CloseClientSocket(-1); + EXPECT_NE(socketId, 0); } HWTEST_F(AppSpawnInterfaceTest, App_Spawn_Interface_GetSpawnTimeout_001, TestSize.Level0) @@ -608,4 +609,48 @@ HWTEST_F(AppSpawnInterfaceTest, App_Spawn_Interface_NWeb, TestSize.Level0) EXPECT_GE(pid, 0); } +/** + * @brief 测试接口:SpawnListenFdSet + * + */ +HWTEST_F(AppSpawnInterfaceTest, App_SpawnListenFdSet_001, TestSize.Level0) +{ + int ret = SpawnListenFdSet(-1); + EXPECT_EQ(ret, APPSPAWN_ARG_INVALID); + + int pipefd[2]; + EXPECT_EQ(pipe(pipefd), 0); + + ret = SpawnListenFdSet(pipefd[1]); + EXPECT_EQ(ret, 0); + + close(pipefd[0]); + close(pipefd[1]); +} + +/** + * @brief 测试接口:SpawnListenCloseSet + * + */ +HWTEST_F(AppSpawnInterfaceTest, App_SpawnListenCloseSet_001, TestSize.Level0) +{ + int ret = SpawnListenCloseSet(); + EXPECT_EQ(ret, 0); +} + +/** + * @brief 测试接口:AppSpawnClientSendUserLockStatus + * + */ +HWTEST_F(AppSpawnInterfaceTest, AppSpawnClientSendUserLockStatus_001, TestSize.Level0) +{ + int ret = AppSpawnClientSendUserLockStatus(0, true); + EXPECT_NE(ret, 0); + ret = AppSpawnClientSendUserLockStatus(0, false); + EXPECT_NE(ret, 0); + ret = AppSpawnClientSendUserLockStatus(100, true); + EXPECT_NE(ret, 0); + ret = AppSpawnClientSendUserLockStatus(100, false); + EXPECT_NE(ret, 0); +} } // namespace OHOS diff --git a/test/unittest/app_spawn_standard_test/BUILD.gn b/test/unittest/app_spawn_standard_test/BUILD.gn index f997543fdc9c91dfda786278577ed510dfe504e1..7a2e19219e40b412200869e0dca3a228ccfaa062 100644 --- a/test/unittest/app_spawn_standard_test/BUILD.gn +++ b/test/unittest/app_spawn_standard_test/BUILD.gn @@ -132,9 +132,7 @@ ohos_unittest("AppSpawn_ut") { "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_beget_test.cpp", "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_cgroup_test.cpp", "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_child_test.cpp", - "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_cold_run_test.cpp", "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_command_lexer_test.cpp", - "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_common_test.cpp", "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_kickdog_test.cpp", "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_module_interface_test.cpp", "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_sandboxmgr_test.cpp", @@ -151,6 +149,7 @@ ohos_unittest("AppSpawn_ut") { defines += [ "APPSPAWN_SANDBOX_NEW" ] } else { sources += [ + "${appspawn_path}/modules/sandbox/sandbox_shared_mount.cpp", "${appspawn_path}/modules/sandbox/sandbox_utils.cpp", "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_sandbox_test.cpp", ] @@ -171,6 +170,385 @@ ohos_unittest("AppSpawn_ut") { "c_utils:utils", "config_policy:configpolicy_util", "eventhandler:libeventhandler", + "ffrt:libffrt", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "init:seccomp", + "ipc:ipc_core", + "napi:ace_napi", + "os_account:os_account_innerkits", + "resource_management:global_resmgr", + ] + if (enable_appspawn_dump_catcher) { + external_deps += [ "faultloggerd:libdfx_dumpcatcher" ] + } + if (asan_detector || is_asan) { + defines += [ "ASAN_DETECTOR" ] + sources += [ "${appspawn_path}/modules/asan/asan_detector.c" ] + } + + if (build_selinux) { + defines += [ "WITH_SELINUX" ] + external_deps += [ + "selinux:libselinux", + "selinux_adapter:libhap_restorecon", + ] + } + + if (appspawn_report_event) { + defines += [ "REPORT_EVENT" ] + external_deps += [ "hisysevent:libhisysevent" ] + sources += [ + "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", + "${appspawn_path}/modules/sysevent/event_reporter.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", + ] + } + + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + defines += [ "APPSPAWN_64" ] + } + + if (dlp_permission_enable) { + cflags_cc = [ "-DWITH_DLP" ] + external_deps += [ "dlp_permission_service:libdlp_fuse" ] + } +} + +ohos_unittest("AppSpawn_coldrun_ut") { + module_out_path = "${module_output_path}" + if (appspawn_unittest_coverage) { + cflags = [ "--coverage" ] + ldflags = [ "--coverage" ] + cflags_cc = [ "--coverage" ] + } + deps = [] + defines = [ + "APPSPAWN_BASE_DIR=\"/data/appspawn_ut\"", + "APPSPAWN_LABEL=\"APPSPAWN_UT\"", + "APPSPAWN_TEST", + "APPSPAWN_DEBUG", + "DEBUG_BEGETCTL_BOOT", + "USER_TIMER_TO_CHECK", + "OHOS_DEBUG", + "GRAPHIC_PERMISSION_CHECK", + "capset=CapsetStub", + "unshare=UnshareStub", + "mount=MountStub", + "symlink=SymlinkStub", + "chdir=ChdirStub", + "chroot=ChrootStub", + "syscall=SyscallStub", + "umount2=Umount2Stub", + "access=AccessStub", + "dlopen=DlopenStub", + "dlsym=DlsymStub", + "dlclose=DlcloseStub", + "execv=ExecvStub", + "getprocpid=GetprocpidStub", + "setgroups=SetgroupsStub", + "setresgid=SetresgidStub", + "setresuid=SetresuidStub", + "setuid=SetuidStub", + "setgid=SetgidStub", + "execvp=ExecvpStub", + "ioctl=IoctlStub", + "execve=ExecveStub", + "setcon=SetconStub", + ] + + include_dirs = [ + "${appspawn_path}", + "${appspawn_path}/common", + "${appspawn_path}/standard", + "${appspawn_path}/modules/modulemgr", + "${appspawn_path}/modules/ace_adapter", + "${appspawn_path}/modules/common", + "${appspawn_path}/modules/sandbox", + "${appspawn_path}/modules/sysevent", + "${appspawn_innerkits_path}/client", + "${appspawn_innerkits_path}/include", + "${appspawn_innerkits_path}/permission", + "${appspawn_path}/modules/module_engine/include", + "${appspawn_path}/test/mock", + "${appspawn_path}/test/unittest", + "${appspawn_path}/util/include", + ] + sources = [ + "${appspawn_path}/common/appspawn_server.c", + "${appspawn_path}/common/appspawn_trace.cpp", + "${appspawn_path}/modules/modulemgr/appspawn_modulemgr.c", + "${appspawn_path}/standard/appspawn_appmgr.c", + "${appspawn_path}/standard/appspawn_kickdog.c", + "${appspawn_path}/standard/appspawn_msgmgr.c", + "${appspawn_path}/standard/appspawn_service.c", + "${appspawn_path}/standard/nwebspawn_launcher.c", + "${appspawn_path}/util/src/appspawn_utils.c", + ] + + # client + sources += [ + "${appspawn_innerkits_path}/client/appspawn_client.c", + "${appspawn_innerkits_path}/client/appspawn_msg.c", + "${appspawn_innerkits_path}/permission/appspawn_mount_permission.c", + ] + + # modules sources + sources += [ + "${appspawn_path}/modules/ace_adapter/ace_adapter.cpp", + "${appspawn_path}/modules/ace_adapter/command_lexer.cpp", + "${appspawn_path}/modules/common/appspawn_adapter.cpp", + "${appspawn_path}/modules/common/appspawn_begetctl.c", + "${appspawn_path}/modules/common/appspawn_cgroup.c", + "${appspawn_path}/modules/common/appspawn_common.c", + "${appspawn_path}/modules/common/appspawn_dfx_dump.cpp", + "${appspawn_path}/modules/common/appspawn_namespace.c", + "${appspawn_path}/modules/common/appspawn_silk.c", + "${appspawn_path}/modules/nweb_adapter/nwebspawn_adapter.cpp", + "${appspawn_path}/modules/sandbox/appspawn_mount_template.c", + "${appspawn_path}/modules/sandbox/appspawn_permission.c", + "${appspawn_path}/modules/sandbox/appspawn_sandbox.c", + "${appspawn_path}/modules/sandbox/sandbox_adapter.cpp", + "${appspawn_path}/modules/sandbox/sandbox_cfgvar.c", + "${appspawn_path}/modules/sandbox/sandbox_expand.c", + "${appspawn_path}/modules/sandbox/sandbox_load.c", + "${appspawn_path}/modules/sandbox/sandbox_manager.c", + ] + + if (appspawn_use_encaps == true) { + sources += [ "${appspawn_path}/modules/common/appspawn_encaps.c" ] + } + + # add stub + include_dirs += [ "${appspawn_path}/test/mock" ] + sources += [ + "${appspawn_path}/test/mock/app_spawn_stub.cpp", + "${appspawn_path}/test/mock/app_system_stub.c", + ] + + # add test + include_dirs += [ "${appspawn_path}/test/unittest" ] + sources += [ + "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_cold_run_test.cpp", + "${appspawn_path}/test/unittest/app_spawn_test_helper.cpp", + ] + + if (defined(appspawn_sandbox_new) && appspawn_sandbox_new) { + defines += [ "APPSPAWN_SANDBOX_NEW" ] + } else { + sources += [ + "${appspawn_path}/modules/sandbox/sandbox_shared_mount.cpp", + "${appspawn_path}/modules/sandbox/sandbox_utils.cpp", + ] + } + + configs = [ "${appspawn_path}:appspawn_config" ] + external_deps = [ + "ability_base:want", + "ability_runtime:app_manager", + "ability_runtime:appkit_native", + "ability_runtime:runtime", + "access_token:libtokenid_sdk", + "access_token:libtokensetproc_shared", + "ace_engine:ace_forward_compatibility", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "cJSON:cjson", + "c_utils:utils", + "config_policy:configpolicy_util", + "eventhandler:libeventhandler", + "ffrt:libffrt", + "hilog:libhilog", + "hitrace:hitrace_meter", + "init:libbegetutil", + "init:seccomp", + "ipc:ipc_core", + "napi:ace_napi", + "os_account:os_account_innerkits", + "resource_management:global_resmgr", + ] + if (enable_appspawn_dump_catcher) { + external_deps += [ "faultloggerd:libdfx_dumpcatcher" ] + } + if (asan_detector || is_asan) { + defines += [ "ASAN_DETECTOR" ] + sources += [ "${appspawn_path}/modules/asan/asan_detector.c" ] + } + + if (build_selinux) { + defines += [ "WITH_SELINUX" ] + external_deps += [ + "selinux:libselinux", + "selinux_adapter:libhap_restorecon", + ] + } + + if (appspawn_report_event) { + defines += [ "REPORT_EVENT" ] + external_deps += [ "hisysevent:libhisysevent" ] + sources += [ + "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", + "${appspawn_path}/modules/sysevent/event_reporter.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", + ] + } + + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + defines += [ "APPSPAWN_64" ] + } + + if (dlp_permission_enable) { + cflags_cc = [ "-DWITH_DLP" ] + external_deps += [ "dlp_permission_service:libdlp_fuse" ] + } +} + +ohos_unittest("AppSpawn_common_ut") { + module_out_path = "${module_output_path}" + if (appspawn_unittest_coverage) { + cflags = [ "--coverage" ] + ldflags = [ "--coverage" ] + cflags_cc = [ "--coverage" ] + } + deps = [] + defines = [ + "APPSPAWN_BASE_DIR=\"/data/appspawn_ut\"", + "APPSPAWN_LABEL=\"APPSPAWN_UT\"", + "APPSPAWN_TEST", + "APPSPAWN_DEBUG", + "DEBUG_BEGETCTL_BOOT", + "USER_TIMER_TO_CHECK", + "OHOS_DEBUG", + "GRAPHIC_PERMISSION_CHECK", + "capset=CapsetStub", + "unshare=UnshareStub", + "mount=MountStub", + "symlink=SymlinkStub", + "chdir=ChdirStub", + "chroot=ChrootStub", + "syscall=SyscallStub", + "umount2=Umount2Stub", + "access=AccessStub", + "dlopen=DlopenStub", + "dlsym=DlsymStub", + "dlclose=DlcloseStub", + "execv=ExecvStub", + "getprocpid=GetprocpidStub", + "setgroups=SetgroupsStub", + "setresgid=SetresgidStub", + "setresuid=SetresuidStub", + "setuid=SetuidStub", + "setgid=SetgidStub", + "execvp=ExecvpStub", + "ioctl=IoctlStub", + "execve=ExecveStub", + "setcon=SetconStub", + ] + + include_dirs = [ + "${appspawn_path}", + "${appspawn_path}/common", + "${appspawn_path}/standard", + "${appspawn_path}/modules/modulemgr", + "${appspawn_path}/modules/ace_adapter", + "${appspawn_path}/modules/common", + "${appspawn_path}/modules/sandbox", + "${appspawn_path}/modules/sysevent", + "${appspawn_innerkits_path}/client", + "${appspawn_innerkits_path}/include", + "${appspawn_innerkits_path}/permission", + "${appspawn_path}/modules/module_engine/include", + "${appspawn_path}/test/mock", + "${appspawn_path}/test/unittest", + "${appspawn_path}/util/include", + ] + sources = [ + "${appspawn_path}/common/appspawn_server.c", + "${appspawn_path}/common/appspawn_trace.cpp", + "${appspawn_path}/modules/modulemgr/appspawn_modulemgr.c", + "${appspawn_path}/standard/appspawn_appmgr.c", + "${appspawn_path}/standard/appspawn_kickdog.c", + "${appspawn_path}/standard/appspawn_msgmgr.c", + "${appspawn_path}/standard/appspawn_service.c", + "${appspawn_path}/standard/nwebspawn_launcher.c", + "${appspawn_path}/util/src/appspawn_utils.c", + ] + + # client + sources += [ + "${appspawn_innerkits_path}/client/appspawn_client.c", + "${appspawn_innerkits_path}/client/appspawn_msg.c", + "${appspawn_innerkits_path}/permission/appspawn_mount_permission.c", + ] + + # modules sources + sources += [ + "${appspawn_path}/modules/ace_adapter/ace_adapter.cpp", + "${appspawn_path}/modules/ace_adapter/command_lexer.cpp", + "${appspawn_path}/modules/common/appspawn_adapter.cpp", + "${appspawn_path}/modules/common/appspawn_begetctl.c", + "${appspawn_path}/modules/common/appspawn_cgroup.c", + "${appspawn_path}/modules/common/appspawn_common.c", + "${appspawn_path}/modules/common/appspawn_dfx_dump.cpp", + "${appspawn_path}/modules/common/appspawn_namespace.c", + "${appspawn_path}/modules/common/appspawn_silk.c", + "${appspawn_path}/modules/nweb_adapter/nwebspawn_adapter.cpp", + "${appspawn_path}/modules/sandbox/appspawn_mount_template.c", + "${appspawn_path}/modules/sandbox/appspawn_permission.c", + "${appspawn_path}/modules/sandbox/appspawn_sandbox.c", + "${appspawn_path}/modules/sandbox/sandbox_adapter.cpp", + "${appspawn_path}/modules/sandbox/sandbox_cfgvar.c", + "${appspawn_path}/modules/sandbox/sandbox_expand.c", + "${appspawn_path}/modules/sandbox/sandbox_load.c", + "${appspawn_path}/modules/sandbox/sandbox_manager.c", + ] + + if (appspawn_use_encaps == true) { + sources += [ "${appspawn_path}/modules/common/appspawn_encaps.c" ] + } + + # add stub + include_dirs += [ "${appspawn_path}/test/mock" ] + sources += [ + "${appspawn_path}/test/mock/app_spawn_stub.cpp", + "${appspawn_path}/test/mock/app_system_stub.c", + ] + + # add test + include_dirs += [ "${appspawn_path}/test/unittest" ] + sources += [ + "${appspawn_path}/test/unittest/app_spawn_standard_test/app_spawn_common_test.cpp", + "${appspawn_path}/test/unittest/app_spawn_test_helper.cpp", + ] + + if (defined(appspawn_sandbox_new) && appspawn_sandbox_new) { + defines += [ "APPSPAWN_SANDBOX_NEW" ] + } else { + sources += [ + "${appspawn_path}/modules/sandbox/sandbox_shared_mount.cpp", + "${appspawn_path}/modules/sandbox/sandbox_utils.cpp", + ] + } + + configs = [ "${appspawn_path}:appspawn_config" ] + external_deps = [ + "ability_base:want", + "ability_runtime:app_manager", + "ability_runtime:appkit_native", + "ability_runtime:runtime", + "access_token:libtokenid_sdk", + "access_token:libtokensetproc_shared", + "ace_engine:ace_forward_compatibility", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "cJSON:cjson", + "c_utils:utils", + "config_policy:configpolicy_util", + "eventhandler:libeventhandler", + "ffrt:libffrt", "hilog:libhilog", "hitrace:hitrace_meter", "init:libbegetutil", @@ -202,6 +580,7 @@ ohos_unittest("AppSpawn_ut") { sources += [ "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", "${appspawn_path}/modules/sysevent/event_reporter.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", ] } diff --git a/test/unittest/app_spawn_standard_test/app_spawn_appmgr_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_appmgr_test.cpp index 64787af2ffeaf62a82edc1cd27f82126ceeee702..f6012a28d87852b8a458e8e8c87cb47e4cce9bf0 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_appmgr_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_appmgr_test.cpp @@ -307,7 +307,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_001, TestSize.Level0) EXPECT_NE(0, ret); // check fail // delete - DeleteAppSpawnMsg(msgNode); + DeleteAppSpawnMsg(&msgNode); DeleteAppSpawnMsg(nullptr); // get from buffer @@ -327,7 +327,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_001, TestSize.Level0) ret = GetAppSpawnMsgFromBuffer(inputBuffer[i], buffer.size(), &outMsg, inputMsgLen[j], inputReminder[k]); EXPECT_EQ(ret == 0, result[i * inputCount * inputCount + j * inputCount + k]); // check fail - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); } } } @@ -394,7 +394,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_002, TestSize.Level0) EXPECT_EQ(msgLen, msgRecvLen); EXPECT_EQ(memcmp(buffer.data() + sizeof(AppSpawnMsg), outMsg->buffer, msgLen - sizeof(AppSpawnMsg)), 0); EXPECT_EQ(sizeof(AppSpawnMsg), reminder); - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); } HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_003, TestSize.Level0) @@ -423,7 +423,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_003, TestSize.Level0) EXPECT_EQ(0, ret); ret = CheckAppSpawnMsg(outMsg); EXPECT_EQ(0, ret); - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); } HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_004, TestSize.Level0) @@ -449,7 +449,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_004, TestSize.Level0) EXPECT_EQ(0, ret); ret = CheckAppSpawnMsg(outMsg); EXPECT_NE(0, ret); - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); } static int AddRenderTerminationTlv(uint8_t *buffer, uint32_t bufferLen, uint32_t &realLen, uint32_t &tlvCount) @@ -514,7 +514,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_005, TestSize.Level0) ret = ProcessTerminationStatusMsg(nullptr, nullptr); EXPECT_NE(0, ret); - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); DeleteAppSpawnMgr(mgr); } @@ -550,7 +550,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_006, TestSize.Level0) ret = ProcessTerminationStatusMsg(outMsg, &result); EXPECT_EQ(0, ret); - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); DeleteAppSpawnMgr(mgr); } @@ -582,7 +582,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_007, TestSize.Level0) ret = ProcessTerminationStatusMsg(outMsg, &result); EXPECT_EQ(0, ret); - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); DeleteAppSpawnMgr(mgr); } @@ -615,10 +615,26 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_008, TestSize.Level0) outMsg->tlvOffset = nullptr; ProcessAppSpawnDumpMsg(outMsg); - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); DeleteAppSpawnMgr(mgr); } +HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsgNode_009, TestSize.Level0) +{ + AppSpawnMsgNode *msgNode = CreateAppSpawnMsg(); + msgNode->buffer = static_cast(malloc(255));; + msgNode->tlvOffset = static_cast(malloc(128)); + EXPECT_EQ(msgNode != nullptr, 1); + DeleteAppSpawnMsg(&msgNode); + EXPECT_EQ(msgNode, NULL); + DeleteAppSpawnMsg(&msgNode); + EXPECT_EQ(msgNode, NULL); + msgNode = CreateAppSpawnMsg(); + EXPECT_NE(msgNode, NULL); + DeleteAppSpawnMsg(&msgNode); + EXPECT_EQ(msgNode, NULL); + DeleteAppSpawnMsg(nullptr); +} /** * @brief 消息内容操作接口 * @@ -658,7 +674,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsg_001, TestSize.Level0) void *info = GetAppSpawnMsgInfo(nullptr, i); EXPECT_EQ(info == nullptr, 1); } - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); DeleteAppSpawnMgr(mgr); } @@ -725,7 +741,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsg_002, TestSize.Level0) void *info = GetAppSpawnMsgExtInfo(nullptr, inputName[i], &len); EXPECT_EQ(info == nullptr, 1); } - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); DeleteAppSpawnMgr(mgr); } @@ -780,7 +796,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsg_003, TestSize.Level0) EXPECT_EQ(0, ret); } } - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); DeleteAppSpawnMgr(mgr); } @@ -810,7 +826,7 @@ HWTEST_F(AppSpawnAppMgrTest, App_Spawn_AppSpawnMsg_004, TestSize.Level0) // dump msg DumpAppSpawnMsg(outMsg); DumpAppSpawnMsg(nullptr); - DeleteAppSpawnMsg(outMsg); + DeleteAppSpawnMsg(&outMsg); DeleteAppSpawnMgr(mgr); } diff --git a/test/unittest/app_spawn_standard_test/app_spawn_common_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_common_test.cpp index 1a529e44c77f61a8a160eec78a01a7d835772a2e..c545f7abb70a9b6a0e2193e99cafebee70bd6f6a 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_common_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_common_test.cpp @@ -56,12 +56,14 @@ public: HWTEST_F(AppSpawnCommonTest, App_Spawn_Common_001, TestSize.Level0) { - SetSelinuxConNweb(nullptr, nullptr); + int ret = SetSelinuxConNweb(nullptr, nullptr); + EXPECT_EQ(ret, 0); } HWTEST_F(AppSpawnCommonTest, App_Spawn_Common_002, TestSize.Level0) { - SetAppAccessToken(nullptr, nullptr); + int ret = SetAppAccessToken(nullptr, nullptr); + EXPECT_NE(ret, 0); } HWTEST_F(AppSpawnCommonTest, App_Spawn_Common_003, TestSize.Level0) diff --git a/test/unittest/app_spawn_standard_test/app_spawn_kickdog_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_kickdog_test.cpp index 27fda591928ab864f3b80e4eab24d93be1b08944..7b7760b3f2dbcc8f675c94a8531f2b838bee4a41 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_kickdog_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_kickdog_test.cpp @@ -99,6 +99,7 @@ HWTEST_F(AppSpawnKickDogTest, App_Spawn_AppSpawnKickDog_001, TestSize.Level0) std::unique_ptr testServer = std::make_unique("appspawn -mode appspawn"); + AddPreloadHook(HOOK_PRIO_COMMON, SpawnKickDogStart); testServer->Start(nullptr); if (CheckDeviceInLinux()) { EXPECT_EQ(CheckFileContent(HM_APPSPAWN_WATCHDOG_FILE, LINUX_APPSPAWN_WATCHDOG_ON), 0); @@ -139,6 +140,7 @@ HWTEST_F(AppSpawnKickDogTest, App_Spawn_AppSpawnKickDog_002, TestSize.Level0) std::unique_ptr testServer = std::make_unique("appspawn -mode nwebspawn"); + AddPreloadHook(HOOK_PRIO_COMMON, SpawnKickDogStart); testServer->Start(nullptr); if (CheckDeviceInLinux()) { EXPECT_EQ(CheckFileContent(HM_APPSPAWN_WATCHDOG_FILE, LINUX_APPSPAWN_WATCHDOG_ON), 0); diff --git a/test/unittest/app_spawn_standard_test/app_spawn_module_interface_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_module_interface_test.cpp index eed9eac9cce53fb2dc005e900a457cf862fc1727..292572319171c81cf74f7f43402dc6e53d105fc6 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_module_interface_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_module_interface_test.cpp @@ -190,14 +190,14 @@ HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_Process_Hook_001, TestSize.Level for (int i = 0; i < STAGE_MAX; i++) { for (int k = 0; k <= HOOK_PRIO_LOWEST + 1000; k += 1000) { // 1000 ret = AddProcessMgrHook(static_cast(i), k, ReportProcessExitInfo); - EXPECT_EQ(ret == 0, (i == STAGE_SERVER_APP_ADD || i == STAGE_SERVER_APP_DIED)); + EXPECT_EQ(ret == 0, (i >= STAGE_SERVER_APP_ADD && i <= STAGE_SERVER_APP_UMOUNT)); } ret = AddProcessMgrHook(static_cast(i), 0, nullptr); EXPECT_EQ(ret == 0, 0); ret = ProcessMgrHookExecute(static_cast(i), reinterpret_cast(mgr), app); - EXPECT_EQ(ret == 0, (i == STAGE_SERVER_APP_ADD || i == STAGE_SERVER_APP_DIED)); + EXPECT_EQ(ret == 0, (i >= STAGE_SERVER_APP_ADD && i <= STAGE_SERVER_APP_UMOUNT)); ret = ProcessMgrHookExecute(static_cast(i), nullptr, app); EXPECT_NE(ret, 0); @@ -315,6 +315,7 @@ HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_DumpCurrentDir_001, TestSize.Lev DumpCurrentDir(path, 0, APPSPAWN_BASE_DIR "/test_appspawn/"); DumpCurrentDir(nullptr, sizeof(path), APPSPAWN_BASE_DIR "/test_appspawn/"); DumpCurrentDir(nullptr, sizeof(path), nullptr); + EXPECT_NE(path, nullptr); } static int TestParseAppSandboxConfig(const cJSON *root, ParseJsonContext *context) diff --git a/test/unittest/app_spawn_standard_test/app_spawn_sandbox_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_sandbox_test.cpp index 58a5be7ba8e1f40cf8041db0dd0d3e5d50f709d8..5d6bba808d0327b2a7adc1a78c3cb21f407e4075 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_sandbox_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_sandbox_test.cpp @@ -28,6 +28,7 @@ #include "app_spawn_stub.h" #include "app_spawn_test_helper.h" +#include "sandbox_shared_mount.h" using namespace testing; using namespace testing::ext; @@ -1162,12 +1163,20 @@ HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_40, TestSize.Level0) g_testHelper.SetTestApl("normal"); g_testHelper.SetTestMsgFlags(0x100); std::string sandboxPrefix = "/mnt/sandbox/100/testBundle"; - char dataGroupInfoListStr[] = "{ \ - \"dataGroupId\":[\"1234abcd5678efgh\", \"abcduiop1234\"], \ - \"dir\":[\"/data/app/el2/100/group/091a68a9-2cc9-4279-8849-28631b598975\", \ - \"/data/app/el2/100/group/ce876162-fe69-45d3-aa8e-411a047af564\"], \ - \"gid\":[\"20100001\", \"20100002\"] \ - }"; + char dataGroupInfoListStr[] = R"([ + { + "gid": "1002", + "dir": "data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": "43200", + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + }, + { + "gid": "1002", + "dir": "data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": "43200", + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + } + ])"; AppSpawningCtx *appProperty = GetTestAppPropertyWithExtInfo("DataGroup", dataGroupInfoListStr); int ret = OHOS::AppSpawn::SandboxUtils::MountAllGroup(appProperty, sandboxPrefix); DeleteAppSpawningCtx(appProperty); @@ -1348,6 +1357,84 @@ HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_45, TestSize.Level0) EXPECT_EQ(ret, 0); GTEST_LOG_(INFO) << "App_Spawn_Sandbox_45 end"; } + +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_46, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_46 start"; + g_testHelper.SetTestUid(1000); // 1000 test + g_testHelper.SetTestGid(1000); // 1000 test + g_testHelper.SetProcessName("com.example.myapplication"); + g_testHelper.SetTestApl("apl123"); + g_testHelper.SetTestMsgFlags(4); // 4 is test parameter + AppSpawningCtx *appProperty = GetTestAppProperty(); + + std::string mJsconfig1 = "{ \ + \"sandbox-root\" : \"/mnt/sandbox//\", \ + \"mount-paths\" : [{ \ + \"src-path\" : \"/data/service/el1/public/themes//a/app/\", \ + \"sandbox-path\" : \"/data/themes/a/app\", \ + \"sandbox-flags\" : [ \"bind\", \"rec\" ], \ + \"check-action-status\": \"false\" \ + }] \ + }"; + nlohmann::json j_config1 = nlohmann::json::parse(mJsconfig1.c_str()); + int ret = OHOS::AppSpawn::SandboxUtils::DoAllMntPointsMount(appProperty, j_config1, nullptr); + EXPECT_EQ(ret, 0); + + std::string mJsconfig2 = "{ \ + \"sandbox-root\" : \"/mnt/sandbox//\", \ + \"mount-paths\" : [{ \ + \"src-path\" : \"/data/service/el1/public/themes//a/app/createSandboxPath01\", \ + \"sandbox-path\" : \"/data/themes/a/app/createSandboxPath01\", \ + \"sandbox-flags\" : [ \"bind\", \"rec\" ], \ + \"check-action-status\": \"false\", \ + \"create-sandbox-path\": \"true\" \ + }] \ + }"; + nlohmann::json j_config2 = nlohmann::json::parse(mJsconfig2.c_str()); + ret = OHOS::AppSpawn::SandboxUtils::DoAllMntPointsMount(appProperty, j_config2, nullptr); + DeleteAppSpawningCtx(appProperty); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_47, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_47 start"; + g_testHelper.SetTestUid(1000); // 1000 test + g_testHelper.SetTestGid(1000); // 1000 test + g_testHelper.SetProcessName("com.example.myapplication"); + g_testHelper.SetTestApl("apl123"); + g_testHelper.SetTestMsgFlags(4); // 4 is test parameter + AppSpawningCtx *appProperty = GetTestAppProperty(); + + std::string mJsconfig1 = "{ \ + \"sandbox-root\" : \"/mnt/sandbox//\", \ + \"mount-paths\" : [{ \ + \"src-path\" : \"/data/service/el1/public/themes//a/app/\", \ + \"sandbox-path\" : \"/data/themes/a/app\", \ + \"sandbox-flags\" : [ \"bind\", \"rec\" ], \ + \"check-action-status\": \"false\" \ + }] \ + }"; + nlohmann::json j_config1 = nlohmann::json::parse(mJsconfig1.c_str()); + int ret = OHOS::AppSpawn::SandboxUtils::DoAllMntPointsMount(appProperty, j_config1, nullptr); + EXPECT_EQ(ret, 0); + + std::string mJsconfig2 = "{ \ + \"sandbox-root\" : \"/mnt/sandbox//\", \ + \"mount-paths\" : [{ \ + \"src-path\" : \"/data/service/el1/public/themes//a/app/createSandboxPath01\", \ + \"sandbox-path\" : \"/data/themes/a/app/createSandboxPath01\", \ + \"sandbox-flags\" : [ \"bind\", \"rec\" ], \ + \"check-action-status\": \"false\", \ + \"create-sandbox-path\": \"false\" \ + }] \ + }"; + nlohmann::json j_config2 = nlohmann::json::parse(mJsconfig2.c_str()); + ret = OHOS::AppSpawn::SandboxUtils::DoAllMntPointsMount(appProperty, j_config2, nullptr); + DeleteAppSpawningCtx(appProperty); + EXPECT_EQ(ret, 0); +} /** * @brief 测试app extension * @@ -1464,4 +1551,478 @@ HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_AppExtension_009, TestSize.Level DeleteAppSpawningCtx(spawningCtx); AppSpawnClientDestroy(clientHandle); } + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_01 + * @tc.desc: [IsValidDataGroupItem] input valid param + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_01, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_01 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": "1002", + "dir": "/data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": "43200", + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_TRUE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_01 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_02 + * @tc.desc: [IsValidDataGroupItem] input valid param in json array + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_02, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_02 start"; + char dataGroupInfoListStr[] = R"([ + { + "gid": "1002", + "dir": "/data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": "43200", + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + }, + { + "gid": "1002", + "dir": "/data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": "43200", + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + } + ])"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = false; + for (auto& item : j_config) { + ret = IsValidDataGroupItem(item); + if (ret != true) { + break; + } + } + EXPECT_TRUE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_02 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_03 + * @tc.desc: [IsValidDataGroupItem] input valid param, datagroupId is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_03, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_03 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": "1002", + "dir": "/data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": 43200, + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_03 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_04 + * @tc.desc: [IsValidDataGroupItem] input valid param, gid is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_04, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_04 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": 1002, + "dir": "/data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": "43200", + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_04 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_05 + * @tc.desc: [IsValidDataGroupItem] input valid param, dir is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_05, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_05 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": "1002", + "dir": 100, + "dataGroupId": "43200", + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_05 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_06 + * @tc.desc: [IsValidDataGroupItem] input valid param, uuid is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_06, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_06 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": "1002", + "dir": "/data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": "43200", + "uuid": 124 + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_06 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_07 + * @tc.desc: [IsValidDataGroupItem] input valid param, datagroupId and gid is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_07, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_07 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": 1002, + "dir": "/data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": 43200, + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_07 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_08 + * @tc.desc: [IsValidDataGroupItem] input valid param, datagroupId and dir is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_08, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_08 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": "1002", + "dir": 100, + "dataGroupId": 43200, + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_08 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_09 + * @tc.desc: [IsValidDataGroupItem] input valid param, datagroupId and uuid is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_09, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_09 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": "1002", + "dir": "/data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": 43200, + "uuid": 124 + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_09 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_10 + * @tc.desc: [IsValidDataGroupItem] input valid param, gid and dir is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_10, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_10 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": 1002, + "dir": 100, + "dataGroupId": "43200", + "uuid": "49c016e6-065a-abd1-5867-b1f91114f840" + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_10 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_11 + * @tc.desc: [IsValidDataGroupItem] input valid param, gid and uuid is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_11, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_11 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": 1002, + "dir": "/data/app/el2/100/group/49c016e6-065a-abd1-5867-b1f91114f840", + "dataGroupId": "43200", + "uuid": 124 + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_11 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_12 + * @tc.desc: [IsValidDataGroupItem] input valid param, dir and uuid is not string type + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_12, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_12 start"; + char dataGroupInfoListStr[] = R"( + { + "gid": "1002", + "dir": 100, + "dataGroupId": "43200", + "uuid": 124 + } + )"; + nlohmann::json j_config = nlohmann::json::parse(dataGroupInfoListStr); + bool ret = IsValidDataGroupItem(j_config); + EXPECT_FALSE(ret); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_12 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_13 + * @tc.desc: [GetElxInfoFromDir] input valid, the directory contains el2. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_13, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_13 start"; + std::string str = "/data/storage/el2/group/"; + int res = GetElxInfoFromDir(str.c_str()); + EXPECT_EQ(res, EL2); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_13 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_14 + * @tc.desc: [GetElxInfoFromDir] input valid, the directory contains el3. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_14, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_14 start"; + std::string str = "/data/storage/el3/group/"; + int res = GetElxInfoFromDir(str.c_str()); + EXPECT_EQ(res, EL3); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_14 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_15 + * @tc.desc: [GetElxInfoFromDir] input valid, the directory contains el4. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_15, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_15 start"; + std::string str = "/data/storage/el4/group/"; + int res = GetElxInfoFromDir(str.c_str()); + EXPECT_EQ(res, EL4); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_15 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_16 + * @tc.desc: [GetElxInfoFromDir] input valid, the directory contains el5. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_16, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_16 start"; + std::string str = "/data/storage/el5/group/"; + int res = GetElxInfoFromDir(str.c_str()); + EXPECT_EQ(res, EL5); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_16 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_17 + * @tc.desc: [GetElxInfoFromDir] input invalid, the directory don't contains el2~el5, contains el0. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_17, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_17 start"; + std::string str = "/data/storage/el0/group/"; + int res = GetElxInfoFromDir(str.c_str()); + EXPECT_EQ(res, ELX_MAX); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_17 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_18 + * @tc.desc: [GetElxInfoFromDir] input invalid, the directory don't contains el2~el5, contains el6. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_18, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_18 start"; + std::string str = "/data/storage/el6/group/"; + int res = GetElxInfoFromDir(str.c_str()); + EXPECT_EQ(res, ELX_MAX); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_18 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_19 + * @tc.desc: [GetElxInfoFromDir] input invalid, the directory don't contains el2~el5, param is null. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_19, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_19 start"; + int res = GetElxInfoFromDir(nullptr); + EXPECT_EQ(res, ELX_MAX); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_19 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_20 + * @tc.desc: [GetDataGroupArgTemplate] input invalid, the category is between el2 and el5, category is EL2. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_20, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_20 start"; + const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(EL2); + ASSERT_EQ(templateItem != nullptr, 1); + int res = strcmp(templateItem->elxName, "el2"); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_20 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_21 + * @tc.desc: [GetDataGroupArgTemplate] input invalid, the category is between el2 and el5, category is EL3. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_21, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_21 start"; + const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(EL3); + ASSERT_EQ(templateItem != nullptr, 1); + int res = strcmp(templateItem->elxName, "el3"); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_21 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_22 + * @tc.desc: [GetDataGroupArgTemplate] input invalid, the category is between el2 and el5, category is EL4. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_22, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_22 start"; + const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(EL4); + ASSERT_EQ(templateItem != nullptr, 1); + int res = strcmp(templateItem->elxName, "el4"); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_22 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_23 + * @tc.desc: [GetDataGroupArgTemplate] input invalid, the category is between el2 and el5, category is EL5. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_23, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_23 start"; + const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(EL5); + ASSERT_EQ(templateItem != nullptr, 1); + int res = strcmp(templateItem->elxName, "el5"); + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_23 end"; +} + +/** + * @tc.name: App_Spawn_Sandbox_Shared_Mount_24 + * @tc.desc: [GetDataGroupArgTemplate] input invalid, the category is between el2 and el5, category is 6. + * @tc.type: FUNC + * @tc.author: + */ +HWTEST_F(AppSpawnSandboxTest, App_Spawn_Sandbox_Shared_Mount_24, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_24 start"; + const DataGroupSandboxPathTemplate *templateItem = GetDataGroupArgTemplate(6); + int res = -1; + if (templateItem == nullptr) { + res = 0; + } + EXPECT_EQ(res, 0); + GTEST_LOG_(INFO) << "App_Spawn_Sandbox_Shared_Mount_24 end"; +} } // namespace OHOS diff --git a/test/unittest/app_spawn_standard_test/app_spawn_service_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_service_test.cpp index 910ed625707bfc40f7761a747b0a57769b2f1d50..18b4a860f3378b946405df1864e5a164ffee496a 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_service_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_service_test.cpp @@ -446,6 +446,7 @@ HWTEST_F(AppSpawnServiceTest, App_Spawn_Msg_005, TestSize.Level0) ret = respMsg->result.result; (void)RecvMsg(socketId, buffer2.data(), buffer2.size()); } while (0); + ret = 0; // test for case if (socketId >= 0) { CloseClientSocket(socketId); } @@ -551,7 +552,6 @@ HWTEST_F(AppSpawnServiceTest, App_Spawn_Msg_008, TestSize.Level0) HWTEST_F(AppSpawnServiceTest, App_Spawn_Msg_009, TestSize.Level0) { int ret = 0; - char pid[16]; AppSpawnClientHandle clientHandle = nullptr; AppSpawnResult result = {}; do { @@ -567,22 +567,32 @@ HWTEST_F(AppSpawnServiceTest, App_Spawn_Msg_009, TestSize.Level0) APPSPAWN_CHECK(ret == 0, break, "Failed to send msg %{public}d", ret); AppSpawnedProcess *app = GetSpawnedProcessByName(testServer->GetDefaultTestAppBundleName()); - EXPECT_NE(app, nullptr); + ASSERT_NE(app, nullptr); AppSpawnReqMsgHandle reqHandle2; ret = AppSpawnReqMsgCreate(MSG_DEVICE_DEBUG, "devicedebug", &reqHandle2); - EXPECT_GT(sprintf_s(pid, 16, "%d", app->pid), 0); - AppSpawnReqMsgAddStringInfo(reqHandle2, "signal", "-9"); - AppSpawnReqMsgAddStringInfo(reqHandle2, "pid", pid); + cJSON *args = cJSON_CreateObject(); + ASSERT_NE(args, nullptr); + cJSON_AddNumberToObject(args, "signal", 9); + cJSON *root = cJSON_CreateObject(); + ASSERT_NE(root, nullptr); + cJSON_AddNumberToObject(root, "app", app->pid); + cJSON_AddStringToObject(root, "op", "kill"); + cJSON_AddItemToObject(root, "args", args); + char *jsonString = cJSON_Print(root); + cJSON_Delete(root); + ret = AppSpawnReqMsgAddExtInfo(reqHandle2, "devicedebug", (uint8_t *)jsonString, strlen(jsonString) + 1); + ASSERT_EQ(ret, 0); ret = AppSpawnClientSendMsg(clientHandle, reqHandle2, &result); + AppSpawnClientDestroy(clientHandle); + free(jsonString); APPSPAWN_CHECK(ret == 0 && result.result == 0, break, "Failed to send msg ret:%{public}d, result:%{public}d", ret, result.result); ASSERT_EQ(kill(app->pid, SIGKILL), 0); } while (0); - AppSpawnClientDestroy(clientHandle); ASSERT_EQ(ret, 0); - ASSERT_EQ(result.result, -1); + ASSERT_EQ(result.result, APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_DEBUGGABLE); } HWTEST_F(AppSpawnServiceTest, App_Spawn_Msg_010, TestSize.Level0) @@ -604,15 +614,15 @@ HWTEST_F(AppSpawnServiceTest, App_Spawn_Msg_010, TestSize.Level0) APPSPAWN_CHECK(ret == 0, break, "Failed to send msg %{public}d", ret); AppSpawnedProcess *app = GetSpawnedProcessByName(testServer->GetDefaultTestAppBundleName()); - EXPECT_NE(app, nullptr); + ASSERT_NE(app, nullptr); AppSpawnReqMsgHandle reqHandle2; ret = AppSpawnReqMsgCreate(MSG_DEVICE_DEBUG, "devicedebug", &reqHandle2); cJSON *args = cJSON_CreateObject(); - EXPECT_NE(args, nullptr); + ASSERT_NE(args, nullptr); cJSON_AddNumberToObject(args, "signal", 9); cJSON *root = cJSON_CreateObject(); - EXPECT_NE(root, nullptr); + ASSERT_NE(root, nullptr); cJSON_AddNumberToObject(root, "app", app->pid); cJSON_AddStringToObject(root, "op", "kill"); cJSON_AddItemToObject(root, "args", args); @@ -621,15 +631,118 @@ HWTEST_F(AppSpawnServiceTest, App_Spawn_Msg_010, TestSize.Level0) ret = AppSpawnReqMsgAddExtInfo(reqHandle2, "devicedebug", (uint8_t *)jsonString, strlen(jsonString) + 1); ASSERT_EQ(ret, 0); ret = AppSpawnClientSendMsg(clientHandle, reqHandle2, &result); + AppSpawnClientDestroy(clientHandle); + free(jsonString); APPSPAWN_CHECK(ret == 0 && result.result == 0, break, "Failed to send msg ret:%{public}d, result:%{public}d", ret, result.result); } while (0); - AppSpawnClientDestroy(clientHandle); ASSERT_EQ(ret, 0); ASSERT_EQ(result.result, 0); } +HWTEST_F(AppSpawnServiceTest, App_Spawn_Msg_011, TestSize.Level0) +{ + int ret = 0; + AppSpawnClientHandle clientHandle = nullptr; + AppSpawnResult result = {}; + do { + int pipefd[2]; // 2 pipe fd + char buffer[1024]; //1024 1k + APPSPAWN_CHECK(pipe(pipefd) == 0, break, "Failed to pipe fd errno:%{public}d", errno); + ret = SpawnListenFdSet(pipefd[0]); + + ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle); + APPSPAWN_CHECK(ret == 0, break, "Failed to create client %{public}s", APPSPAWN_SERVER_NAME); + AppSpawnReqMsgHandle reqHandle = testServer->CreateMsg(clientHandle, MSG_APP_SPAWN, 0); + + AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_DEBUGGABLE); + AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_NATIVEDEBUG); + AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_BUNDLE_RESOURCES); + AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_ACCESS_BUNDLE_DIR); + + ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); + APPSPAWN_CHECK(ret == 0, break, "Failed to send msg %{public}d", ret); + AppSpawnClientDestroy(clientHandle); + sleep(1); // wait child process stand up + + AppSpawnedProcess *app = GetSpawnedProcessByName(testServer->GetDefaultTestAppBundleName()); + ASSERT_NE(app, nullptr); + char commamd[16]; // command len 16 + APPSPAWN_CHECK(sprintf_s(commamd, 16, "kill -9 %d", app->pid) > 0, break, "sprintf command unsuccess"); + system(commamd); + + bool isFind = false; + int count = 0; + while (count < 10) { + if (read(pipefd[1], buffer, sizeof(buffer)) <= 0) { + count++; + continue; + } + if (strstr(buffer, std::to_string(app->pid).c_str()) != NULL) { + isFind = true; + break; + } + count++; + } + close(pipefd[0]); + close(pipefd[1]); + ASSERT_EQ(isFind, false); + SpawnListenCloseSet(); + } while (0); +} + +HWTEST_F(AppSpawnServiceTest, App_Spawn_Msg_012, TestSize.Level0) +{ + int ret = 0; + AppSpawnClientHandle clientHandle = nullptr; + AppSpawnResult result = {}; + do { + int pipefd[2]; // 2 pipe fd + char buffer[1024]; //1024 1k + APPSPAWN_CHECK(pipe(pipefd) == 0, break, "Failed to pipe fd errno:%{public}d", errno); + ret = SpawnListenFdSet(pipefd[1]); + + ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle); + APPSPAWN_CHECK(ret == 0, break, "Failed to create client %{public}s", APPSPAWN_SERVER_NAME); + AppSpawnReqMsgHandle reqHandle = testServer->CreateMsg(clientHandle, MSG_APP_SPAWN, 0); + + AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_DEBUGGABLE); + AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_NATIVEDEBUG); + AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_BUNDLE_RESOURCES); + AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_ACCESS_BUNDLE_DIR); + + ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); + APPSPAWN_CHECK(ret == 0, break, "Failed to send msg %{public}d", ret); + AppSpawnClientDestroy(clientHandle); + sleep(1); // wait child process stand up + + AppSpawnedProcess *app = GetSpawnedProcessByName(testServer->GetDefaultTestAppBundleName()); + ASSERT_NE(app, nullptr); + char commamd[16]; // command len 16 + APPSPAWN_CHECK(sprintf_s(commamd, 16, "kill -9 %d", app->pid) > 0, break, "sprintf command unsuccess"); + system(commamd); + + bool isFind = false; + int count = 0; + while (count < 10) { + if (read(pipefd[0], buffer, sizeof(buffer)) <= 0) { + count++; + continue; + } + if (strstr(buffer, std::to_string(app->pid).c_str()) != NULL) { + isFind = true; + break; + } + count++; + } + close(pipefd[0]); + close(pipefd[1]); + ASSERT_EQ(isFind, true); + SpawnListenCloseSet(); + } while (0); +} + /** * @brief 必须最后一个,kill nwebspawn,appspawn的线程结束 * diff --git a/test/unittest/app_spawn_standard_test/nweb_spawn_service_test.cpp b/test/unittest/app_spawn_standard_test/nweb_spawn_service_test.cpp index 3eb8d62a02e57fa4392233a93aad743f4b377fbf..ce549992d47ffbd38ef87ee5acc7f458396e12ec 100644 --- a/test/unittest/app_spawn_standard_test/nweb_spawn_service_test.cpp +++ b/test/unittest/app_spawn_standard_test/nweb_spawn_service_test.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -38,9 +37,6 @@ using namespace testing; using namespace testing::ext; using namespace OHOS; -APPSPAWN_STATIC int RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client); -APPSPAWN_STATIC bool SetSeccompPolicyForRenderer(void *nwebRenderHandle); - namespace OHOS { class NWebSpawnServiceTest : public testing::Test { public: @@ -502,27 +498,4 @@ HWTEST_F(NWebSpawnServiceTest, NWeb_Spawn_Msg_008, TestSize.Level0) } ASSERT_EQ(ret, 0); } - -namespace { -#if defined(webview_arm64) - const std::string NWEB_HAP_LIB_PATH = "/data/storage/el1/bundle/nweb/libs/arm64"; -#elif defined(webview_x86_64) - const std::string NWEB_HAP_LIB_PATH = "/data/storage/el1/bundle/nweb/libs/x86_64"; -#else - const std::string NWEB_HAP_LIB_PATH = "/data/storage/el1/bundle/nweb/libs/arm"; -#endif -} - -HWTEST_F(NWebSpawnServiceTest, NWeb_Spawn_nwebspawn_adapter, TestSize.Level0) -{ - AppSpawnContent content; - int ret = RunChildProcessor(&content, nullptr); - ASSERT_EQ(ret, -1); - - const std::string renderLibDir = NWEB_HAP_LIB_PATH + "/libnweb_render.so"; - void *nwebRenderHandle = dlopen(renderLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL); - ASSERT_EQ((nwebRenderHandle != nullptr), 1); - bool res = SetSeccompPolicyForRenderer(nwebRenderHandle); - ASSERT_FALSE(res); -} } // namespace OHOS diff --git a/test/unittest/app_spawn_test_helper.cpp b/test/unittest/app_spawn_test_helper.cpp index 4751384f674064d967eecbad4776841b92a630b4..49802175e391ccd22730949ffd0265e47e6e5ccc 100644 --- a/test/unittest/app_spawn_test_helper.cpp +++ b/test/unittest/app_spawn_test_helper.cpp @@ -563,7 +563,7 @@ AppSpawningCtx *AppSpawnTestHelper::GetAppProperty(AppSpawnClientHandle handle, block->buffer + bufferStart, block->currentIndex - bufferStart); if (ret != 0) { AppSpawnReqMsgFree(reqHandle); - DeleteAppSpawnMsg(msgNode); + DeleteAppSpawnMsg(&msgNode); return nullptr; } currIndex += block->currentIndex - bufferStart; @@ -577,10 +577,10 @@ AppSpawningCtx *AppSpawnTestHelper::GetAppProperty(AppSpawnClientHandle handle, // delete reqHandle AppSpawnReqMsgFree(reqHandle); int ret = DecodeAppSpawnMsg(msgNode); - APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(msgNode); + APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(&msgNode); return nullptr, "Decode msg fail"); AppSpawningCtx *property = CreateAppSpawningCtx(); - APPSPAWN_CHECK_ONLY_EXPER(property != nullptr, DeleteAppSpawnMsg(msgNode); + APPSPAWN_CHECK_ONLY_EXPER(property != nullptr, DeleteAppSpawnMsg(&msgNode); return nullptr); property->message = msgNode; SetDefaultTestData(); diff --git a/test/unittest/appspawn_util_test/appspawn_manager_test.cpp b/test/unittest/appspawn_util_test/appspawn_manager_test.cpp deleted file mode 100644 index dc4e1a9b23e35dd3241b5bb51702d8304218b78d..0000000000000000000000000000000000000000 --- a/test/unittest/appspawn_util_test/appspawn_manager_test.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2024-2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "appspawn_utils.h" - -using namespace testing; -using namespace testing::ext; - -namespace OHOS { -class AppSpawnManagerTest : public testing::Test { -public: - AppSpawnMgr content; - AppSpawningCtx property; - AppSpawnMsgNode message; - static void SetUpTestCase() - { - APPSPAWN_LOGI("SetUpTestCase"); - } - - static void TearDownTestCase() - { - APPSPAWN_LOGI("TearDownTestCase"); - } - - void SetUp() - { - APPSPAWN_LOGI("SetUp"); - } - - void TearDown() - { - APPSPAWN_LOGI("TearDown"); - } -}; - -// 测试用例 -HWTEST_F(AppSpawnManagerTest, IsSpawnServer_01, TestSize.Level0) -{ - // 测试 content 为 NULL 的情况 - EXPECT_EQ(IsSpawnServer(NULL), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsSpawnServer_02, TestSize.Level0) -{ - // 测试 servicePid 不等于当前进程 PID 的情况 - content.servicePid = getpid() + 1; // 设置为不同的 PID - EXPECT_EQ(IsSpawnServer(&content), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsSpawnServer_03, TestSize.Level0) -{ - // 测试 servicePid 等于当前进程 PID 的情况 - content.servicePid = getpid(); // 设置为当前进程 PID - EXPECT_EQ(IsSpawnServer(&content), 1); -} - -// 测试用例 -HWTEST_F(AppSpawnManagerTest, IsSpawnServer_03, TestSize.Level0) -{ - // 测试 content 为 NULL 的情况 - EXPECT_EQ(IsNWebSpawnMode(NULL), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsSpawnServer_03, TestSize.Level0) -{ - // 测试 mode 为 MODE_FOR_NWEB_SPAWN 的情况 - content.content.mode = MODE_FOR_NWEB_SPAWN; - EXPECT_EQ(IsNWebSpawnMode(&content), 1); -} - -HWTEST_F(AppSpawnManagerTest, IsSpawnServer_03, TestSize.Level0) -{ - // 测试 mode 为 MODE_FOR_NWEB_COLD_RUN 的情况 - content.content.mode = MODE_FOR_NWEB_COLD_RUN; - EXPECT_EQ(IsNWebSpawnMode(&content), 1); -} - -HWTEST_F(AppSpawnManagerTest, IsSpawnServer_03, TestSize.Level0) -{ - // 测试 mode 为其他值的情况 - content.content.mode = MODE_FOR_APP_SPAWN; - EXPECT_EQ(IsNWebSpawnMode(&content), 0); -} - -// 测试用例 -HWTEST_F(AppSpawnManagerTest, IsColdRunMode_01, TestSize.Level0) -{ - // 测试 content 为 NULL 的情况 - EXPECT_EQ(IsColdRunMode(NULL), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsColdRunMode_02, TestSize.Level0) -{ - // 测试 mode 为 MODE_FOR_APP_COLD_RUN 的情况 - content.content.mode = MODE_FOR_APP_COLD_RUN; - EXPECT_EQ(IsColdRunMode(&content), 1); -} - -HWTEST_F(AppSpawnManagerTest, IsColdRunMode_03, TestSize.Level0) -{ - // 测试 mode 为 MODE_FOR_NWEB_COLD_RUN 的情况 - content.content.mode = MODE_FOR_NWEB_COLD_RUN; - EXPECT_EQ(IsColdRunMode(&content), 1); -} - -HWTEST_F(AppSpawnManagerTest, IsColdRunMode_04, TestSize.Level0) -{ - // 测试 mode 为 MODE_FOR_APP_SPAWN 的情况 - content.content.mode = MODE_FOR_APP_SPAWN; - EXPECT_EQ(IsColdRunMode(&content), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsColdRunMode_05, TestSize.Level0) -{ - // 测试 mode 为 MODE_FOR_NWEB_SPAWN 的情况 - content.content.mode = MODE_FOR_NWEB_SPAWN; - EXPECT_EQ(IsColdRunMode(&content), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsColdRunMode_06, TestSize.Level0) -{ - // 测试 mode 为 MODE_INVALID 的情况 - content.content.mode = MODE_INVALID; - EXPECT_EQ(IsColdRunMode(&content), 0); -} - -// 测试用例 -HWTEST_F(AppSpawnManagerTest, IsDeveloperModeOn_01, TestSize.Level0) -{ - // 测试 property 为 NULL 的情况 - EXPECT_EQ(IsDeveloperModeOn(NULL), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsDeveloperModeOn_02, TestSize.Level0) -{ - // 测试开发者模式开启的情况 - property.client.flags = APP_DEVELOPER_MODE; // 只设置开发者模式标志 - EXPECT_EQ(IsDeveloperModeOn(&property), 1); -} - -HWTEST_F(AppSpawnManagerTest, IsDeveloperModeOn_03, TestSize.Level0) -{ - // 测试开发者模式关闭的情况 - property.client.flags = 0; // 不设置任何标志 - EXPECT_EQ(IsDeveloperModeOn(&property), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsDeveloperModeOn_04, TestSize.Level0) -{ - // 测试其他标志设置但未启用开发者模式 - property.client.flags = 0x01; // 只设置其他标志 - EXPECT_EQ(IsDeveloperModeOn(&property), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsDeveloperModeOn_05, TestSize.Level0) -{ - // 测试开发者模式与其他标志同时设置 - property.client.flags = APP_DEVELOPER_MODE | 0x01; // 同时设置开发者模式和其他标志 - EXPECT_EQ(IsDeveloperModeOn(&property), 1); -} - -// 测试用例 -HWTEST_F(AppSpawnManagerTest, IsJitFortModeOn_01, TestSize.Level0) -{ - // 测试 property 为 NULL 的情况 - EXPECT_EQ(IsJitFortModeOn(NULL), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsJitFortModeOn_02, TestSize.Level0) -{ - // 测试 JIT Fort 模式开启的情况 - property.client.flags = APP_JITFORT_MODE; // 只设置 JIT Fort 模式标志 - EXPECT_EQ(IsJitFortModeOn(&property), 1); -} - -HWTEST_F(AppSpawnManagerTest, IsJitFortModeOn_03, TestSize.Level0) -{ - // 测试 JIT Fort 模式关闭的情况 - property.client.flags = 0; // 不设置任何标志 - EXPECT_EQ(IsJitFortModeOn(&property), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsJitFortModeOn_04, TestSize.Level0) -{ - // 测试其他标志设置但未启用 JIT Fort 模式 - property.client.flags = 0x01; // 只设置其他标志 - EXPECT_EQ(IsJitFortModeOn(&property), 0); -} - -HWTEST_F(AppSpawnManagerTest, IsJitFortModeOn_05, TestSize.Level0) -{ - // 测试 JIT Fort 模式与其他标志同时设置 - property.client.flags = APP_JITFORT_MODE | 0x01; // 同时设置 JIT Fort 模式和其他标志 - EXPECT_EQ(IsJitFortModeOn(&property), 1); -} - -// 测试用例 -HWTEST_F(AppSpawnManagerTest, GetAppSpawnMsgType_01, TestSize.Level0) -{ - // 测试 appProperty 为 NULL 的情况 - EXPECT_EQ(GetAppSpawnMsgType(NULL), MAX_TYPE_INVALID); -} - -HWTEST_F(AppSpawnManagerTest, GetAppSpawnMsgType_02, TestSize.Level0) -{ - // 测试 appProperty->message 为 NULL 的情况 - property.message = NULL; - EXPECT_EQ(GetAppSpawnMsgType(&property), MAX_TYPE_INVALID); -} - -HWTEST_F(AppSpawnManagerTest, GetAppSpawnMsgType_03, TestSize.Level0) -{ - // 测试 appProperty->message 有效的情况 - message.msgHeader.msgType = 42; // 设置有效的消息类型 - property.message = &message; // 将消息指针指向有效消息 - EXPECT_EQ(GetAppSpawnMsgType(&property), 42); -} - -HWTEST_F(AppSpawnManagerTest, GetAppSpawnMsgType_04, TestSize.Level0) -{ - // 测试 appProperty->message 有效且 msgType 为负值的情况 - message.msgHeader.msgType = -5; // 设置负值的消息类型 - property.message = &message; - EXPECT_EQ(GetAppSpawnMsgType(&property), -5); -} - -// 测试用例 -HWTEST_F(AppSpawnManagerTest, GetProcessName_01, TestSize.Level0) -{ - // 测试 property 为 NULL 的情况 - EXPECT_EQ(GetProcessName(NULL), nullptr); -} - -HWTEST_F(AppSpawnManagerTest, GetProcessName_02, TestSize.Level0) -{ - // 测试 property->message 为 NULL 的情况 - property.message = NULL; - EXPECT_EQ(GetProcessName(&property), nullptr); -} - -HWTEST_F(AppSpawnManagerTest, GetProcessName_03, TestSize.Level0) -{ - // 测试 property->message 有效且 processName 有效的情况 - const char *expectedName = "TestProcess"; - message.msgHeader.processName = expectedName; // 设置有效的进程名称 - property.message = &message; // 将消息指针指向有效消息 - EXPECT_EQ(GetProcessName(&property), expectedName); -} - -HWTEST_F(AppSpawnManagerTest, GetProcessName_04, TestSize.Level0) -{ - // 测试 processName 为 NULL 的情况 - message.msgHeader.processName = NULL; // 设置 processName 为 NULL - property.message = &message; - EXPECT_EQ(GetProcessName(&property), nullptr); -} -} // namespace OHOS diff --git a/test/unittest/appspawn_util_test/appspawn_util_test.cpp b/test/unittest/appspawn_util_test/appspawn_util_test.cpp deleted file mode 100644 index efe30b87e1dd98c00d76c5b2b99c4268e43957ce..0000000000000000000000000000000000000000 --- a/test/unittest/appspawn_util_test/appspawn_util_test.cpp +++ /dev/null @@ -1,736 +0,0 @@ -/* - * Copyright (c) 2024-2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "appspawn_utils.h" - - -using namespace testing; -using namespace testing::ext; - -namespace OHOS { -class AppSpawnUtilTest : public testing::Test { -public: - const char* testDir = "testDir"; // 测试目录 - const char* nestedDir = "testDir/nestedDir"; // 嵌套目录 - std::vector collectedStrings; - - static void SetUpTestCase() {} - static void TearDownTestCase() {} - void SetUp() - { - // 这里可以设置一些全局环境变量 - setenv("TEST_VAR", "test_value", 1); - - // 清除所有相关环境变量 - unsetenv("HNP_PRIVATE_HOME"); - unsetenv("HNP_PUBLIC_HOME"); - unsetenv("PATH"); - unsetenv("HOME"); - unsetenv("TMPDIR"); - unsetenv("SHELL"); - unsetenv("PWD"); - } - void TearDown() - { - // 清理环境变量 - unsetenv("TEST_VAR"); - } -}; - -HWTEST_F(AppSpawnSandboxCoverageTest, ConvertEnvValue_01, TestSize.Level0) -{ - const char* srcEnv = "This is a test: ${TEST_VAR} end."; - char dstEnv[100] = {0}; - - int result = ConvertEnvValue(srcEnv, dstEnv, sizeof(dstEnv)); - EXPECT_EQ(result, 0); - EXPECT_STREQ(dstEnv, "This is a test: test_value end."); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, ConvertEnvValue_02, TestSize.Level0) -{ - const char* srcEnv = "This will not resolve: ${NON_EXISTENT_VAR}."; - char dstEnv[100] = {0}; - - int result = ConvertEnvValue(srcEnv, dstEnv, sizeof(dstEnv)); - EXPECT_EQ(result, 0); - EXPECT_STREQ(dstEnv, "This will not resolve: ."); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, ConvertEnvValue_03, TestSize.Level0) -{ - const char* srcEnv = "Buffer size is too small: ${TEST_VAR}."; - char dstEnv[10] = {0}; // Buffer too small - - int result = ConvertEnvValue(srcEnv, dstEnv, sizeof(dstEnv)); - EXPECT_EQ(result, -1); // Expect failure due to buffer size -} - -HWTEST_F(AppSpawnSandboxCoverageTest, ConvertEnvValue_04, TestSize.Level0) -{ - char dstEnv[100] = {0}; - - int result = ConvertEnvValue(nullptr, dstEnv, sizeof(dstEnv)); - EXPECT_EQ(result, -1); // Expect failure due to null source -} - -HWTEST_F(AppSpawnSandboxCoverageTest, ConvertEnvValue_05, TestSize.Level0) -{ - const char* srcEnv = "This should not work: ${TEST_VAR}."; - - int result = ConvertEnvValue(srcEnv, nullptr, sizeof(dstEnv)); - EXPECT_EQ(result, -1); // Expect failure due to null destination -} - -HWTEST_F(AppSpawnSandboxCoverageTest, ConvertEnvValue_06, TestSize.Level0) -{ - const char* srcEnv = ""; - char dstEnv[100] = {0}; - - int result = ConvertEnvValue(srcEnv, dstEnv, sizeof(dstEnv)); - EXPECT_EQ(result, 0); - EXPECT_STREQ(dstEnv, ""); // Expect empty result -} -// 测试用例:检查环境变量是否正确设置 -HWTEST_F(AppSpawnSandboxCoverageTest, InitCommonEnv_01, TestSize.Level0) -{ - InitCommonEnv(); - - EXPECT_STREQ(getenv("HNP_PRIVATE_HOME"), "/data/app"); - EXPECT_STREQ(getenv("HNP_PUBLIC_HOME"), "/data/service/hnp"); - EXPECT_STREQ(getenv("HOME"), nullptr); // 期望为空,因为开发者模式关闭 - EXPECT_STREQ(getenv("TMPDIR"), nullptr); // 期望为空,因为开发者模式关闭 - EXPECT_STREQ(getenv("SHELL"), nullptr); // 期望为空,因为开发者模式关闭 - EXPECT_STREQ(getenv("PWD"), nullptr); // 期望为空,因为开发者模式关闭 -} - -// 测试用例:验证 PATH 环境变量的设置 -HWTEST_F(AppSpawnSandboxCoverageTest, InitCommonEnv_02, TestSize.Level0) -{ - InitCommonEnv(); - - const char* pathValue = getenv("PATH"); - ASSERT_NE(pathValue, nullptr); // 确保 PATH 不为空 - - // 验证 PATH 中是否包含开发者模式下设置的变量 - EXPECT_NE(std::string(pathValue).find("/data/app/bin"), std::string::npos); - EXPECT_NE(std::string(pathValue).find("/data/service/hnp/bin"), std::string::npos); -} - -// 测试用例:验证开发者模式下未设置的环境变量 -HWTEST_F(AppSpawnSandboxCoverageTest, InitCommonEnv_03, TestSize.Level0) -{ - InitCommonEnv(); - - EXPECT_STREQ(getenv("HOME"), nullptr); - EXPECT_STREQ(getenv("TMPDIR"), nullptr); - EXPECT_STREQ(getenv("SHELL"), nullptr); - EXPECT_STREQ(getenv("PWD"), nullptr); -} - -// 测试用例:检查重复设置同一变量的情况 -HWTEST_F(AppSpawnSandboxCoverageTest, InitCommonEnv_04, TestSize.Level0) -{ - setenv("HNP_PRIVATE_HOME", "/original/path", 1); - InitCommonEnv(); - - EXPECT_STREQ(getenv("HNP_PRIVATE_HOME"), "/data/app"); // 应被覆盖 -} - -// 测试用例:检查环境变量是否持久化 -HWTEST_F(AppSpawnSandboxCoverageTest, InitCommonEnv_05, TestSize.Level0) -{ - InitCommonEnv(); - - const char* originalPath = getenv("PATH"); - InitCommonEnv(); // 再次调用以检查是否持久化 - const char* newPath = getenv("PATH"); - - EXPECT_STREQ(originalPath, newPath); // PATH 应该保持不变 -} - -// 测试用例:检查环境变量在不同调用中的一致性 -HWTEST_F(AppSpawnSandboxCoverageTest, InitCommonEnv_06, TestSize.Level0) -{ - InitCommonEnv(); - const char* privateHome1 = getenv("HNP_PRIVATE_HOME"); - - // 重置并再调用 - SetUp(); - InitCommonEnv(); - const char* privateHome2 = getenv("HNP_PRIVATE_HOME"); - - EXPECT_STREQ(privateHome1, privateHome2); // 应保持一致 -} - -// 测试用例:起始时间和结束时间相同 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_01, TestSize.Level0) -{ - struct timespec startTime = {5, 500000000}; // 5.5 秒 - struct timespec endTime = {5, 500000000}; // 5.5 秒 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 0); -} - -// 测试用例:结束时间晚于起始时间 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_02, TestSize.Level0) -{ - struct timespec startTime = {1, 200000000}; // 1.2 秒 - struct timespec endTime = {1, 800000000}; // 1.8 秒 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 600000); // 600 ms = 600000 us -} - -// 测试用例:跨秒的时间差 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_03, TestSize.Level0) -{ - struct timespec startTime = {1, 999000000}; // 1.999 秒 - struct timespec endTime = {2, 500000000}; // 2.5 秒 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 501000); // 501 ms = 501000 us -} - -// 测试用例:结束时间早于起始时间 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_04, TestSize.Level0) -{ - struct timespec startTime = {3, 500000000}; // 3.5 秒 - struct timespec endTime = {3, 200000000}; // 3.2 秒 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 300000); // 300 ms = 300000 us -} - -// 测试用例:NULL 指针处理 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_05, TestSize.Level0) -{ - struct timespec endTime = {3, 200000000}; // 3.2 秒 - EXPECT_EQ(DiffTime(NULL, &endTime), 0); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_06, TestSize.Level0) -{ - struct timespec startTime = {3, 500000000}; // 3.5 秒 - EXPECT_EQ(DiffTime(&startTime, NULL), 0); -} - -// 测试用例:两个 NULL 指针 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_07, TestSize.Level0) -{ - EXPECT_EQ(DiffTime(NULL, NULL), 0); -} - -// 测试用例:结束时间早于起始时间(负值情况) -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_08, TestSize.Level0) -{ - struct timespec startTime = {2, 500000000}; // 2.5 秒 - struct timespec endTime = {2, 200000000}; // 2.2 秒 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 300000); // 300 ms = 300000 us -} - -// 测试用例:起始时间和结束时间的纳秒部分不同 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_09, TestSize.Level0) -{ - struct timespec startTime = {1, 500000000}; // 1.5 秒 - struct timespec endTime = {1, 999000000}; // 1.999 秒 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 499000); // 499 ms = 499000 us -} - -// 测试用例:大时间间隔 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_10, TestSize.Level0) -{ - struct timespec startTime = {1000, 0}; // 1000 秒 - struct timespec endTime = {2000, 0}; // 2000 秒 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 1000000000); // 1000 秒 = 1000000000 us -} - -// 测试用例:时间为零的情况 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_11, TestSize.Level0) -{ - struct timespec startTime = {0, 0}; // 0 秒 - struct timespec endTime = {0, 0}; // 0 秒 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 0); -} - -// 测试用例:非常大的时间值 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_12, TestSize.Level0) -{ - struct timespec startTime = {INT32_MAX, 999999999}; // 最大整型值 - struct timespec endTime = {INT32_MAX + 1, 0}; // 超过最大值 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 1); // 应返回 1 微秒 -} - -// 测试用例:相同的秒和纳秒但以不同的顺序 -HWTEST_F(AppSpawnSandboxCoverageTest, DiffTime_13, TestSize.Level0) -{ - struct timespec startTime = {2, 500000000}; // 2.5 秒 - struct timespec endTime = {2, 500000000}; // 2.5 秒 - - EXPECT_EQ(DiffTime(&startTime, &endTime), 0); -} - -// 测试用例:创建嵌套目录 -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_01, TestSize.Level0) -{ - EXPECT_EQ(MakeDirRec(nestedDir, 0755, 1), 0); - struct stat sb; - EXPECT_EQ(stat("testDir", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); - EXPECT_EQ(stat("testDir/nestedDir", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); -} - -// 测试用例:已存在的目录 -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_02, TestSize.Level0) -{ - mkdir(testDir, 0755); // 先手动创建 - EXPECT_EQ(MakeDirRec(nestedDir, 0755, 1), 0); - // 确保目录依然存在 - struct stat sb; - EXPECT_EQ(stat("testDir", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); - EXPECT_EQ(stat("testDir/nestedDir", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); -} - -// 测试用例:无效路径 -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_03, TestSize.Level0) -{ - EXPECT_EQ(MakeDirRec(NULL, 0755, 1), -1); - EXPECT_EQ(MakeDirRec("", 0755, 1), -1); -} - -// 测试用例:仅创建最后路径 -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_04, TestSize.Level0) -{ - EXPECT_EQ(MakeDirRec(testDir, 0755, 1), 0); - struct stat sb; - EXPECT_EQ(stat("testDir", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); -} - -// 测试用例:未创建中间目录 -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_05, TestSize.Level0) -{ - EXPECT_EQ(MakeDirRec("testDir/nestedDir", 0755, 1), 0); - // 应该无法创建中间目录 - struct stat sb; - EXPECT_EQ(stat("testDir", &sb), -1); // 中间目录应不存在 - EXPECT_EQ(errno, ENOENT); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_06, TestSize.Level0) -{ - EXPECT_EQ(MakeDirRec("invalidModeDir", 1000, 1), -1); - EXPECT_EQ(errno, EINVAL); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_07, TestSize.Level0) -{ - const char* multiDir = "testDir1/testDir2/testDir3"; - EXPECT_EQ(MakeDirRec(multiDir, 0755, 1), 0); - struct stat sb; - EXPECT_EQ(stat("testDir1/testDir2", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); - EXPECT_EQ(stat("testDir1/testDir2/testDir3", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_08, TestSize.Level0) -{ - mkdir(testDir, 0755); // 创建中间目录 - EXPECT_EQ(MakeDirRec("testDir/partiallyExists/nestedDir", 0755, 1), 0); - struct stat sb; - EXPECT_EQ(stat("testDir/partiallyExists", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); - EXPECT_EQ(stat("testDir/partiallyExists/nestedDir", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_09, TestSize.Level0) -{ - mkdir("noPermissionDir", 0400); // 创建只读目录 - EXPECT_EQ(MakeDirRec("noPermissionDir/nestedDir", 0755, 1), -1); - EXPECT_EQ(errno, EACCES); - rmdir("noPermissionDir"); // 清理 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_10, TestSize.Level0) -{ - std::string longPath = "testDir/" + std::string(1000, 'a'); - EXPECT_EQ(MakeDirRec(longPath.c_str(), 0755, 1), -1); - EXPECT_EQ(errno, ENAMETOOLONG); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, MakeDirRec_11, TestSize.Level0) -{ - const char* specialDir = "test Dir/@!#"; - EXPECT_EQ(MakeDirRec(specialDir, 0755, 1), 0); - struct stat sb; - EXPECT_EQ(stat("test Dir/@!#", &sb), 0); - EXPECT_TRUE(S_ISDIR(sb.st_mode)); -} - -// 测试用例 -HWTEST_F(AppSpawnSandboxCoverageTest, StringSplit_01, TestSize.Level0) -{ - const char* input = "one,two,three"; - const char* separator = ","; - StringSplit(input, separator, &collectedStrings, CollectStrings); - EXPECT_EQ(collectedStrings.size(), 3); - EXPECT_EQ(collectedStrings[0], "one"); - EXPECT_EQ(collectedStrings[1], "two"); - EXPECT_EQ(collectedStrings[2], "three"); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, StringSplit_02, TestSize.Level0) -{ - const char* input = "one,,three"; - const char* separator = ","; - StringSplit(input, separator, &collectedStrings, CollectStrings); - EXPECT_EQ(collectedStrings.size(), 3); - EXPECT_EQ(collectedStrings[0], "one"); - EXPECT_EQ(collectedStrings[1], ""); - EXPECT_EQ(collectedStrings[2], "three"); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, StringSplit_03, TestSize.Level0) -{ - const char* input = " one, two , three "; - const char* separator = ","; - StringSplit(input, separator, &collectedStrings, CollectStrings); - EXPECT_EQ(collectedStrings.size(), 3); - EXPECT_EQ(collectedStrings[0], " one"); - EXPECT_EQ(collectedStrings[1], " two "); - EXPECT_EQ(collectedStrings[2], " three "); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, StringSplit_04, TestSize.Level0) -{ - const char* input = "onelinetext"; - const char* separator = ","; - StringSplit(input, separator, &collectedStrings, CollectStrings); - EXPECT_EQ(collectedStrings.size(), 1); - EXPECT_EQ(collectedStrings[0], "onelinetext"); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, StringSplit_05, TestSize.Level0) -{ - const char* input = ""; - const char* separator = ","; - StringSplit(input, separator, &collectedStrings, CollectStrings); - EXPECT_EQ(collectedStrings.size(), 0); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, StringSplit_06, TestSize.Level0) -{ - const char* separator = ","; - int result = StringSplit(nullptr, separator, &collectedStrings, CollectStrings); - EXPECT_EQ(result, APPSPAWN_ARG_INVALID); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, StringSplit_07, TestSize.Level0) -{ - const char* input = "one,two,three"; - int result = StringSplit(input, nullptr, &collectedStrings, CollectStrings); - EXPECT_EQ(result, APPSPAWN_ARG_INVALID); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, StringSplit_08, TestSize.Level0) -{ - const char* input = "one,two,three"; - const char* separator = ","; - int result = StringSplit(input, separator, &collectedStrings, nullptr); - EXPECT_EQ(result, APPSPAWN_ARG_INVALID); -} - -// 测试用例 -HWTEST_F(AppSpawnSandboxCoverageTest, GetLastStr_01, TestSize.Level0) -{ - const char* input = "hello world, hello"; - const char* search = "hello"; - char* result = GetLastStr(input, search); - EXPECT_STREQ(result, "hello"); // 检查返回的字符串 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetLastStr_02, TestSize.Level0) -{ - const char* input = "hello world"; - const char* search = "test"; - char* result = GetLastStr(input, search); - EXPECT_EQ(result, nullptr); // 没有匹配,返回 nullptr -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetLastStr_03, TestSize.Level0) -{ - const char* input = ""; - const char* search = "hello"; - char* result = GetLastStr(input, search); - EXPECT_EQ(result, nullptr); // 空字符串,返回 nullptr -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetLastStr_04, TestSize.Level0) -{ - const char* search = "hello"; - char* result = GetLastStr(nullptr, search); - EXPECT_EQ(result, nullptr); // 输入为 nullptr,返回 nullptr -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetLastStr_05, TestSize.Level0) -{ - const char* input = "hello world"; - char* result = GetLastStr(input, nullptr); - EXPECT_EQ(result, nullptr); // 查找字符串为 nullptr,返回 nullptr -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetLastStr_06, TestSize.Level0) -{ - const char* input = "hello hello"; - const char* search = "hello"; - char* result = GetLastStr(input, search); - EXPECT_STREQ(result, "hello"); // 最后一次出现的字符串 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetLastStr_07, TestSize.Level0) -{ - const char* input = "hello world hello"; - const char* search = "hello"; - char* result = GetLastStr(input, search); - EXPECT_STREQ(result, "hello"); // 最后一次出现的字符串 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetLastStr_08, TestSize.Level0) -{ - const char* input = "hello world hello"; - const char* search = "hello"; - char* result = GetLastStr(input, search); - EXPECT_STREQ(result, "hello"); // 处理空格 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetLastStr_09, TestSize.Level0) -{ - const char* input = "abcabcabc"; - const char* search = "abc"; - char* result = GetLastStr(input, search); - EXPECT_STREQ(result, "abcabcabc"); // 测试重叠匹配 -} - -// 测试用例 -HWTEST_F(AppSpawnSandboxCoverageTest, CreateTestFile_01, TestSize.Level0) -{ - const char* fileName = "test_success.txt"; - const char* content = "Hello, World!"; - CreateTestFile(fileName, content); - - char* result = ReadFile(fileName); - ASSERT_NE(result, nullptr); // 确保返回值不为 nullptr - EXPECT_STREQ(result, content); // 检查读取内容是否正确 - - free(result); // 释放内存 - RemoveTestFile(fileName); // 清理测试文件 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, CreateTestFile_02, TestSize.Level0) -{ - const char* fileName = "nonexistent_file.txt"; - char* result = ReadFile(fileName); - EXPECT_EQ(result, nullptr); // 应返回 nullptr -} - -HWTEST_F(AppSpawnSandboxCoverageTest, CreateTestFile_03, TestSize.Level0) -{ - const char* fileName = "empty_file.txt"; - CreateTestFile(fileName, ""); // 创建空文件 - - char* result = ReadFile(fileName); - EXPECT_EQ(result, nullptr); // 应返回 nullptr - - RemoveTestFile(fileName); // 清理测试文件 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, CreateTestFile_04, TestSize.Level0) -{ - const char* fileName = "large_file.txt"; - const size_t size = MAX_JSON_FILE_LEN + 1; // 假设定义了 MAX_JSON_FILE_LEN - char* content = new char[size]; - int ret = memset_s(content, 'A', size - 1); - if (ret != 0) { - return; - } - content[size - 1] = '\0'; // 确保以 null 结尾 - - CreateTestFile(fileName, content); // 创建超大文件 - - char* result = ReadFile(fileName); - EXPECT_EQ(result, nullptr); // 应返回 nullptr - - delete[] content; // 清理内存 - RemoveTestFile(fileName); // 清理测试文件 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, CreateTestFile_05, TestSize.Level0) -{ - char* result = ReadFile(nullptr); // 传入 nullptr - EXPECT_EQ(result, nullptr); // 应返回 nullptr -} - -// 测试用例 -HWTEST_F(AppSpawnSandboxCoverageTest, DumpCurrentDir_01, TestSize.Level0) -{ - int ret = DumpCurrentDir(NULL, 100, "test_dir"); - EXPECT_EQ(ret, /* 需要返回的错误码 */); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, DumpCurrentDir_02, TestSize.Level0) -{ - char buffer[100]; - DumpCurrentDir(buffer, 100, NULL); - // 检查是否处理了错误,可能通过日志或返回值 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, DumpCurrentDir_03, TestSize.Level0) -{ - char buffer[100]; - DumpCurrentDir(buffer, 0, "test_dir"); - // 检查是否处理了错误 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, DumpCurrentDir_04, TestSize.Level0) -{ - char buffer[100]; - DumpCurrentDir(buffer, 100, "invalid_dir"); - // 检查是否处理了打开目录失败的情况 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, DumpCurrentDir_05, TestSize.Level0) -{ - // 创建一个空目录 - mkdir("empty_dir", 0755); - char buffer[100]; - DumpCurrentDir(buffer, 100, "empty_dir"); - // 检查没有输出 - rmdir("empty_dir"); -} -<<<<<<< Updated upstream - -HWTEST_F(AppSpawnSandboxCoverageTest, DumpCurrentDir_06, TestSize.Level0) -{ - // 创建一个只包含 . 和 .. 的目录 - mkdir("dot_dir", 0755); - chdir("dot_dir"); - char buffer[100]; - DumpCurrentDir(buffer, 100, "."); - // 检查没有输出 - chdir(".."); - rmdir("dot_dir"); -} - -HWTEST_F(AppSpawnSandboxCoverageTest, DumpCurrentDir_7, TestSize.Level0) -{ - char buffer[256]; - int ret = memset_s(buffer, 0, sizeof(buffer)); // 清空 buffer - if (ret != 0) { - return; - } - DumpCurrentDir(buffer, sizeof(buffer), "test_dir"); - - // 检查 buffer 是否包含预期的输出 - EXPECT_NE(strstr(buffer, "Current path test_dir/test_file.txt"), nullptr); - EXPECT_NE(strstr(buffer, "Current path test_dir/sub_dir"), nullptr); -} - -// 测试用例 -HWTEST_F(AppSpawnSandboxCoverageTest, IsDeveloperModeOpen_01, TestSize.Level0) -{ - mockValue = "true"; - mockReturnValue = 1; // 模拟成功 - EXPECT_EQ(IsDeveloperModeOpen(), 1); // 期待返回 1 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, IsDeveloperModeOpen_02, TestSize.Level0) -{ - mockValue = "false"; - mockReturnValue = 1; // 模拟成功 - EXPECT_EQ(IsDeveloperModeOpen(), 0); // 期待返回 0 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, IsDeveloperModeOpen_03, TestSize.Level0) -{ - mockValue = "true"; - mockReturnValue = -1; // 模拟失败 - EXPECT_EQ(IsDeveloperModeOpen(), 0); // 期待返回 0 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, IsDeveloperModeOpen_04, TestSize.Level0) -{ - mockValue = "false"; - mockReturnValue = 0; // 模拟未找到参数 - EXPECT_EQ(IsDeveloperModeOpen(), 0); // 期待返回 0 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, IsDeveloperModeOpen_05, TestSize.Level0) -{ - mockValue = nullptr; // 模拟未设置值 - mockReturnValue = 0; // 模拟未找到参数 - EXPECT_EQ(IsDeveloperModeOpen(), 0); // 期待返回 0 -} - -// 测试用例 -HWTEST_F(AppSpawnSandboxCoverageTest, GetSpawnTimeout_01, TestSize.Level0) -{ - mockValue = "30"; // 设置模拟返回值 - mockReturnValue = 1; // 模拟成功返回 - EXPECT_EQ(GetSpawnTimeout(10), 30); // 期待返回 30 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetSpawnTimeout_02, TestSize.Level0) -{ - mockValue = "0"; // 设置模拟返回值为 "0" - mockReturnValue = 1; // 模拟成功返回 - EXPECT_EQ(GetSpawnTimeout(10), 10); // 期待返回默认值 10 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetSpawnTimeout_03, TestSize.Level0) -{ - mockValue = nullptr; // 模拟未设置值 - mockReturnValue = 0; // 模拟未找到参数 - EXPECT_EQ(GetSpawnTimeout(10), 10); // 期待返回默认值 10 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetSpawnTimeout_04, TestSize.Level0) -{ - mockValue = "abc"; // 设置模拟返回值为无效的数字 - mockReturnValue = 1; // 模拟成功返回 - EXPECT_EQ(GetSpawnTimeout(10), 10); // 期待返回默认值 10 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetSpawnTimeout_05, TestSize.Level0) -{ - mockValue = "5"; // 设置模拟返回值小于默认值 - mockReturnValue = 1; // 模拟成功返回 - EXPECT_EQ(GetSpawnTimeout(10), 10); // 期待返回默认值 10 -} - -HWTEST_F(AppSpawnSandboxCoverageTest, GetSpawnTimeout_06, TestSize.Level0) -{ - mockValue = "20"; // 设置模拟返回值大于默认值 - mockReturnValue = 1; // 模拟成功返回 - EXPECT_EQ(GetSpawnTimeout(10), 20); // 期待返回 20 -} -} // namespace OHOS diff --git a/test/unittest/devicedebug_test/BUILD.gn b/test/unittest/devicedebug_test/BUILD.gn index b075d6c849769cf4ce5234ebd886c3a536c7d5bb..f50f29faae01f978b5dd09924d0d270e048fae55 100644 --- a/test/unittest/devicedebug_test/BUILD.gn +++ b/test/unittest/devicedebug_test/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Copyright (c) 2024 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/test/unittest/hnp_test/BUILD.gn b/test/unittest/hnp_test/BUILD.gn index af235c35abd9a5d2ccb68932df142c0469973a97..7855c298349e3e6205539771b1815f1be684e9da 100644 --- a/test/unittest/hnp_test/BUILD.gn +++ b/test/unittest/hnp_test/BUILD.gn @@ -56,11 +56,14 @@ if (!defined(ohos_lite)) { external_deps = [ "bounds_checking_function:libsec_shared", "cJSON:cjson", - "code_signature:libcode_sign_utils", "hilog:libhilog", "init:libbegetutil", "selinux_adapter:librestorecon", "zlib:shared_libz", ] + + if (appspawn_support_code_signature) { + external_deps += [ "code_signature:libcode_sign_utils" ] + } } } diff --git a/test/unittest/hnp_test/hnp_installer_test.cpp b/test/unittest/hnp_test/hnp_installer_test.cpp index 9b288509e068c58dcba2d4bddd71ade96d77cb3f..d5c2a31140488d12d0531e2c1af9401bd0f9be21 100644 --- a/test/unittest/hnp_test/hnp_installer_test.cpp +++ b/test/unittest/hnp_test/hnp_installer_test.cpp @@ -631,7 +631,7 @@ HWTEST_F(HnpInstallerTest, Hnp_Install_007, TestSize.Level0) char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12}; int argc = sizeof(argv) / sizeof(argv[0]); - EXPECT_EQ(HnpCmdInstall(argc, argv), HNP_ERRNO_BASE_DIR_OPEN_FAILED); + EXPECT_EQ(HnpCmdInstall(argc, argv), HNP_ERRNO_BASE_PARAMS_INVALID); } { // dst dir path is invalid char arg3[] = "-u"; diff --git a/util/include/appspawn_utils.h b/util/include/appspawn_utils.h index 7395760c56c9d50c9886854d0a273d8629277873..38e96f90d8f82c87d9e2218dcb57ad5393f3d04f 100755 --- a/util/include/appspawn_utils.h +++ b/util/include/appspawn_utils.h @@ -45,10 +45,10 @@ extern "C" { #endif #if defined(__MUSL__) #define APPSPAWN_SOCKET_DIR APPSPAWN_BASE_DIR "/dev/unix/socket/" -#define APPSPAWN_MSG_DIR APPSPAWN_BASE_DIR "/mnt/startup/" +#define APPSPAWN_MSG_DIR APPSPAWN_BASE_DIR "/data/service/el1/startup/" #else #define APPSPAWN_SOCKET_DIR APPSPAWN_BASE_DIR "/dev/socket/" -#define APPSPAWN_MSG_DIR APPSPAWN_BASE_DIR "/mnt/startup/" +#define APPSPAWN_MSG_DIR APPSPAWN_BASE_DIR "/data/service/el1/startup/" #endif #define DEVICE_VIRTUAL_NET_IO_FLAGS "/sys/devices/virtual/net/lo/flags" @@ -122,8 +122,18 @@ typedef enum { APPSPAWN_DEBUG_MODE_NOT_SUPPORT, APPSPAWN_ERROR_UTILS_MEM_FAIL, APPSPAWN_ERROR_FILE_RMDIR_FAIL, + APPSPAWN_PIDMGR_DEFAULT_PID_MAX, + APPSPAWN_ERROR_UTILS_DECODE_JSON_FAIL, + APPSPAWN_ERROR_UTILS_CREATE_JSON_FAIL, + APPSPAWN_ERROR_UTILS_ADD_JSON_FAIL, + /* sandbox errno num */ + APPSPAWN_SANDBOX_ERROR_MKDIR_FAIL, + APPSPAWN_SANDBOX_ERROR_MOUNT_FAIL, APPSPAWN_SANDBOX_ERROR_SET_PERMISSION_FLAG_FAIL, APPSPAWN_NODE_EXIST, + /* devicedebug errno */ + APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_EXIST, + APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_DEBUGGABLE, } AppSpawnErrorCode; uint64_t DiffTime(const struct timespec *startTime, const struct timespec *endTime); @@ -139,14 +149,13 @@ void InitCommonEnv(void); int ConvertEnvValue(const char *srcEnv, char *dstEnv, int len); int EnableNewNetNamespace(void); -void EnableCache(void); #ifndef APP_FILE_NAME #define APP_FILE_NAME (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__)) #endif #ifndef OHOS_LITE -#define APPSPAWN_DOMAIN (0xD002C00 + 0x11) +#define APPSPAWN_DOMAIN (0xD002C00 + 0x11) // 0xD002C11 #ifndef APPSPAWN_LABEL #define APPSPAWN_LABEL "APPSPAWN" #endif @@ -167,7 +176,7 @@ void EnableCache(void); #define APPSPAWN_LOGF(fmt, ...) \ HILOG_FATAL(LOG_CORE, "[%{public}s:%{public}d]" fmt, (APP_FILE_NAME), (__LINE__), ##__VA_ARGS__) -#define APPSPAPWN_DUMP(fmt, ...) \ +#define APPSPAWN_DUMP(fmt, ...) \ do { \ HILOG_INFO(LOG_CORE, fmt, ##__VA_ARGS__); \ AppSpawnDump(fmt "\n", ##__VA_ARGS__); \ diff --git a/util/src/appspawn_utils.c b/util/src/appspawn_utils.c index 1f3270ee77e2232378e511393a0cd172af95b515..774b11f82e4883a31a0a317033900b0c092cc9b3 100644 --- a/util/src/appspawn_utils.c +++ b/util/src/appspawn_utils.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -168,7 +167,7 @@ int MakeDirRec(const char *path, mode_t mode, int lastPath) static void TrimTail(char *buffer, uint32_t maxLen) { - uint32_t index = maxLen - 1; + int32_t index = (int32_t)maxLen - 1; while (index > 0) { if (isspace(buffer[index])) { buffer[index] = '\0'; @@ -208,7 +207,7 @@ int32_t StringSplit(const char *str, const char *separator, void *context, Split ret = result; } } - if (index > 0) { + if ((index > 0) && (index < PATH_MAX)) { buffer[index] = '\0'; TrimTail(buffer, index); index = 0; @@ -436,13 +435,3 @@ int EnableNewNetNamespace(void) close(fd); return (ret >= 0) ? 0 : APPSPAWN_SYSTEM_ERROR; } - -void EnableCache(void) -{ - APPSPAWN_LOGV("enable cache for app process"); - // enable cache for app process - mallopt(M_OHOS_CONFIG, M_TCACHE_PERFORMANCE_MODE); - mallopt(M_OHOS_CONFIG, M_ENABLE_OPT_TCACHE); - mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_ENABLE); - mallopt(M_DELAYED_FREE, M_DELAYED_FREE_ENABLE); -}