From f5d3e25c021d2bff9127b3950e43326f59ccdf18 Mon Sep 17 00:00:00 2001 From: roynatech2544 Date: Mon, 18 Apr 2022 14:10:29 +0900 Subject: [PATCH] universal7885: parts: Implement swap on /data ctrl --- .../apps/SamsungParts/AndroidManifest.xml | 6 ++ .../apps/SamsungParts/jni/SwapBridge.cpp | 28 ++++++++ .../SamsungParts/res/drawable/ic_memory.xml | 13 ++++ .../apps/SamsungParts/res/values/strings.xml | 5 ++ .../res/xml/preferences_samsung_parts.xml | 3 + .../SamsungParts/res/xml/swap_settings.xml | 6 ++ .../samsungextras/interfaces/Swap.kt | 22 ++++++ .../samsungextras/swap/SwapActivity.kt | 30 ++++++++ .../samsungextras/swap/SwapFragment.kt | 69 +++++++++++++++++++ .../interfaces/hardware/parts/1.0/Android.bp | 1 + .../hardware/parts/1.0/ISwapOnData.hal | 21 ++++++ .../hardware/parts/1.0/default/Android.bp | 3 +- .../hardware/parts/1.0/default/Swap.cpp | 52 ++++++++++++++ .../hardware/parts/1.0/default/Swap.h | 40 +++++++++++ .../hardware/parts/1.0/default/service.cpp | 15 ++++ ...endor.eureka.hardware.parts@1.0-service.rc | 1 + .../vendor.eureka.hardware.parts@1.0.xml | 4 ++ .../sepolicy/vendor/file_contexts | 1 + .../sepolicy/vendor/hal_parts_default.te | 9 +++ .../sepolicy/vendor/hwservice_contexts | 1 + 20 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 universal7885-common/apps/SamsungParts/jni/SwapBridge.cpp create mode 100644 universal7885-common/apps/SamsungParts/res/drawable/ic_memory.xml create mode 100644 universal7885-common/apps/SamsungParts/res/xml/swap_settings.xml create mode 100644 universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/interfaces/Swap.kt create mode 100644 universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/swap/SwapActivity.kt create mode 100644 universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/swap/SwapFragment.kt create mode 100644 universal7885-common/hardware/interfaces/hardware/parts/1.0/ISwapOnData.hal create mode 100644 universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Swap.cpp create mode 100644 universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Swap.h diff --git a/universal7885-common/apps/SamsungParts/AndroidManifest.xml b/universal7885-common/apps/SamsungParts/AndroidManifest.xml index 372bbc7..54d5d43 100644 --- a/universal7885-common/apps/SamsungParts/AndroidManifest.xml +++ b/universal7885-common/apps/SamsungParts/AndroidManifest.xml @@ -40,6 +40,12 @@ + + + + + + diff --git a/universal7885-common/apps/SamsungParts/jni/SwapBridge.cpp b/universal7885-common/apps/SamsungParts/jni/SwapBridge.cpp new file mode 100644 index 0000000..16ed991 --- /dev/null +++ b/universal7885-common/apps/SamsungParts/jni/SwapBridge.cpp @@ -0,0 +1,28 @@ +#include "jni.h" +#include +#include +#include +#include +#include + +using android::sp; +using vendor::eureka::hardware::parts::V1_0::ISwapOnData; + +static sp service = ISwapOnData::getService(); + +extern "C" JNIEXPORT void JNICALL +Java_com_eurekateam_samsungextras_interfaces_Swap_setSize(JNIEnv *env, + jclass clazz, + jint size) { + service->setSwapSize(size); +} + +extern "C" JNIEXPORT void JNICALL +Java_com_eurekateam_samsungextras_interfaces_Swap_setSwapOn( + JNIEnv *env, jclass clazz, jboolean enable) { + if (enable){ + service->setSwapOn(); + } else { + service->setSwapOff(); + } +} diff --git a/universal7885-common/apps/SamsungParts/res/drawable/ic_memory.xml b/universal7885-common/apps/SamsungParts/res/drawable/ic_memory.xml new file mode 100644 index 0000000..e68e458 --- /dev/null +++ b/universal7885-common/apps/SamsungParts/res/drawable/ic_memory.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/universal7885-common/apps/SamsungParts/res/values/strings.xml b/universal7885-common/apps/SamsungParts/res/values/strings.xml index 342387a..6c95597 100644 --- a/universal7885-common/apps/SamsungParts/res/values/strings.xml +++ b/universal7885-common/apps/SamsungParts/res/values/strings.xml @@ -56,6 +56,11 @@ Samsung\'s OneUI Has An Option to Adjust Flashlight Brightness. AOSP doesn\'t have this feature.\n\n Use this feature to adjust low or high flashlight brightness. Ranges from 0 to 10. + Swap on userdata + Enable swap on EMMC + Swap size + Adjust the size of swap + Creates the swap (not zram) on /data partiton. Useful for low memory devices. Misc Toggle for double tap to wake diff --git a/universal7885-common/apps/SamsungParts/res/xml/preferences_samsung_parts.xml b/universal7885-common/apps/SamsungParts/res/xml/preferences_samsung_parts.xml index d914b9f..b5c1295 100644 --- a/universal7885-common/apps/SamsungParts/res/xml/preferences_samsung_parts.xml +++ b/universal7885-common/apps/SamsungParts/res/xml/preferences_samsung_parts.xml @@ -22,6 +22,9 @@ + + + diff --git a/universal7885-common/apps/SamsungParts/res/xml/swap_settings.xml b/universal7885-common/apps/SamsungParts/res/xml/swap_settings.xml new file mode 100644 index 0000000..01ba27f --- /dev/null +++ b/universal7885-common/apps/SamsungParts/res/xml/swap_settings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/interfaces/Swap.kt b/universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/interfaces/Swap.kt new file mode 100644 index 0000000..61007d1 --- /dev/null +++ b/universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/interfaces/Swap.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2022 Eureka Team + * + * 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. + */ + +package com.eurekateam.samsungextras.interfaces + +object Swap{ + external fun setSwapOn(mEnabled: Boolean) + external fun setSize(mSize : Int) +} diff --git a/universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/swap/SwapActivity.kt b/universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/swap/SwapActivity.kt new file mode 100644 index 0000000..b2d0f4d --- /dev/null +++ b/universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/swap/SwapActivity.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Eureka Team + * + * 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. + */ +package com.eurekateam.samsungextras.swap + +import android.os.Bundle +import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity +import com.android.settingslib.collapsingtoolbar.R + +class SwapActivity : CollapsingToolbarBaseActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + supportFragmentManager.beginTransaction().replace( + R.id.content_frame, + SwapFragment() + ).commit() + } +} diff --git a/universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/swap/SwapFragment.kt b/universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/swap/SwapFragment.kt new file mode 100644 index 0000000..efccb0a --- /dev/null +++ b/universal7885-common/apps/SamsungParts/src/com/eurekateam/samsungextras/swap/SwapFragment.kt @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 Eureka Team + * + * 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. + */ +package com.eurekateam.samsungextras.swap + +import android.content.SharedPreferences +import android.os.Build +import android.os.Bundle +import android.widget.Switch +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import androidx.preference.PreferenceManager +import androidx.preference.SeekBarPreference +import com.android.settingslib.widget.MainSwitchPreference +import com.android.settingslib.widget.OnMainSwitchChangeListener +import com.eurekateam.samsungextras.R +import com.eurekateam.samsungextras.interfaces.Swap + +class SwapFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener, OnMainSwitchChangeListener { + private lateinit var mSwapSizePref: SeekBarPreference + private lateinit var mSharedPreferences: SharedPreferences + private lateinit var mSwapEnable: MainSwitchPreference + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + addPreferencesFromResource(R.xml.swap_settings) + mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) + mSwapSizePref = findPreference(PREF_SWAP_SIZE)!! + mSwapSizePref.onPreferenceChangeListener = this + mSwapSizePref.setMax(100) + mSwapSizePref.setMin(10) + mSwapSizePref.value = mSharedPreferences.getInt(PREF_SWAP_SIZE, 50) + mSwapEnable = findPreference(PREF_SWAP_ENABLE)!! + mSwapEnable.isChecked = mSharedPreferences.getBoolean(PREF_SWAP_ENABLE, false) + mSwapEnable.addOnSwitchChangeListener(this) + mSwapSizePref.isEnabled = !mSwapEnable.isChecked + } + + override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean { + if (preference == mSwapSizePref) { + val value = newValue as Int + Swap.setSize(value) + mSharedPreferences.edit().putInt(PREF_SWAP_SIZE, value).apply() + return true + } + return false + } + + override fun onSwitchChanged(switchView: Switch, isChecked: Boolean) { + Swap.setSwapOn(isChecked) + mSharedPreferences.edit().putBoolean(PREF_SWAP_ENABLE, isChecked) + mSwapSizePref.isEnabled = !isChecked + } + + companion object { + const val PREF_SWAP_SIZE = "swap_size" + const val PREF_SWAP_ENABLE = "swap_enable" + } +} diff --git a/universal7885-common/hardware/interfaces/hardware/parts/1.0/Android.bp b/universal7885-common/hardware/interfaces/hardware/parts/1.0/Android.bp index eae74af..dadfb8e 100644 --- a/universal7885-common/hardware/interfaces/hardware/parts/1.0/Android.bp +++ b/universal7885-common/hardware/interfaces/hardware/parts/1.0/Android.bp @@ -6,6 +6,7 @@ hidl_interface { "IBatteryStats.hal", "IFlashBrightness.hal", "IDisplayConfigs.hal", + "ISwapOnData.hal", ], interfaces: [ "android.hidl.base@1.0" ], gen_java: false, diff --git a/universal7885-common/hardware/interfaces/hardware/parts/1.0/ISwapOnData.hal b/universal7885-common/hardware/interfaces/hardware/parts/1.0/ISwapOnData.hal new file mode 100644 index 0000000..cf38a19 --- /dev/null +++ b/universal7885-common/hardware/interfaces/hardware/parts/1.0/ISwapOnData.hal @@ -0,0 +1,21 @@ +// Copyright (C) 2021 Eureka Team +// +// 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. + +package vendor.eureka.hardware.parts@1.0; + +interface ISwapOnData { + setSwapSize(int32_t size /* Size in megabytes */); + setSwapOn(); + setSwapOff(); +}; diff --git a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Android.bp b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Android.bp index 8d6aca2..11b4e2e 100644 --- a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Android.bp +++ b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Android.bp @@ -7,7 +7,8 @@ cc_binary { "Battery.cpp", "FlashLight.cpp", "Display.cpp", - "service.cpp", + "Swap.cpp", + "service.cpp", ], shared_libs: [ "libhidlbase", diff --git a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Swap.cpp b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Swap.cpp new file mode 100644 index 0000000..b62774b --- /dev/null +++ b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Swap.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2021 Eureka Team +// +// 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 "Swap.h" +#include +#include + +static int mSwapSize = 100; + +#define SWAP_PATH "/data/swap/swapfile" +using namespace std; +namespace vendor::eureka::hardware::parts::V1_0 { + +Return SwapOnData::setSwapSize(int32_t size) { + mSwapSize = size; + return Void(); +} + +Return SwapOnData::setSwapOn(){ + string cmd = string("dd if=/dev/zero of=") + string(SWAP_PATH) + string(" bs=") + std::to_string(mSwapSize) + + " count=10"; + system(cmd.c_str()); + cmd = string("mkswap ") + string(SWAP_PATH); + system(cmd.c_str()); + cmd = string("swapon ") + string(SWAP_PATH); + system(cmd.c_str()); + return Void(); +} + +Return SwapOnData::setSwapOff(){ + std::string cmd = string("swapoff ") + string(SWAP_PATH); + system(cmd.c_str()); + cmd = string("rm ") + string(SWAP_PATH); + system(cmd.c_str()); + return Void(); +} + +ISwapOnData *SwapOnData::getInstance(void) { + return new SwapOnData(); +} +} // namespace vendor::eureka::hardware::parts::V1_0 diff --git a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Swap.h b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Swap.h new file mode 100644 index 0000000..0f204f8 --- /dev/null +++ b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/Swap.h @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Eureka Team +// +// 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. + +#pragma once + +#include +#include +#include + +namespace vendor::eureka::hardware::parts::V1_0 { + +using ::android::sp; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; + +struct SwapOnData : public ISwapOnData { + // Methods from ::vendor::eureka::hardware::parts::V1_0::ISwapOnData + // follow. + Return setSwapSize(int32_t size); + Return setSwapOn(); + Return setSwapOff(); + // Methods from ::android::hidl::base::V2_0::IBase follow. + static ISwapOnData *getInstance(void); +}; +} // namespace vendor::eureka::hardware::parts::V1_0 diff --git a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/service.cpp b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/service.cpp index 9d9af70..176dff0 100644 --- a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/service.cpp +++ b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/service.cpp @@ -18,10 +18,12 @@ #include #include #include +#include #include "Battery.h" #include "Display.h" #include "FlashLight.h" +#include "Swap.h" using android::sp; using android::hardware::configureRpcThreadpool; @@ -29,9 +31,11 @@ using android::hardware::joinRpcThreadpool; using vendor::eureka::hardware::parts::V1_0::BatteryStats; using vendor::eureka::hardware::parts::V1_0::DisplayConfigs; using vendor::eureka::hardware::parts::V1_0::FlashBrightness; +using vendor::eureka::hardware::parts::V1_0::SwapOnData; using vendor::eureka::hardware::parts::V1_0::IBatteryStats; using vendor::eureka::hardware::parts::V1_0::IDisplayConfigs; using vendor::eureka::hardware::parts::V1_0::IFlashBrightness; +using vendor::eureka::hardware::parts::V1_0::ISwapOnData; int main() { int ret; @@ -39,6 +43,7 @@ int main() { android::sp mFlashLightService = FlashBrightness::getInstance(); android::sp mDisplayService = DisplayConfigs::getInstance(); + android::sp mSwapService = SwapOnData::getInstance(); configureRpcThreadpool(4, true /*callerWillJoin*/); if (mBatteryService != nullptr) { @@ -71,6 +76,16 @@ int main() { } else { ALOGE("Can't create instance of Display HAL, nullptr"); } + if (mSwapService != nullptr) { + ret = mSwapService->registerAsService(); + if (ret != 0) { + ALOGE("Can't register instance of Swap HAL, nullptr"); + } else { + ALOGI("registered Swap HAL"); + } + } else { + ALOGE("Can't create instance of Swap HAL, nullptr"); + } joinRpcThreadpool(); return -1; // should never get here diff --git a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/vendor.eureka.hardware.parts@1.0-service.rc b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/vendor.eureka.hardware.parts@1.0-service.rc index 3f84d9c..00107cf 100644 --- a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/vendor.eureka.hardware.parts@1.0-service.rc +++ b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/vendor.eureka.hardware.parts@1.0-service.rc @@ -2,6 +2,7 @@ service vendor.parts-hal /vendor/bin/vendor.eureka.hardware.parts@1.0-service interface vendor.eureka.hardware.parts@1.0::IBatteryStats default interface vendor.eureka.hardware.parts@1.0::IDisplayConfigs default interface vendor.eureka.hardware.parts@1.0::IFlashBrightness default + interface vendor.eureka.hardware.parts@1.0::ISwapOnData default class hal user root group root diff --git a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/vendor.eureka.hardware.parts@1.0.xml b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/vendor.eureka.hardware.parts@1.0.xml index 7cc2556..3f190ab 100644 --- a/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/vendor.eureka.hardware.parts@1.0.xml +++ b/universal7885-common/hardware/interfaces/hardware/parts/1.0/default/vendor.eureka.hardware.parts@1.0.xml @@ -16,5 +16,9 @@ IDisplayConfigs default + + ISwapOnData + default + diff --git a/universal7885-common/sepolicy/vendor/file_contexts b/universal7885-common/sepolicy/vendor/file_contexts index dad4db5..9c854ea 100644 --- a/universal7885-common/sepolicy/vendor/file_contexts +++ b/universal7885-common/sepolicy/vendor/file_contexts @@ -24,6 +24,7 @@ /data/vendor/log(/.*)? u:object_r:log_vendor_data_file:s0 /data/vendor/log/cbd(/.*)? u:object_r:log_cbd_vendor_data_file:s0 /data/vendor/secradio(/.*)? u:object_r:radio_vendor_data_file:s0 +/data/swap(/.*)? u:object_r:parts_data_file:s0 ### DEV /dev/block/platform/.+/by-name/boot u:object_r:boot_block_device:s0 diff --git a/universal7885-common/sepolicy/vendor/hal_parts_default.te b/universal7885-common/sepolicy/vendor/hal_parts_default.te index d60e9e8..153c03f 100644 --- a/universal7885-common/sepolicy/vendor/hal_parts_default.te +++ b/universal7885-common/sepolicy/vendor/hal_parts_default.te @@ -24,3 +24,12 @@ allow hal_parts_default sysfs_virtual:dir search; # Display allow hal_parts_default sysfs_sec_touchscreen:dir search; allow hal_parts_default sysfs_touchscreen_writable:file rw_file_perms; + +# Swap +type parts_data_file, file_type, data_file_type; +allow hal_parts_default parts_data_file:dir rw_dir_perms; +allow hal_parts_default parts_data_file:file rw_file_perms; +allow hal_parts_default parts_data_file:file create_file_perms; +allow hal_parts_default vendor_shell_exec:file rx_file_perms; +allow hal_parts_default vendor_toolbox_exec:file rx_file_perms; +allow hal_parts_default self:capability sys_admin; diff --git a/universal7885-common/sepolicy/vendor/hwservice_contexts b/universal7885-common/sepolicy/vendor/hwservice_contexts index 90d1f97..37f8918 100644 --- a/universal7885-common/sepolicy/vendor/hwservice_contexts +++ b/universal7885-common/sepolicy/vendor/hwservice_contexts @@ -8,6 +8,7 @@ vendor.lineage.power::ILineagePower u:object_r:hal_power_hwservice:s0 vendor.eureka.hardware.parts::IBatteryStats u:object_r:hal_parts_hwservice:s0 vendor.eureka.hardware.parts::IFlashBrightness u:object_r:hal_parts_hwservice:s0 vendor.eureka.hardware.parts::IDisplayConfigs u:object_r:hal_parts_hwservice:s0 +vendor.eureka.hardware.parts::ISwapOnData u:object_r:hal_parts_hwservice:s0 # FMRadio vendor.eureka.hardware.fmradio::IFMRadio u:object_r:hal_fmradio_hwservice:s0