forked from suyu/suyu
android: Add key check
This commit is contained in:
parent
bc317a9807
commit
b8be8dff69
6 changed files with 67 additions and 2 deletions
|
@ -614,6 +614,11 @@ object NativeLibrary {
|
||||||
*/
|
*/
|
||||||
external fun clearFilesystemProvider()
|
external fun clearFilesystemProvider()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if all necessary keys are present for decryption
|
||||||
|
*/
|
||||||
|
external fun areKeysPresent(): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button type for use in onTouchEvent
|
* Button type for use in onTouchEvent
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -31,6 +31,7 @@ import androidx.preference.PreferenceManager
|
||||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||||
import com.google.android.material.transition.MaterialFadeThrough
|
import com.google.android.material.transition.MaterialFadeThrough
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
|
@ -162,7 +163,7 @@ class SetupFragment : Fragment() {
|
||||||
R.string.install_prod_keys_warning_help,
|
R.string.install_prod_keys_warning_help,
|
||||||
{
|
{
|
||||||
val file = File(DirectoryInitialization.userDirectory + "/keys/prod.keys")
|
val file = File(DirectoryInitialization.userDirectory + "/keys/prod.keys")
|
||||||
if (file.exists()) {
|
if (file.exists() && NativeLibrary.areKeysPresent()) {
|
||||||
StepState.COMPLETE
|
StepState.COMPLETE
|
||||||
} else {
|
} else {
|
||||||
StepState.INCOMPLETE
|
StepState.INCOMPLETE
|
||||||
|
@ -347,7 +348,8 @@ class SetupFragment : Fragment() {
|
||||||
val getProdKey =
|
val getProdKey =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
if (mainActivity.processKey(result)) {
|
mainActivity.processKey(result)
|
||||||
|
if (NativeLibrary.areKeysPresent()) {
|
||||||
keyCallback.onStepCompleted()
|
keyCallback.onStepCompleted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,9 @@ class HomeViewModel : ViewModel() {
|
||||||
private val _reloadPropertiesList = MutableStateFlow(false)
|
private val _reloadPropertiesList = MutableStateFlow(false)
|
||||||
val reloadPropertiesList get() = _reloadPropertiesList.asStateFlow()
|
val reloadPropertiesList get() = _reloadPropertiesList.asStateFlow()
|
||||||
|
|
||||||
|
private val _checkKeys = MutableStateFlow(false)
|
||||||
|
val checkKeys = _checkKeys.asStateFlow()
|
||||||
|
|
||||||
var navigatedToSetup = false
|
var navigatedToSetup = false
|
||||||
|
|
||||||
fun setNavigationVisibility(visible: Boolean, animated: Boolean) {
|
fun setNavigationVisibility(visible: Boolean, animated: Boolean) {
|
||||||
|
@ -66,4 +69,8 @@ class HomeViewModel : ViewModel() {
|
||||||
fun reloadPropertiesList(reload: Boolean) {
|
fun reloadPropertiesList(reload: Boolean) {
|
||||||
_reloadPropertiesList.value = reload
|
_reloadPropertiesList.value = reload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setCheckKeys(value: Boolean) {
|
||||||
|
_checkKeys.value = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,9 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
|
|
||||||
override var themeId: Int = 0
|
override var themeId: Int = 0
|
||||||
|
|
||||||
|
private val CHECKED_DECRYPTION = "CheckedDecryption"
|
||||||
|
private var checkedDecryption = false
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
val splashScreen = installSplashScreen()
|
val splashScreen = installSplashScreen()
|
||||||
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }
|
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }
|
||||||
|
@ -75,6 +78,18 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
checkedDecryption = savedInstanceState.getBoolean(CHECKED_DECRYPTION)
|
||||||
|
}
|
||||||
|
if (!checkedDecryption) {
|
||||||
|
val firstTimeSetup = PreferenceManager.getDefaultSharedPreferences(applicationContext)
|
||||||
|
.getBoolean(Settings.PREF_FIRST_APP_LAUNCH, true)
|
||||||
|
if (!firstTimeSetup) {
|
||||||
|
checkKeys()
|
||||||
|
}
|
||||||
|
checkedDecryption = true
|
||||||
|
}
|
||||||
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
|
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
|
||||||
|
|
||||||
|
@ -150,6 +165,16 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||||
|
homeViewModel.checkKeys.collect {
|
||||||
|
if (it) {
|
||||||
|
checkKeys()
|
||||||
|
homeViewModel.setCheckKeys(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dismiss previous notifications (should not happen unless a crash occurred)
|
// Dismiss previous notifications (should not happen unless a crash occurred)
|
||||||
|
@ -158,6 +183,21 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
setInsets()
|
setInsets()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkKeys() {
|
||||||
|
if (!NativeLibrary.areKeysPresent()) {
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
titleId = R.string.keys_missing,
|
||||||
|
descriptionId = R.string.keys_missing_description,
|
||||||
|
helpLinkId = R.string.keys_missing_help
|
||||||
|
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState.putBoolean(CHECKED_DECRYPTION, checkedDecryption)
|
||||||
|
}
|
||||||
|
|
||||||
fun finishSetup(navController: NavController) {
|
fun finishSetup(navController: NavController) {
|
||||||
navController.navigate(R.id.action_firstTimeSetupFragment_to_gamesFragment)
|
navController.navigate(R.id.action_firstTimeSetupFragment_to_gamesFragment)
|
||||||
(binding.navigationView as NavigationBarView).setupWithNavController(navController)
|
(binding.navigationView as NavigationBarView).setupWithNavController(navController)
|
||||||
|
@ -349,6 +389,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
R.string.install_keys_success,
|
R.string.install_keys_success,
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
|
homeViewModel.setCheckKeys(true)
|
||||||
gamesViewModel.reloadGames(true)
|
gamesViewModel.reloadGames(true)
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
|
@ -399,6 +440,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
firmwarePath.deleteRecursively()
|
firmwarePath.deleteRecursively()
|
||||||
cacheFirmwareDir.copyRecursively(firmwarePath, true)
|
cacheFirmwareDir.copyRecursively(firmwarePath, true)
|
||||||
NativeLibrary.initializeSystem(true)
|
NativeLibrary.initializeSystem(true)
|
||||||
|
homeViewModel.setCheckKeys(true)
|
||||||
getString(R.string.save_file_imported_success)
|
getString(R.string.save_file_imported_success)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
@ -913,4 +913,10 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_clearFilesystemProvider(JNIEnv* env,
|
||||||
EmulationSession::GetInstance().GetContentProvider()->ClearAllEntries();
|
EmulationSession::GetInstance().GetContentProvider()->ClearAllEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_areKeysPresent(JNIEnv* env, jobject jobj) {
|
||||||
|
auto& system = EmulationSession::GetInstance().System();
|
||||||
|
system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
|
||||||
|
return ContentManager::AreKeysPresent();
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -144,6 +144,9 @@
|
||||||
<string name="no_save_data_found">No save data found</string>
|
<string name="no_save_data_found">No save data found</string>
|
||||||
<string name="verify_installed_content">Verify installed content</string>
|
<string name="verify_installed_content">Verify installed content</string>
|
||||||
<string name="verify_installed_content_description">Checks all installed content for corruption</string>
|
<string name="verify_installed_content_description">Checks all installed content for corruption</string>
|
||||||
|
<string name="keys_missing">Encryption keys are missing</string>
|
||||||
|
<string name="keys_missing_description">Firmware and retail games cannot be decrypted</string>
|
||||||
|
<string name="keys_missing_help">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
|
||||||
|
|
||||||
<!-- Applet launcher strings -->
|
<!-- Applet launcher strings -->
|
||||||
<string name="applets">Applet launcher</string>
|
<string name="applets">Applet launcher</string>
|
||||||
|
|
Loading…
Reference in a new issue