mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-22 14:59:15 +01:00
Android 12 Support + Update Libraries + Include Khronos Validation Layer
* Fix handling `SA_EXPOSE_TAGBITS` bit being set in Android 12 `sigaction` * Fix CMake bug using `CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE` when not supported causing `-fuse-ld=gold` to be emitted as a linker flag * Support using `VIBRATOR_MANAGER_SERVICE` rather than `VIBRATOR_SERVICE` on Android 12 * Optimize Imports for Kotlin code * Move away from deprecated APIs in Kotlin or explicitly mark where it's not possible * Update SDK, NDK and libraries * Enable Gradle Configuration Cache
This commit is contained in:
parent
b7d0f2fafa
commit
a7548c79a0
@ -11,7 +11,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||
set(source_DIR ${CMAKE_SOURCE_DIR}/src/main/cpp)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -flto=full -fno-stack-protector -Wno-unused-command-line-argument -DNDEBUG")
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
|
||||
|
||||
# {fmt}
|
||||
add_subdirectory("libraries/fmt")
|
||||
|
@ -6,13 +6,13 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '30.0.3'
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion '31.0.0'
|
||||
defaultConfig {
|
||||
applicationId "skyline.emu"
|
||||
|
||||
minSdkVersion 29
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
|
||||
versionCode 3
|
||||
versionName "0.0.3"
|
||||
@ -50,19 +50,10 @@ android {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
shrinkResources false
|
||||
}
|
||||
}
|
||||
|
||||
/* Vulkan Validation Layers */
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs {
|
||||
srcDir "$buildDir/generated/vulkan_layers"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
buildFeatures {
|
||||
prefab true
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
@ -72,7 +63,7 @@ android {
|
||||
}
|
||||
|
||||
/* NDK */
|
||||
ndkVersion '22.1.7171670'
|
||||
ndkVersion '23.0.7599858'
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
version '3.18.1+'
|
||||
@ -84,41 +75,29 @@ android {
|
||||
aaptOptions {
|
||||
ignoreAssetsPattern "*.md"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We just want VK_LAYER_KHRONOS_validation in the APK while NDK contains several other legacy layers
|
||||
* This task copies shared objects associated with that layer into a folder from where JNI can use it
|
||||
*/
|
||||
task setupValidationLayer(type: Copy) {
|
||||
doFirst {
|
||||
def folder = new File("$buildDir/generated/vulkan_layers")
|
||||
if (!folder.exists()) {
|
||||
folder.mkdirs() // We need to recursively create all directories as the copy requires the output directory to exist
|
||||
/* Vulkan Validation Layers */
|
||||
sourceSets {
|
||||
debug {
|
||||
jniLibs {
|
||||
srcDir "libraries/vklayers"
|
||||
}
|
||||
}
|
||||
from("${android.ndkDirectory}/sources/third_party/vulkan/src/build-android/jniLibs") {
|
||||
include "*/libVkLayer_khronos_validation.so"
|
||||
}
|
||||
into "$buildDir/generated/vulkan_layers"
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
preDebugBuild.dependsOn setupValidationLayer
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/* Google */
|
||||
implementation "androidx.core:core-ktx:1.6.0"
|
||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
|
||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
|
||||
implementation 'androidx.fragment:fragment-ktx:1.3.5'
|
||||
implementation 'androidx.fragment:fragment-ktx:1.3.6'
|
||||
implementation "com.google.dagger:hilt-android:$hilt_version"
|
||||
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||
implementation 'com.google.android:flexbox:2.0.1'
|
||||
@ -129,3 +108,7 @@ dependencies {
|
||||
/* Other Java */
|
||||
implementation 'info.debatty:java-string-similarity:2.0.0'
|
||||
}
|
||||
|
||||
kapt {
|
||||
correctErrorTypes true
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 4237966924d69ea5c875d5c2072fc0804f15b4b5
|
||||
Subproject commit e32407f2b4cac7f0d739f10821d7f7e0c81e8436
|
@ -1 +1 @@
|
||||
Subproject commit 9e8b86fd2d9806672cc73133d21780dd182bfd24
|
||||
Subproject commit dcd282bb268a0766f6d273b6e41a3a96719bbbfb
|
@ -1 +1 @@
|
||||
Subproject commit 96ac3481a9e9543f44b4de8e65af9ad2b040241c
|
||||
Subproject commit 7264ab0eae2a072afa55d617d5e9e11bcb464aae
|
@ -1 +1 @@
|
||||
Subproject commit f126f79fd3d9cbfac78f6e8d8e8bc1cd9f4db849
|
||||
Subproject commit 855ea841a93bf304065e5152909983b1b85ffabb
|
@ -1 +1 @@
|
||||
Subproject commit 08b3433180727ea2f78fe02e860a08471db1e03c
|
||||
Subproject commit 9e382f98076e57581fcc61323728443374889646
|
@ -1 +1 @@
|
||||
Subproject commit 8c7a248a72c685ce28cbc63f6c40e6a2ea786346
|
||||
Subproject commit 4bcd301070d7d4a3d6ca191da96430025d708a6a
|
BIN
app/libraries/vklayers/arm64-v8a/libVkLayer_khronos_validation.so
Executable file
BIN
app/libraries/vklayers/arm64-v8a/libVkLayer_khronos_validation.so
Executable file
Binary file not shown.
@ -1 +1 @@
|
||||
Subproject commit 0790b5f0a9b96cd79fe75e4f458fc6b468dd9ec3
|
||||
Subproject commit 895b080a3c2189feaea0919af8982e9a248ff7d6
|
@ -22,12 +22,15 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||
<activity android:name="emu.skyline.MainActivity">
|
||||
<activity
|
||||
android:name="emu.skyline.MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="emu.skyline.SettingsActivity"
|
||||
android:exported="true"
|
||||
@ -37,6 +40,7 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="emu.skyline.MainActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="emu.skyline.input.ControllerActivity"
|
||||
android:exported="true">
|
||||
@ -44,6 +48,7 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="emu.skyline.SettingsActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="emu.skyline.input.onscreen.OnScreenEditActivity"
|
||||
android:exported="true"
|
||||
@ -53,9 +58,11 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="emu.skyline.input.ControllerActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="emu.skyline.EmulationActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true"
|
||||
android:launchMode="singleInstance"
|
||||
android:screenOrientation="landscape"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
|
@ -149,7 +149,7 @@ namespace skyline {
|
||||
*/
|
||||
template<typename S, typename... Args>
|
||||
auto Format(S formatString, Args &&... args) {
|
||||
return fmt::format(formatString, FmtCast(args)...);
|
||||
return fmt::format(fmt::runtime(formatString), FmtCast(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,7 +159,7 @@ namespace skyline {
|
||||
class exception : public std::runtime_error {
|
||||
public:
|
||||
template<typename S, typename... Args>
|
||||
exception(const S &formatStr, Args &&... args) : runtime_error(fmt::format(formatStr, util::FmtCast(args)...)) {}
|
||||
exception(const S &formatStr, Args &&... args) : runtime_error(fmt::format(fmt::runtime(formatStr), util::FmtCast(args)...)) {}
|
||||
};
|
||||
|
||||
namespace util {
|
||||
@ -364,7 +364,6 @@ namespace skyline {
|
||||
template<typename T> requires (std::is_integral_v<T>)
|
||||
void FillRandomBytes(std::span<T> in) {
|
||||
std::independent_bits_engine<std::mt19937_64, std::numeric_limits<T>::digits, T> gen(detail::generator);
|
||||
|
||||
std::generate(in.begin(), in.end(), gen);
|
||||
}
|
||||
|
||||
@ -577,7 +576,7 @@ namespace skyline {
|
||||
S string;
|
||||
const char *function;
|
||||
|
||||
FunctionString(S string, const char *function = __builtin_FUNCTION()) : string(std::move(string)), function(function) {}
|
||||
constexpr FunctionString(S string, const char *function = __builtin_FUNCTION()) : string(std::move(string)), function(function) {}
|
||||
|
||||
std::string operator*() {
|
||||
return std::string(function) + ": " + std::string(string);
|
||||
@ -587,91 +586,91 @@ namespace skyline {
|
||||
template<typename... Args>
|
||||
void Error(FunctionString<const char*> formatString, Args &&... args) {
|
||||
if (LogLevel::Error <= configLevel)
|
||||
Write(LogLevel::Error, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Error, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Error(FunctionString<std::string> formatString, Args &&... args) {
|
||||
if (LogLevel::Error <= configLevel)
|
||||
Write(LogLevel::Error, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Error, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename S, typename... Args>
|
||||
void ErrorNoPrefix(S formatString, Args &&... args) {
|
||||
if (LogLevel::Error <= configLevel)
|
||||
Write(LogLevel::Error, fmt::format(formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Error, fmt::format(fmt::runtime(formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Warn(FunctionString<const char*> formatString, Args &&... args) {
|
||||
if (LogLevel::Warn <= configLevel)
|
||||
Write(LogLevel::Warn, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Warn, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Warn(FunctionString<std::string> formatString, Args &&... args) {
|
||||
if (LogLevel::Warn <= configLevel)
|
||||
Write(LogLevel::Warn, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Warn, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename S, typename... Args>
|
||||
void WarnNoPrefix(S formatString, Args &&... args) {
|
||||
if (LogLevel::Warn <= configLevel)
|
||||
Write(LogLevel::Warn, fmt::format(formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Warn, fmt::format(fmt::runtime(formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Info(FunctionString<const char*> formatString, Args &&... args) {
|
||||
if (LogLevel::Info <= configLevel)
|
||||
Write(LogLevel::Info, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Info, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Info(FunctionString<std::string> formatString, Args &&... args) {
|
||||
if (LogLevel::Info <= configLevel)
|
||||
Write(LogLevel::Info, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Info, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename S, typename... Args>
|
||||
void InfoNoPrefix(S formatString, Args &&... args) {
|
||||
if (LogLevel::Info <= configLevel)
|
||||
Write(LogLevel::Info, fmt::format(formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Info, fmt::format(fmt::runtime(formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Debug(FunctionString<const char*> formatString, Args &&... args) {
|
||||
if (LogLevel::Debug <= configLevel)
|
||||
Write(LogLevel::Debug, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Debug, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Debug(FunctionString<std::string> formatString, Args &&... args) {
|
||||
if (LogLevel::Debug <= configLevel)
|
||||
Write(LogLevel::Debug, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Debug, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename S, typename... Args>
|
||||
void DebugNoPrefix(S formatString, Args &&... args) {
|
||||
if (LogLevel::Debug <= configLevel)
|
||||
Write(LogLevel::Debug, fmt::format(formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Debug, fmt::format(fmt::runtime(formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Verbose(FunctionString<const char*> formatString, Args &&... args) {
|
||||
if (LogLevel::Verbose <= configLevel)
|
||||
Write(LogLevel::Verbose, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Verbose, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Verbose(FunctionString<std::string> formatString, Args &&... args) {
|
||||
if (LogLevel::Verbose <= configLevel)
|
||||
Write(LogLevel::Verbose, fmt::format(*formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Verbose, fmt::format(fmt::runtime(*formatString), util::FmtCast(args)...));
|
||||
}
|
||||
|
||||
template<typename S, typename... Args>
|
||||
void VerboseNoPrefix(S formatString, Args &&... args) {
|
||||
if (LogLevel::Verbose <= configLevel)
|
||||
Write(LogLevel::Verbose, fmt::format(formatString, util::FmtCast(args)...));
|
||||
Write(LogLevel::Verbose, fmt::format(fmt::runtime(formatString), util::FmtCast(args)...));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <unwind.h>
|
||||
#include <fcntl.h>
|
||||
#include "signal.h"
|
||||
|
||||
namespace skyline::signal {
|
||||
@ -172,19 +173,21 @@ namespace skyline::signal {
|
||||
void SetSignalHandler(std::initializer_list<int> signals, SignalHandler function, bool syscallRestart) {
|
||||
static std::array<std::once_flag, NSIG> signalHandlerOnce{};
|
||||
|
||||
stack_t stack;
|
||||
sigaltstack(nullptr, &stack);
|
||||
struct sigaction action{
|
||||
.sa_sigaction = reinterpret_cast<void (*)(int, siginfo *, void *)>(ThreadSignalHandler),
|
||||
.sa_flags = (syscallRestart ? SA_RESTART : 0) | SA_SIGINFO | (stack.ss_sp && stack.ss_size ? SA_ONSTACK : 0),
|
||||
.sa_flags = SA_SIGINFO | SA_EXPOSE_TAGBITS | (syscallRestart ? SA_RESTART : 0) | SA_ONSTACK,
|
||||
};
|
||||
|
||||
for (int signal : signals) {
|
||||
std::call_once(signalHandlerOnce[signal], [signal, &action]() {
|
||||
struct sigaction oldAction;
|
||||
Sigaction(signal, &action, &oldAction);
|
||||
if (oldAction.sa_flags && oldAction.sa_flags != action.sa_flags)
|
||||
if (oldAction.sa_flags) {
|
||||
oldAction.sa_flags &= ~SA_UNSUPPORTED; // Mask out kernel not supporting old sigaction() bits
|
||||
oldAction.sa_flags |= SA_SIGINFO | SA_EXPOSE_TAGBITS | SA_RESTART | SA_ONSTACK; // Intentionally ignore these flags for the comparison
|
||||
if (oldAction.sa_flags != (action.sa_flags | SA_RESTART))
|
||||
throw exception("Old sigaction flags aren't equivalent to the replaced signal: {:#b} | {:#b}", oldAction.sa_flags, action.sa_flags);
|
||||
}
|
||||
|
||||
DefaultSignalHandlers.at(signal).function = (oldAction.sa_flags & SA_SIGINFO) ? oldAction.sa_sigaction : reinterpret_cast<void (*)(int, struct siginfo *, void *)>(oldAction.sa_handler);
|
||||
});
|
||||
|
@ -10,7 +10,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.AssetManager
|
||||
import android.graphics.PointF
|
||||
import android.net.Uri
|
||||
import android.os.*
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
@ -434,19 +433,29 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
} else {
|
||||
inputManager.controllers[index]!!.rumbleDeviceDescriptor?.let {
|
||||
if (it == "builtin") {
|
||||
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||
val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
val vibratorManager = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
|
||||
vibratorManager.defaultVibrator
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||
}
|
||||
vibrators[index] = vibrator
|
||||
vibrator
|
||||
} else {
|
||||
for (id in InputDevice.getDeviceIds()) {
|
||||
val device = InputDevice.getDevice(id)
|
||||
if (device.descriptor == inputManager.controllers[index]!!.rumbleDeviceDescriptor) {
|
||||
vibrators[index] = device.vibrator
|
||||
vibrators[index] = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
device.vibratorManager.defaultVibrator
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
device.vibrator
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -36,10 +36,9 @@ import emu.skyline.loader.AppEntry
|
||||
import emu.skyline.loader.LoaderResult
|
||||
import emu.skyline.loader.RomFormat
|
||||
import emu.skyline.utils.Settings
|
||||
import emu.skyline.utils.toFile
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
@ -23,7 +23,7 @@ class RomProvider @Inject constructor(@ApplicationContext private val context :
|
||||
if (file.isDirectory) {
|
||||
addEntries(fileFormats, file, entries, systemLanguage)
|
||||
} else {
|
||||
fileFormats[file.name?.substringAfterLast(".")?.toLowerCase()]?.let { romFormat->
|
||||
fileFormats[file.name?.substringAfterLast(".")?.lowercase()]?.let { romFormat->
|
||||
entries.getOrPut(romFormat, { arrayListOf() }).add(RomFile(context, romFormat, file.uri, systemLanguage).appEntry)
|
||||
}
|
||||
}
|
||||
|
@ -64,9 +64,10 @@ class SettingsActivity : AppCompatActivity() {
|
||||
if (parentFragmentManager.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null)
|
||||
return
|
||||
|
||||
val f = IntegerListPreference.IntegerListPreferenceDialogFragmentCompat.newInstance(preference.getKey())
|
||||
f.setTargetFragment(this, 0)
|
||||
f.show(parentFragmentManager, DIALOG_FRAGMENT_TAG)
|
||||
val dialogFragment = IntegerListPreference.IntegerListPreferenceDialogFragmentCompat.newInstance(preference.getKey())
|
||||
@Suppress("DEPRECATION")
|
||||
dialogFragment.setTargetFragment(this, 0) // androidx.preference.PreferenceDialogFragmentCompat depends on the target fragment being set correctly even though it's deprecated
|
||||
dialogFragment.show(parentFragmentManager, DIALOG_FRAGMENT_TAG)
|
||||
} else {
|
||||
super.onDisplayPreferenceDialog(preference)
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class GenericAdapter : RecyclerView.Adapter<GenericViewHolder<ViewBinding>>(), F
|
||||
* This sorts the items in [allItems] in relation to how similar they are to [currentSearchTerm]
|
||||
*/
|
||||
fun extractSorted() = allItems.mapNotNull { item ->
|
||||
item.key().toLowerCase(Locale.getDefault()).let {
|
||||
item.key().lowercase(Locale.getDefault()).let {
|
||||
val similarity = (jw.similarity(currentSearchTerm, it) + cos.similarity(currentSearchTerm, it)) / 2
|
||||
if (similarity != 0.0) ScoredItem(similarity, item) else null
|
||||
}
|
||||
@ -99,7 +99,7 @@ class GenericAdapter : RecyclerView.Adapter<GenericViewHolder<ViewBinding>>(), F
|
||||
/**
|
||||
* This performs filtering on the items in [allItems] based on similarity to [term]
|
||||
*/
|
||||
override fun performFiltering(term : CharSequence) = (term as String).toLowerCase(Locale.getDefault()).let { lowerCaseTerm ->
|
||||
override fun performFiltering(term : CharSequence) = (term as String).lowercase(Locale.getDefault()).let { lowerCaseTerm ->
|
||||
currentSearchTerm = lowerCaseTerm
|
||||
|
||||
with(if (term.isEmpty()) {
|
||||
@ -108,7 +108,7 @@ class GenericAdapter : RecyclerView.Adapter<GenericViewHolder<ViewBinding>>(), F
|
||||
val filterData = mutableListOf<GenericListItem<*>>()
|
||||
|
||||
val topResults = extractSorted()
|
||||
val avgScore = topResults.sumByDouble { it.score } / topResults.size
|
||||
val avgScore = topResults.sumOf { it.score } / topResults.size
|
||||
|
||||
for (result in topResults)
|
||||
if (result.score >= avgScore) filterData.add(result.item)
|
||||
|
@ -8,7 +8,6 @@ package emu.skyline.adapter.controller
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isGone
|
||||
import emu.skyline.adapter.GenericListItem
|
||||
import emu.skyline.adapter.GenericViewHolder
|
||||
import emu.skyline.adapter.ViewBindingFactory
|
||||
import emu.skyline.adapter.inflater
|
||||
import emu.skyline.databinding.ControllerCheckboxItemBinding
|
||||
|
@ -8,11 +8,9 @@ package emu.skyline.adapter.controller
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isGone
|
||||
import emu.skyline.adapter.GenericListItem
|
||||
import emu.skyline.adapter.GenericViewHolder
|
||||
import emu.skyline.adapter.ViewBindingFactory
|
||||
import emu.skyline.adapter.inflater
|
||||
import emu.skyline.databinding.ControllerItemBinding
|
||||
import emu.skyline.input.InputManager
|
||||
|
||||
object ControllerBindingFactory : ViewBindingFactory {
|
||||
override fun createBinding(parent : ViewGroup) = ControllerItemBinding.inflate(parent.inflater(), parent, false)
|
||||
|
@ -7,9 +7,7 @@ package emu.skyline.input.dialog
|
||||
|
||||
import android.animation.LayoutTransition
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import android.os.*
|
||||
import android.view.*
|
||||
import android.view.animation.LinearInterpolator
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
@ -64,7 +62,15 @@ class RumbleDialog @JvmOverloads constructor(val item : ControllerGeneralViewIte
|
||||
|
||||
if (context.id == 0) {
|
||||
binding.rumbleBuiltin.visibility = View.VISIBLE
|
||||
if (!(context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator).hasVibrator())
|
||||
val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
val vibratorManager = context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
|
||||
vibratorManager.defaultVibrator
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||
}
|
||||
|
||||
if (!vibrator.hasVibrator())
|
||||
binding.rumbleBuiltin.isEnabled = false
|
||||
binding.rumbleBuiltin.setOnClickListener {
|
||||
controller.rumbleDeviceDescriptor = "builtin"
|
||||
@ -85,7 +91,12 @@ class RumbleDialog @JvmOverloads constructor(val item : ControllerGeneralViewIte
|
||||
// We want all input events from Joysticks and game pads
|
||||
if (event.isFromSource(InputDevice.SOURCE_GAMEPAD) || event.isFromSource(InputDevice.SOURCE_JOYSTICK)) {
|
||||
if (event.repeatCount == 0 && event.action == KeyEvent.ACTION_DOWN) {
|
||||
val vibrator = event.device.vibrator
|
||||
val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
event.device.vibratorManager.defaultVibrator
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
event.device.vibrator
|
||||
}
|
||||
|
||||
when {
|
||||
// If the device doesn't match the currently selected device then update the UI accordingly and set [deviceId] to the current device
|
||||
|
@ -41,7 +41,7 @@ fun getRomFormat(uri : Uri, contentResolver : ContentResolver) : RomFormat {
|
||||
cursor.moveToFirst()
|
||||
uriStr = cursor.getString(nameIndex)
|
||||
}
|
||||
return RomFormat.valueOf(uriStr.substring(uriStr.lastIndexOf(".") + 1).toUpperCase(Locale.ROOT))
|
||||
return RomFormat.valueOf(uriStr.substring(uriStr.lastIndexOf(".") + 1).uppercase(Locale.ROOT))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,24 +5,23 @@
|
||||
|
||||
package emu.skyline.preference
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.res.Resources
|
||||
import android.content.res.TypedArray
|
||||
import android.os.Bundle
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.os.Parcelable.Creator
|
||||
import android.util.AttributeSet
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.content.res.TypedArray
|
||||
import android.content.DialogInterface
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.annotation.ArrayRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.res.TypedArrayUtils
|
||||
import androidx.preference.R
|
||||
import androidx.preference.DialogPreference
|
||||
import androidx.preference.PreferenceDialogFragmentCompat
|
||||
import emu.skyline.R as sR
|
||||
import androidx.preference.R
|
||||
import emu.skyline.di.getSettings
|
||||
import emu.skyline.R as sR
|
||||
|
||||
/**
|
||||
* A Preference that displays a list of strings in a dialog and saves an integer that corresponds to the selected entry (as specified by entryValues or the index of the selected entry)
|
||||
@ -177,19 +176,6 @@ class IntegerListPreference @JvmOverloads constructor(
|
||||
super.writeToParcel(dest, flags)
|
||||
dest.writeSerializable(value)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val CREATOR : Creator<SavedState> = object : Creator<SavedState> {
|
||||
override fun createFromParcel(input : Parcel) : SavedState? {
|
||||
return SavedState(input)
|
||||
}
|
||||
|
||||
override fun newArray(size : Int) : Array<SavedState?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,7 +44,7 @@ class SharedPreferencesDelegate<T>(context : Context, private val clazz : Class<
|
||||
private fun camelToSnakeCase(text : String) = StringBuilder().apply {
|
||||
text.forEachIndexed { index, c ->
|
||||
if (index != 0 && c.isUpperCase()) append('_')
|
||||
append(c.toLowerCase())
|
||||
append(c.lowercase())
|
||||
}.toString()
|
||||
}
|
||||
}
|
||||
|
@ -2,19 +2,18 @@
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
kotlin_version = '1.4.30'
|
||||
kotlin_version = '1.5.31'
|
||||
lifecycle_version = '2.3.1'
|
||||
hilt_version = '2.33-beta'
|
||||
hilt_version = '2.39.1'
|
||||
lifecycle_version = '2.3.1'
|
||||
}
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||
classpath 'com.android.tools.build:gradle:7.0.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
|
||||
|
||||
@ -28,7 +27,6 @@ allprojects {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url "https://google.bintray.com/flexbox-layout" }
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,3 +21,5 @@ android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
# Android NDK verbose build output
|
||||
android.native.buildOutput=verbose
|
||||
# Gradle Configuration Cache
|
||||
org.gradle.unsafe.configuration-cache=true
|
||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Mon Feb 08 07:42:45 GMT 2021
|
||||
#Mon Oct 11 06:23:28 GMT 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-milestone-1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
Loading…
Reference in New Issue
Block a user