diff --git a/app/src/full/java/com/topjohnwu/magisk/Data.java b/app/src/full/java/com/topjohnwu/magisk/Data.java index 2c3d84ae3..100d8b4e4 100644 --- a/app/src/full/java/com/topjohnwu/magisk/Data.java +++ b/app/src/full/java/com/topjohnwu/magisk/Data.java @@ -51,6 +51,7 @@ public class Data { public static int suRequestTimeout; public static int suLogTimeout = 14; public static int suAccessState; + public static boolean suFingerprint; public static int multiuserMode; public static int suResponseType; public static int suNotificationType; @@ -151,6 +152,7 @@ public class Data { suAccessState = mm.mDB.getSettings(Const.Key.ROOT_ACCESS, Const.Value.ROOT_ACCESS_APPS_AND_ADB); multiuserMode = mm.mDB.getSettings(Const.Key.SU_MULTIUSER_MODE, Const.Value.MULTIUSER_MODE_OWNER_ONLY); suNamespaceMode = mm.mDB.getSettings(Const.Key.SU_MNT_NS, Const.Value.NAMESPACE_MODE_REQUESTER); + suFingerprint = mm.mDB.getSettings(Const.Key.SU_FINGERPRINT, 0) != 0; // config isDarkTheme = mm.prefs.getBoolean(Const.Key.DARK_THEME, false); @@ -164,6 +166,7 @@ public class Data { .putBoolean(Const.Key.MAGISKHIDE, magiskHide) .putBoolean(Const.Key.HOSTS, Const.MAGISK_HOST_FILE.exists()) .putBoolean(Const.Key.COREONLY, Const.MAGISK_DISABLE_FILE.exists()) + .putBoolean(Const.Key.SU_FINGERPRINT, suFingerprint) .putString(Const.Key.SU_REQUEST_TIMEOUT, String.valueOf(suRequestTimeout)) .putString(Const.Key.SU_AUTO_RESPONSE, String.valueOf(suResponseType)) .putString(Const.Key.SU_NOTIFICATION, String.valueOf(suNotificationType)) diff --git a/app/src/full/java/com/topjohnwu/magisk/SettingsActivity.java b/app/src/full/java/com/topjohnwu/magisk/SettingsActivity.java index fed152ed5..b464831cf 100644 --- a/app/src/full/java/com/topjohnwu/magisk/SettingsActivity.java +++ b/app/src/full/java/com/topjohnwu/magisk/SettingsActivity.java @@ -27,6 +27,7 @@ import com.topjohnwu.magisk.receivers.DownloadReceiver; import com.topjohnwu.magisk.utils.Download; import com.topjohnwu.magisk.utils.FingerprintHelper; import com.topjohnwu.magisk.utils.LocaleManager; +import com.topjohnwu.magisk.utils.Logger; import com.topjohnwu.magisk.utils.RootUtils; import com.topjohnwu.magisk.utils.Topic; import com.topjohnwu.magisk.utils.Utils; @@ -86,7 +87,6 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { implements SharedPreferences.OnSharedPreferenceChangeListener, Topic.Subscriber, Topic.AutoSubscriber { - private SharedPreferences prefs; private PreferenceScreen prefScreen; private ListPreference updateChannel, suAccess, autoRes, suNotification, @@ -98,7 +98,6 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.app_settings, rootKey); mm = Data.MM(); - prefs = mm.prefs; prefScreen = getPreferenceScreen(); generalCatagory = (PreferenceCategory) findPreference("general"); @@ -107,7 +106,7 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { Preference hideManager = findPreference("hide"); Preference restoreManager = findPreference("restore"); findPreference("clear").setOnPreferenceClickListener((pref) -> { - prefs.edit().remove(Const.Key.ETAG_KEY).apply(); + mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply(); mm.repoDB.clearRepo(); Utils.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT); return true; @@ -129,17 +128,17 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { if (channel == Const.Value.CUSTOM_CHANNEL) { View v = LayoutInflater.from(requireActivity()).inflate(R.layout.custom_channel_dialog, null); EditText url = v.findViewById(R.id.custom_url); - url.setText(prefs.getString(Const.Key.CUSTOM_CHANNEL, "")); + url.setText(mm.prefs.getString(Const.Key.CUSTOM_CHANNEL, "")); new AlertDialog.Builder(requireActivity()) .setTitle(R.string.settings_update_custom) .setView(v) .setPositiveButton(R.string.ok, (d, i) -> - prefs.edit().putString(Const.Key.CUSTOM_CHANNEL, + mm.prefs.edit().putString(Const.Key.CUSTOM_CHANNEL, url.getText().toString()).apply()) .setNegativeButton(R.string.close, (d, i) -> - prefs.edit().putString(Const.Key.UPDATE_CHANNEL, prev).apply()) + mm.prefs.edit().putString(Const.Key.UPDATE_CHANNEL, prev).apply()) .setOnCancelListener(d -> - prefs.edit().putString(Const.Key.UPDATE_CHANNEL, prev).apply()) + mm.prefs.edit().putString(Const.Key.UPDATE_CHANNEL, prev).apply()) .show(); } return true; @@ -155,12 +154,14 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { // Disable re-authentication option on Android O, it will not work if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { reauth.setEnabled(false); + reauth.setChecked(false); reauth.setSummary(R.string.android_o_not_support); } // Disable fingerprint option if not possible if (!FingerprintHelper.canUseFingerprint()) { fingerprint.setEnabled(false); + fingerprint.setChecked(false); fingerprint.setSummary(R.string.disable_fingerprint); } @@ -175,7 +176,7 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { if (Download.checkNetworkStatus(mm)) { restoreManager.setOnPreferenceClickListener((pref) -> { Download.receive( - getActivity(), new DownloadReceiver() { + requireActivity(), new DownloadReceiver() { @Override public void onDownloadDone(Context context, Uri uri) { Data.exportPrefs(); @@ -233,26 +234,33 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - prefs.registerOnSharedPreferenceChangeListener(this); + mm.prefs.registerOnSharedPreferenceChangeListener(this); Topic.subscribe(this); return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onDestroyView() { - prefs.unregisterOnSharedPreferenceChangeListener(this); + mm.prefs.unregisterOnSharedPreferenceChangeListener(this); Topic.unsubscribe(this); super.onDestroyView(); } @Override public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - + switch (key) { + case Const.Key.ROOT_ACCESS: + case Const.Key.SU_MULTIUSER_MODE: + case Const.Key.SU_MNT_NS: + mm.mDB.setSettings(key, Utils.getPrefsInt(prefs, key)); + break; + } + Data.loadConfig(); + setSummary(); switch (key) { case Const.Key.DARK_THEME: - Data.isDarkTheme = prefs.getBoolean(key, false); Topic.publish(false, Topic.RELOAD_ACTIVITY); - return; + break; case Const.Key.COREONLY: if (prefs.getBoolean(key, false)) { try { @@ -261,7 +269,7 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { } else { Const.MAGISK_DISABLE_FILE.delete(); } - Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show(); + Utils.toast(R.string.settings_reboot_toast, Toast.LENGTH_LONG); break; case Const.Key.MAGISKHIDE: if (prefs.getBoolean(key, false)) { @@ -281,11 +289,6 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { .submit(); } break; - case Const.Key.ROOT_ACCESS: - case Const.Key.SU_MULTIUSER_MODE: - case Const.Key.SU_MNT_NS: - mm.mDB.setSettings(key, Utils.getPrefsInt(prefs, key)); - break; case Const.Key.LOCALE: LocaleManager.setLocale(mm); Topic.publish(false, Topic.RELOAD_ACTIVITY); @@ -298,8 +301,17 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { Utils.setupUpdateCheck(); break; } - Data.loadConfig(); - setSummary(); + } + + @Override + public boolean onPreferenceTreeClick(Preference preference) { + String key = preference.getKey(); + switch (key) { + case Const.Key.SU_FINGERPRINT: + mm.mDB.setSettings(key, mm.prefs.getBoolean(key, false) ? 1 : 0); + break; + } + return true; } private void setSummary() { @@ -312,7 +324,8 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber { suNotification.setSummary(getResources() .getStringArray(R.array.su_notification)[Data.suNotificationType]); requestTimeout.setSummary( - getString(R.string.request_timeout_summary, prefs.getString(Const.Key.SU_REQUEST_TIMEOUT, "10"))); + getString(R.string.request_timeout_summary, + mm.prefs.getString(Const.Key.SU_REQUEST_TIMEOUT, "10"))); multiuserMode.setSummary(getResources() .getStringArray(R.array.multiuser_summary)[Data.multiuserMode]); namespaceMode.setSummary(getResources() diff --git a/app/src/full/java/com/topjohnwu/magisk/database/MagiskDatabaseHelper.java b/app/src/full/java/com/topjohnwu/magisk/database/MagiskDatabaseHelper.java index 9dbed6e62..60f62e436 100644 --- a/app/src/full/java/com/topjohnwu/magisk/database/MagiskDatabaseHelper.java +++ b/app/src/full/java/com/topjohnwu/magisk/database/MagiskDatabaseHelper.java @@ -31,7 +31,7 @@ import java.util.List; public class MagiskDatabaseHelper { - private static final int DATABASE_VER = 5; + private static final int DATABASE_VER = 6; private static final String POLICY_TABLE = "policies"; private static final String LOG_TABLE = "logs"; private static final String SETTINGS_TABLE = "settings"; @@ -39,6 +39,7 @@ public class MagiskDatabaseHelper { private PackageManager pm; private SQLiteDatabase db; + private MagiskManager mm; @NonNull public static MagiskDatabaseHelper getInstance(MagiskManager mm) { @@ -51,7 +52,8 @@ public class MagiskDatabaseHelper { } } - private MagiskDatabaseHelper(MagiskManager mm) { + private MagiskDatabaseHelper(MagiskManager context) { + mm = context; pm = mm.getPackageManager(); db = openDatabase(mm); db.disableWriteAheadLogging(); @@ -139,6 +141,11 @@ public class MagiskDatabaseHelper { db.execSQL(Utils.fmt("UPDATE %s SET uid=uid%%100000", POLICY_TABLE)); ++oldVersion; } + if (oldVersion == 5) { + setSettings(Const.Key.SU_FINGERPRINT, + mm.prefs.getBoolean(Const.Key.SU_FINGERPRINT, false) ? 1 : 0); + ++oldVersion; + } } // Remove everything, we do not support downgrade diff --git a/app/src/full/java/com/topjohnwu/magisk/superuser/RequestActivity.java b/app/src/full/java/com/topjohnwu/magisk/superuser/RequestActivity.java index 737024357..091238bd1 100644 --- a/app/src/full/java/com/topjohnwu/magisk/superuser/RequestActivity.java +++ b/app/src/full/java/com/topjohnwu/magisk/superuser/RequestActivity.java @@ -140,7 +140,7 @@ public class RequestActivity extends BaseActivity { } }; - boolean useFingerprint = mm.prefs.getBoolean(Const.Key.SU_FINGERPRINT, false) && FingerprintHelper.canUseFingerprint(); + boolean useFingerprint = Data.suFingerprint && FingerprintHelper.canUseFingerprint(); if (useFingerprint) { try { @@ -165,7 +165,7 @@ public class RequestActivity extends BaseActivity { warning.setText(R.string.auth_fail); } }; - fingerprintHelper.startAuth(); + fingerprintHelper.authenticate(); } catch (Exception e) { e.printStackTrace(); useFingerprint = false; diff --git a/app/src/full/java/com/topjohnwu/magisk/utils/FingerprintHelper.java b/app/src/full/java/com/topjohnwu/magisk/utils/FingerprintHelper.java index 3257dcaf6..40e6bb709 100644 --- a/app/src/full/java/com/topjohnwu/magisk/utils/FingerprintHelper.java +++ b/app/src/full/java/com/topjohnwu/magisk/utils/FingerprintHelper.java @@ -36,9 +36,8 @@ public abstract class FingerprintHelper { } protected FingerprintHelper() throws Exception { - MagiskManager mm = Data.MM(); KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); - manager = mm.getSystemService(FingerprintManager.class); + manager = Data.MM().getSystemService(FingerprintManager.class); cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7); @@ -64,30 +63,10 @@ public abstract class FingerprintHelper { public abstract void onAuthenticationFailed(); - public void startAuth() { + public void authenticate() { cancel = new CancellationSignal(); FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher); - manager.authenticate(cryptoObject, cancel, 0, new FingerprintManager.AuthenticationCallback() { - @Override - public void onAuthenticationError(int errorCode, CharSequence errString) { - FingerprintHelper.this.onAuthenticationError(errorCode, errString); - } - - @Override - public void onAuthenticationHelp(int helpCode, CharSequence helpString) { - FingerprintHelper.this.onAuthenticationHelp(helpCode, helpString); - } - - @Override - public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { - FingerprintHelper.this.onAuthenticationSucceeded(result); - } - - @Override - public void onAuthenticationFailed() { - FingerprintHelper.this.onAuthenticationFailed(); - } - }, null); + manager.authenticate(cryptoObject, cancel, 0, new Callback(), null); } public void cancel() { @@ -111,4 +90,26 @@ public abstract class FingerprintHelper { keygen.init(builder.build()); return keygen.generateKey(); } + + private class Callback extends FingerprintManager.AuthenticationCallback { + @Override + public void onAuthenticationError(int errorCode, CharSequence errString) { + FingerprintHelper.this.onAuthenticationError(errorCode, errString); + } + + @Override + public void onAuthenticationHelp(int helpCode, CharSequence helpString) { + FingerprintHelper.this.onAuthenticationHelp(helpCode, helpString); + } + + @Override + public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { + FingerprintHelper.this.onAuthenticationSucceeded(result); + } + + @Override + public void onAuthenticationFailed() { + FingerprintHelper.this.onAuthenticationFailed(); + } + } }