From bfdc9e312f10e3b6efa043bcd3498051cc2e853a Mon Sep 17 00:00:00 2001 From: Timotej Leginus Date: Sat, 10 Jun 2023 22:52:50 +0200 Subject: [PATCH] Fixed network interfaces on Android --- src/android/app/src/main/AndroidManifest.xml | 1 + .../java/org/yuzu/yuzu_emu/YuzuApplication.kt | 2 + .../features/settings/model/Settings.kt | 2 + .../features/settings/model/StringSetting.kt | 6 ++- .../settings/model/view/SettingsItem.kt | 1 + .../settings/model/view/TextSetting.kt | 31 +++++++++++++ .../features/settings/ui/SettingsAdapter.kt | 41 ++++++++++++++++- .../settings/ui/SettingsFragmentPresenter.kt | 25 ++++++++++- .../ui/viewholder/TextSettingViewHolder.kt | 44 +++++++++++++++++++ .../org/yuzu/yuzu_emu/utils/NetworkHelper.kt | 20 +++++++++ src/android/app/src/main/jni/config.cpp | 5 +++ .../app/src/main/res/values/strings.xml | 5 +++ src/common/settings.h | 1 + .../internal_network/network_interface.cpp | 33 +++++++++++++- 14 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/TextSetting.kt create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/TextSettingViewHolder.kt create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NetworkHelper.kt diff --git a/src/android/app/src/main/AndroidManifest.xml b/src/android/app/src/main/AndroidManifest.xml index eef5660425..ddf52ce961 100644 --- a/src/android/app/src/main/AndroidManifest.xml +++ b/src/android/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ SPDX-License-Identifier: GPL-3.0-or-later + diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt index 4c947b7869..9fd9add6de 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt @@ -10,6 +10,7 @@ import android.content.Context import org.yuzu.yuzu_emu.utils.DirectoryInitialization import org.yuzu.yuzu_emu.utils.DocumentsTree import org.yuzu.yuzu_emu.utils.GpuDriverHelper +import org.yuzu.yuzu_emu.utils.NetworkHelper import java.io.File fun Context.getPublicFilesDir() : File = getExternalFilesDir(null) ?: filesDir @@ -46,6 +47,7 @@ class YuzuApplication : Application() { documentsTree = DocumentsTree() DirectoryInitialization.start(applicationContext) GpuDriverHelper.initializeDriverParameters(applicationContext) + NetworkHelper.setRoutes(applicationContext) NativeLibrary.logDeviceInfo() createNotificationChannels(); diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt index 8df20b928f..4eefa0bcce 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt @@ -107,6 +107,7 @@ class Settings { const val SECTION_RENDERER = "Renderer" const val SECTION_AUDIO = "Audio" const val SECTION_CPU = "Cpu" + const val SECTION_NETWORK = "Network" const val SECTION_THEME = "Theme" const val SECTION_DEBUG = "Debug" @@ -151,6 +152,7 @@ class Settings { SECTION_SYSTEM, SECTION_RENDERER, SECTION_AUDIO, + SECTION_NETWORK, SECTION_CPU ) } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt index 63f95690c7..999f080cb0 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt @@ -8,7 +8,8 @@ enum class StringSetting( override val section: String, override val defaultValue: String ) : AbstractStringSetting { - CUSTOM_RTC("custom_rtc", Settings.SECTION_SYSTEM, "0"); + CUSTOM_RTC("custom_rtc", Settings.SECTION_SYSTEM, "0"), + NETWORK_ROUTE("network_route", Settings.SECTION_NETWORK, ";;;;"); override var string: String = defaultValue @@ -27,7 +28,8 @@ enum class StringSetting( companion object { private val NOT_RUNTIME_EDITABLE = listOf( - CUSTOM_RTC + CUSTOM_RTC, + NETWORK_ROUTE ) fun from(key: String): StringSetting? = StringSetting.values().firstOrNull { it.key == key } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 07520849ec..d12b9331ee 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -35,5 +35,6 @@ abstract class SettingsItem( const val TYPE_STRING_SINGLE_CHOICE = 5 const val TYPE_DATETIME_SETTING = 6 const val TYPE_RUNNABLE = 7 + const val TYPE_TEXT_SETTING = 8 } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/TextSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/TextSetting.kt new file mode 100644 index 0000000000..c1fc51c16f --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/TextSetting.kt @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.features.settings.model.view + +import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting +import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting + +class TextSetting( + setting: AbstractSetting?, + titleId: Int, + descriptionId: Int, + val key: String? = null, + private val defaultValue: String? = null +) : SettingsItem(setting, titleId, descriptionId) { + override val type = TYPE_TEXT_SETTING + + val value: String + get() = if (setting != null) { + val setting = setting as AbstractStringSetting + setting.string + } else { + defaultValue!! + } + + fun setSelectedValue(string: String): AbstractStringSetting { + val stringSetting = setting as AbstractStringSetting + stringSetting.string = string + return stringSetting + } +} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt index 1eb4899fcb..2dc205a7f5 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt @@ -7,13 +7,14 @@ import android.content.Context import android.content.DialogInterface import android.icu.util.Calendar import android.icu.util.TimeZone +import android.text.TextWatcher import android.text.format.DateFormat import android.view.LayoutInflater import android.view.ViewGroup import android.widget.TextView import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.setFragmentResultListener +import androidx.core.widget.doAfterTextChanged import androidx.recyclerview.widget.RecyclerView import com.google.android.material.datepicker.MaterialDatePicker import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -21,6 +22,7 @@ import com.google.android.material.slider.Slider import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.TimeFormat import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.DialogEditTextBinding import org.yuzu.yuzu_emu.databinding.DialogSliderBinding import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding @@ -83,6 +85,10 @@ class SettingsAdapter( RunnableViewHolder(ListItemSettingBinding.inflate(inflater), this) } + SettingsItem.TYPE_TEXT_SETTING -> { + TextSettingViewHolder(ListItemSettingBinding.inflate(inflater), this) + } + else -> { // TODO: Create an error view since we can't return null now HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this) @@ -167,6 +173,7 @@ class SettingsAdapter( .setSelection(storedTime) .setTitleText(R.string.select_rtc_date) .build() + val timePicker: MaterialTimePicker = MaterialTimePicker.Builder() .setTimeFormat(timeFormat) .setHour(calendar.get(Calendar.HOUR_OF_DAY)) @@ -199,6 +206,38 @@ class SettingsAdapter( ) } + fun onTextSettingClick(item: TextSetting, position: Int) { + clickedItem = item + clickedPosition = position + var value = item.value + + val inflater = LayoutInflater.from(context) + val editTextBinding = DialogEditTextBinding.inflate(inflater) + + editTextBinding.editText.setText(value) + + editTextBinding.editText.doAfterTextChanged { + value = it.toString() + } + + dialog = MaterialAlertDialogBuilder(context) + .setTitle(item.nameId) + .setView(editTextBinding.root) + .setPositiveButton(android.R.string.ok) { _, _ -> + if (item.value != value) { + fragmentView.onSettingChanged() + } + notifyItemChanged(clickedPosition) + + val setting = item.setSelectedValue(value) + fragmentView.putSetting(setting) + clickedItem = null + } + .setNegativeButton(android.R.string.cancel, defaultCancelListener) + .show() + + } + fun onSliderClick(item: SliderSetting, position: Int) { clickedItem = item clickedPosition = position diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index 061046b2e7..e64f3760b9 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -7,7 +7,6 @@ import android.content.SharedPreferences import android.os.Build import android.text.TextUtils import androidx.preference.PreferenceManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting @@ -67,6 +66,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) Settings.SECTION_SYSTEM -> addSystemSettings(sl) Settings.SECTION_RENDERER -> addGraphicsSettings(sl) Settings.SECTION_AUDIO -> addAudioSettings(sl) + Settings.SECTION_NETWORK -> addNetworkSettings(sl) Settings.SECTION_THEME -> addThemeSettings(sl) Settings.SECTION_DEBUG -> addDebugSettings(sl) else -> { @@ -102,6 +102,13 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) Settings.SECTION_RENDERER ) ) + add( + SubmenuSetting( + R.string.preferences_network, + 0, + Settings.SECTION_NETWORK + ) + ) add( SubmenuSetting( R.string.preferences_audio, @@ -437,6 +444,22 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } } + private fun addNetworkSettings(sl: ArrayList) { + settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_network)) + + sl.apply { + add( + TextSetting( + StringSetting.NETWORK_ROUTE, + R.string.set_network_route, + R.string.network_route_desc, + StringSetting.NETWORK_ROUTE.key, + StringSetting.NETWORK_ROUTE.defaultValue + ) + ) + } + } + private fun addDebugSettings(sl: ArrayList) { settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_debug)) sl.apply { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/TextSettingViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/TextSettingViewHolder.kt new file mode 100644 index 0000000000..9557b07fca --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/TextSettingViewHolder.kt @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.features.settings.ui.viewholder + +import android.view.View +import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding +import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting +import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem +import org.yuzu.yuzu_emu.features.settings.model.view.TextSetting +import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter +import java.time.Instant +import java.time.ZoneId +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle + +class TextSettingViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : + SettingViewHolder(binding.root, adapter) { + private lateinit var setting: TextSetting + + override fun bind(item: SettingsItem) { + setting = item as TextSetting + + binding.textSettingName.setText(item.nameId) + if (item.descriptionId != 0) { + binding.textSettingDescription.setText(item.descriptionId) + binding.textSettingDescription.visibility = View.VISIBLE + } + } + + override fun onClick(clicked: View) { + if (setting.isEditable) { + adapter.onTextSettingClick(setting, bindingAdapterPosition) + } + } + + override fun onLongClick(clicked: View): Boolean { + if (setting.isEditable) { + return adapter.onLongClick(setting.setting!!, bindingAdapterPosition) + } + return false + } +} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NetworkHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NetworkHelper.kt new file mode 100644 index 0000000000..b5b32b5aad --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NetworkHelper.kt @@ -0,0 +1,20 @@ +package org.yuzu.yuzu_emu.utils + +import android.content.Context +import android.net.ConnectivityManager + + + + +object NetworkHelper { + fun setRoutes(context: Context) { + val connectivity = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + + val lp = connectivity.getLinkProperties(connectivity.activeNetwork) + + // lp.routes + + + } +} \ No newline at end of file diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index 2d622a048c..b96dd1f7ee 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -244,6 +244,11 @@ void Config::ReadValues() { ReadSetting("Audio", Settings::values.audio_output_device_id); ReadSetting("Audio", Settings::values.volume); + // Network + + Settings::values.network_route = + config->GetString("Network", "network_route", ""); + // Miscellaneous // log_filter has a different default here than from common Settings::values.log_filter = "*:Info"; diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 0ae69afb47..a2358a93ab 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -151,6 +151,10 @@ Allows you to set a custom real-time clock separate from your current system time. Set custom RTC + + Sets the default network route + Set network route + API Accuracy level @@ -203,6 +207,7 @@ Settings General System + Network Graphics Audio Theme and color diff --git a/src/common/settings.h b/src/common/settings.h index 9682281b08..0613d6f596 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -581,6 +581,7 @@ struct Values { // Network Setting network_interface{std::string(), "network_interface"}; + Setting network_route{std::string(), "network_route"}; // WebService Setting enable_telemetry{true, "enable_telemetry"}; diff --git a/src/core/internal_network/network_interface.cpp b/src/core/internal_network/network_interface.cpp index 4c909a6d3c..0c84db932c 100644 --- a/src/core/internal_network/network_interface.cpp +++ b/src/core/internal_network/network_interface.cpp @@ -6,6 +6,8 @@ #include #include +#include + #include "common/bit_cast.h" #include "common/common_types.h" #include "common/logging/log.h" @@ -20,6 +22,8 @@ #include #include #include +#include + #endif namespace Network { @@ -91,8 +95,31 @@ std::vector GetAvailableNetworkInterfaces() { return result; } -#else +#elif defined(__ANDROID__) +std::vector GetAvailableNetworkInterfaces() { + std::vector result; + std::vector route_parts; + + boost::split(route_parts, Settings::values.network_route.GetValue(), boost::is_any_of(";")); + + struct in_addr ip{}, sm{}, gw{}; + + inet_pton(AF_INET, route_parts[1].c_str(), &ip); + inet_pton(AF_INET, route_parts[2].c_str(), &sm); + inet_pton(AF_INET, route_parts[3].c_str(), &gw); + + result.emplace_back(NetworkInterface{ + .name{route_parts[0]}, + .ip_address{ip}, + .subnet_mask{sm}, + .gateway{gw} + }); + + return result; +} + +#else std::vector GetAvailableNetworkInterfaces() { struct ifaddrs* ifaddr = nullptr; @@ -187,6 +214,10 @@ std::vector GetAvailableNetworkInterfaces() { #endif std::optional GetSelectedNetworkInterface() { +#ifdef __ANDROID__ + Network::SelectFirstNetworkInterface(); // TODO ANDROID +#endif + const auto& selected_network_interface = Settings::values.network_interface.GetValue(); const auto network_interfaces = Network::GetAvailableNetworkInterfaces(); if (network_interfaces.empty()) {