From 1da27627c3e647b30744b79ecaca64f1d184c2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20Karc=C4=B1o=C4=9Flu?= <45714956+frknkrc44@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:04:44 +0300 Subject: [PATCH] Prepare for a new version (#35) * Prepare for a new version - Add "Clear package list" functionality for presets - Add Xiaomi.EU apps in Custom ROM preset - Add new apps into presets - Create new preset, called as "Shizuku/Dhizuku apps" - Move Shizuku to new preset - Add manifest read cache, it can improve performance - Add existence check for package add listener - Add "Enable package query workaround" switch to help MIUI/HyperOS users (needs test) - Other fixes and improvements --- app/src/main/AndroidManifest.xml | 1 - app/src/main/ic_launcher-playstore.png | Bin 5608 -> 69919 bytes .../hidemyapplist/service/ConfigManager.kt | 82 ++++++++++- .../hidemyapplist/service/PrefManager.kt | 36 +++-- .../hidemyapplist/service/ServiceClient.kt | 9 ++ .../ui/adapter/TemplateAdapter.kt | 17 ++- .../ui/fragment/AppSelectFragment.kt | 6 +- .../ui/fragment/AppSettingsFragment.kt | 88 ++++++++++-- .../hidemyapplist/ui/fragment/LogsFragment.kt | 4 +- .../ui/fragment/SettingsFragment.kt | 34 ++++- .../ui/fragment/TemplateManageFragment.kt | 78 ++++++++-- .../ui/fragment/TemplateSettingsFragment.kt | 4 +- .../nullptr/hidemyapplist/ui/util/Fragment.kt | 5 - .../hidemyapplist/ui/view/ListItemView.kt | 2 +- .../hidemyapplist/util/PackageHelper.kt | 34 +++-- .../hma_oss/ui/activity/BaseActivity.kt | 21 +++ .../ui/adapter/AppPresetListAdapter.kt | 8 +- .../ui/adapter/BaseSettingsPTAdapter.kt | 40 ++++++ .../ui/adapter/SettingsPresetListAdapter.kt | 33 +---- .../ui/adapter/SettingsTemplateListAdapter.kt | 21 +++ .../hma_oss/ui/fragment/AboutFragment.kt | 47 ++++-- .../hma_oss/ui/fragment/AppPresetFragment.kt | 12 +- .../ui/fragment/BaseSettingsPTFragment.kt | 73 ++++++++++ .../ui/fragment/EditSettingFragment.kt | 134 +++++++++++++++++ .../hma_oss/ui/fragment/HomeFragment.kt | 4 +- .../ui/fragment/PresetManageFragment.kt | 8 +- .../ui/fragment/SettingsPresetFragment.kt | 67 ++------- .../fragment/SettingsTemplateConfFragment.kt | 136 ++++++++++++++++++ .../fragment/SettingsTemplateInnerFragment.kt | 90 ++++++++++++ .../hma_oss/ui/util/ItemConverter.kt | 22 +++ .../SettingsTemplateConfViewModel.kt | 36 +++++ .../res/drawable/keyboard_arrow_down_24px.xml | 10 ++ app/src/main/res/drawable/switch_thumb.xml | 4 +- app/src/main/res/layout/fragment_about.xml | 47 +++++- .../main/res/layout/fragment_app_select.xml | 25 +--- .../main/res/layout/fragment_edit_setting.xml | 104 ++++++++++++++ ...eset.xml => fragment_settings_pt_base.xml} | 0 .../res/layout/fragment_template_manage.xml | 40 +----- app/src/main/res/layout/layout_list_empty.xml | 26 ++++ .../main/res/menu/menu_settings_template.xml | 9 ++ .../main/res/menu/menu_template_manage.xml | 9 ++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 2 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 1195 -> 0 bytes .../mipmap-hdpi/ic_launcher_background.png | Bin 524 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 978 -> 4512 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 2925 -> 0 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 940 -> 0 bytes .../mipmap-mdpi/ic_launcher_background.png | Bin 297 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 750 -> 2331 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 1899 -> 0 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 1607 -> 0 bytes .../mipmap-xhdpi/ic_launcher_background.png | Bin 752 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 1157 -> 7681 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 4093 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 2186 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_background.png | Bin 1322 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 1632 -> 15157 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 6230 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 3125 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_background.png | Bin 1915 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 1893 -> 26389 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 8868 -> 0 bytes .../main/res/navigation/home_nav_graph.xml | 50 ++++++- .../main/res/values-night/themes_overlay.xml | 1 - app/src/main/res/values/arrays.xml | 5 + app/src/main/res/values/colors.xml | 2 + app/src/main/res/values/dimens.xml | 2 + app/src/main/res/values/strings.xml | 16 +++ app/src/main/res/values/themes_overlay.xml | 1 - app/src/main/res/xml/app_settings.xml | 13 ++ app/src/main/res/xml/settings.xml | 12 ++ build.gradle.kts | 2 +- .../hidemyapplist/common/IHMAService.aidl | 6 + .../hidemyapplist/common/AppPresets.kt | 64 +++++++-- .../nullptr/hidemyapplist/common/Constants.kt | 18 ++- .../hidemyapplist/common/JsonConfig.kt | 22 ++- .../hidemyapplist/common/RiskyPackageUtils.kt | 18 +-- .../hidemyapplist/common/SettingsPresets.kt | 3 +- .../icu/nullptr/hidemyapplist/common/Utils.kt | 8 ++ .../common/app_presets/BasePreset.kt | 2 + .../common/app_presets/CustomROMPreset.kt | 13 +- .../common/app_presets/DetectorAppsPreset.kt | 6 +- .../common/app_presets/RootAppsPreset.kt | 7 +- .../common/app_presets/SDhizukuAppsPreset.kt | 37 +++++ .../app_presets/SuspiciousAppsPreset.kt | 12 +- .../common/app_presets/XposedModulesPreset.kt | 6 +- .../settings_presets/AccessibilityPreset.kt | 3 + .../common/settings_presets/BasePreset.kt | 8 -- .../DeveloperOptionsPreset.kt | 11 ++ .../settings_presets/InputMethodPreset.kt | 23 +++ .../settings_presets/ReplacementItem.kt | 8 +- gradle.properties | 2 - .../hidemyapplist/xposed/HMAService.kt | 99 ++++++++++--- .../hidemyapplist/xposed/UserService.kt | 4 +- .../hidemyapplist/xposed/XposedEntry.kt | 28 +++- .../xposed/hook/AccessibilityHook.kt | 19 ++- .../xposed/hook/AppDataIsolationHook.kt | 54 +++++-- .../xposed/hook/ContentProviderHook.kt | 32 +++-- .../xposed/hook/PmsHookTarget28.kt | 7 +- .../xposed/hook/PmsHookTarget30.kt | 21 ++- .../xposed/hook/PmsHookTarget31.kt | 8 +- .../xposed/hook/PmsHookTarget33.kt | 8 +- .../xposed/hook/PmsHookTarget34.kt | 8 +- .../xposed/hook/PmsHookTargetBase.kt | 98 +++++++++++-- 105 files changed, 1798 insertions(+), 402 deletions(-) create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/BaseSettingsPTAdapter.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/SettingsTemplateListAdapter.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/BaseSettingsPTFragment.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/EditSettingFragment.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsTemplateConfFragment.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsTemplateInnerFragment.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/util/ItemConverter.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/viewmodel/SettingsTemplateConfViewModel.kt create mode 100644 app/src/main/res/drawable/keyboard_arrow_down_24px.xml create mode 100644 app/src/main/res/layout/fragment_edit_setting.xml rename app/src/main/res/layout/{fragment_settings_preset.xml => fragment_settings_pt_base.xml} (100%) create mode 100644 app/src/main/res/layout/layout_list_empty.xml create mode 100644 app/src/main/res/menu/menu_settings_template.xml create mode 100644 app/src/main/res/menu/menu_template_manage.xml delete mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_background.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_background.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_background.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/SDhizukuAppsPreset.kt create mode 100644 common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/InputMethodPreset.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b1e9f43..52d34bf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -31,7 +31,6 @@ diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png index 415d864cec92a52635d760330a5dd99d12205a30..b6c3fd7b8baeb33e87321688f9cd0780a7c7a6c4 100644 GIT binary patch literal 69919 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 Ai2wiq literal 5608 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 JF6*2Ung9W-$07g# diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/service/ConfigManager.kt b/app/src/main/java/icu/nullptr/hidemyapplist/service/ConfigManager.kt index 59ffe27..9e736d7 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/service/ConfigManager.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/service/ConfigManager.kt @@ -3,7 +3,10 @@ package icu.nullptr.hidemyapplist.service import android.os.Build import android.util.Log import icu.nullptr.hidemyapplist.common.JsonConfig +import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem import icu.nullptr.hidemyapplist.hmaApp +import icu.nullptr.hidemyapplist.service.ConfigManager.PTType.APP +import icu.nullptr.hidemyapplist.service.ConfigManager.PTType.SETTINGS import icu.nullptr.hidemyapplist.ui.util.showToast import icu.nullptr.hidemyapplist.util.PackageHelper import org.frknkrc44.hma_oss.R @@ -11,13 +14,26 @@ import org.frknkrc44.hma_oss.common.BuildConfig import java.io.File object ConfigManager { - enum class PresetType { + /** + * Indicates the type of preset/template. + * + * @see APP + * @see SETTINGS + */ + enum class PTType { + /** + * This preset/template type is used for app filtering. + */ APP, + + /** + * This preset/template type is used for settings filtering. + */ SETTINGS, } - data class TemplateInfo(val name: String?, val isWhiteList: Boolean) - data class PresetInfo(val name: String, val type: PresetType?, val translation: String) + data class TemplateInfo(val name: String?, val type: PTType, val isWhiteList: Boolean) + data class PresetInfo(val name: String, val type: PTType?, val translation: String) private const val TAG = "ConfigManager" private lateinit var config: JsonConfig @@ -107,6 +123,14 @@ object ConfigManager { saveConfig() } + var packageQueryWorkaround: Boolean + get() = config.packageQueryWorkaround + set(value) { + config.packageQueryWorkaround = value + saveConfig() + PackageHelper.invalidateCache() + } + fun importConfig(json: String) { config = JsonConfig.parse(json) config.configVersion = BuildConfig.CONFIG_VERSION @@ -118,7 +142,7 @@ object ConfigManager { } fun getTemplateList(): MutableList { - return config.templates.mapTo(mutableListOf()) { TemplateInfo(it.key, it.value.isWhitelist) } + return config.templates.mapTo(mutableListOf()) { TemplateInfo(it.key, PTType.APP, it.value.isWhitelist) } } fun getTemplateAppliedAppList(name: String): ArrayList { @@ -167,6 +191,56 @@ object ConfigManager { saveConfig() } + fun getSettingTemplateList(): MutableList { + return config.settingsTemplates.mapTo(mutableListOf()) { TemplateInfo(it.key, PTType.SETTINGS, false) } + } + + fun getSettingTemplateAppliedAppList(name: String): ArrayList { + return config.scope.mapNotNullTo(ArrayList()) { + if (it.value.applySettingTemplates.contains(name)) it.key else null + } + } + + fun getSettingTemplateTargetSettingList(name: String): ArrayList { + return ArrayList(config.settingsTemplates[name]?.settingsList ?: emptyList()) + } + + fun deleteSettingTemplate(name: String) { + config.scope.forEach { (_, appInfo) -> + appInfo.applySettingTemplates.remove(name) + } + config.settingsTemplates.remove(name) + saveConfig() + } + + fun renameSettingTemplate(oldName: String, newName: String) { + if (oldName == newName) return + config.scope.forEach { (_, appInfo) -> + if (appInfo.applySettingTemplates.contains(oldName)) { + appInfo.applySettingTemplates.remove(oldName) + appInfo.applySettingTemplates.add(newName) + } + } + config.settingsTemplates[newName] = config.settingsTemplates[oldName]!! + config.settingsTemplates.remove(oldName) + saveConfig() + } + + fun updateSettingTemplate(name: String, template: JsonConfig.SettingsTemplate) { + Log.d(TAG, "updateSettingTemplate: $name list = ${template.settingsList}") + config.settingsTemplates[name] = template + saveConfig() + } + + fun updateSettingTemplateAppliedApps(name: String, appliedList: List) { + Log.d(TAG, "updateSettingTemplateAppliedApps: $name list = $appliedList") + config.scope.forEach { (app, appInfo) -> + if (appliedList.contains(app)) appInfo.applySettingTemplates.add(name) + else appInfo.applySettingTemplates.remove(name) + } + saveConfig() + } + fun isHideEnabled(packageName: String): Boolean { return config.scope.containsKey(packageName) } diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/service/PrefManager.kt b/app/src/main/java/icu/nullptr/hidemyapplist/service/PrefManager.kt index bb8f817..4e80bdd 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/service/PrefManager.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/service/PrefManager.kt @@ -4,6 +4,7 @@ import android.content.ComponentName import android.content.Context.MODE_PRIVATE import android.content.pm.PackageManager import androidx.appcompat.app.AppCompatDelegate +import androidx.core.content.edit import icu.nullptr.hidemyapplist.hmaApp import org.frknkrc44.hma_oss.BuildConfig @@ -14,6 +15,7 @@ object PrefManager { private const val PREF_LOCALE = "language" private const val PREF_SYSTEM_WALLPAPER = "system_wallpaper" + private const val PREF_SYSTEM_WALLPAPER_ALPHA = "system_wallpaper_alpha" private const val PREF_DARK_THEME = "dark_theme" private const val PREF_BLACK_DARK_THEME = "black_dark_theme" private const val PREF_FOLLOW_SYSTEM_ACCENT = "follow_system_accent" @@ -36,36 +38,40 @@ object PrefManager { var lastVersion: Int get() = pref.getInt(PREF_LAST_VERSION, 0) - set(value) = pref.edit().putInt(PREF_LAST_VERSION, value).apply() + set(value) = pref.edit { putInt(PREF_LAST_VERSION, value) } var locale: String get() = pref.getString(PREF_LOCALE, "SYSTEM")!! - set(value) = pref.edit().putString(PREF_LOCALE, value).apply() + set(value) = pref.edit { putString(PREF_LOCALE, value) } var darkTheme: Int get() = pref.getInt(PREF_DARK_THEME, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) - set(value) = pref.edit().putInt(PREF_DARK_THEME, value).apply() + set(value) = pref.edit { putInt(PREF_DARK_THEME, value) } var systemWallpaper: Boolean get() = pref.getBoolean(PREF_SYSTEM_WALLPAPER, false) - set(value) = pref.edit().putBoolean(PREF_SYSTEM_WALLPAPER, value).apply() + set(value) = pref.edit { putBoolean(PREF_SYSTEM_WALLPAPER, value) } + + var systemWallpaperAlpha: Int + get() = pref.getInt(PREF_SYSTEM_WALLPAPER_ALPHA, 0xAA) + set(value) = pref.edit { putInt(PREF_SYSTEM_WALLPAPER_ALPHA, value) } var blackDarkTheme: Boolean get() = pref.getBoolean(PREF_BLACK_DARK_THEME, false) - set(value) = pref.edit().putBoolean(PREF_BLACK_DARK_THEME, value).apply() + set(value) = pref.edit { putBoolean(PREF_BLACK_DARK_THEME, value) } var followSystemAccent: Boolean get() = pref.getBoolean(PREF_FOLLOW_SYSTEM_ACCENT, true) - set(value) = pref.edit().putBoolean(PREF_FOLLOW_SYSTEM_ACCENT, value).apply() + set(value) = pref.edit { putBoolean(PREF_FOLLOW_SYSTEM_ACCENT, value) } var themeColor: String get() = pref.getString(PREF_THEME_COLOR, "MATERIAL_BLUE")!! - set(value) = pref.edit().putString(PREF_THEME_COLOR, value).apply() + set(value) = pref.edit { putString(PREF_THEME_COLOR, value) } var hideIcon: Boolean get() = pref.getBoolean(PREF_HIDE_ICON, false) set(value) { - pref.edit().putBoolean(PREF_HIDE_ICON, value).apply() + pref.edit { putBoolean(PREF_HIDE_ICON, value) } val component = ComponentName(hmaApp, "${BuildConfig.APPLICATION_ID}.MainActivityLauncher") val status = if (value) PackageManager.COMPONENT_ENABLED_STATE_DISABLED @@ -75,25 +81,25 @@ object PrefManager { var bypassRiskyPackageWarning: Boolean get() = pref.getBoolean(PREF_BYPASS_RISKY_PACKAGE_WARNING, false) - set(value) = pref.edit().putBoolean(PREF_BYPASS_RISKY_PACKAGE_WARNING, value).apply() + set(value) = pref.edit { putBoolean(PREF_BYPASS_RISKY_PACKAGE_WARNING, value) } var appFilter_showSystem: Boolean get() = pref.getBoolean(PREF_APP_FILTER_SHOW_SYSTEM, false) - set(value) = pref.edit().putBoolean(PREF_APP_FILTER_SHOW_SYSTEM, value).apply() + set(value) = pref.edit { putBoolean(PREF_APP_FILTER_SHOW_SYSTEM, value) } var appFilter_sortMethod: SortMethod - get() = SortMethod.values()[pref.getInt(PREF_APP_FILTER_SORT_METHOD, SortMethod.BY_LABEL.ordinal)] - set(value) = pref.edit().putInt(PREF_APP_FILTER_SORT_METHOD, value.ordinal).apply() + get() = SortMethod.entries[pref.getInt(PREF_APP_FILTER_SORT_METHOD, SortMethod.BY_LABEL.ordinal)] + set(value) = pref.edit { putInt(PREF_APP_FILTER_SORT_METHOD, value.ordinal) } var appFilter_reverseOrder: Boolean get() = pref.getBoolean(PREF_APP_FILTER_REVERSE_ORDER, false) - set(value) = pref.edit().putBoolean(PREF_APP_FILTER_REVERSE_ORDER, value).apply() + set(value) = pref.edit { putBoolean(PREF_APP_FILTER_REVERSE_ORDER, value) } var logFilter_level: Int get() = pref.getInt(PREF_LOG_FILTER_LEVEL, 0) - set(value) = pref.edit().putInt(PREF_LOG_FILTER_LEVEL, value).apply() + set(value) = pref.edit { putInt(PREF_LOG_FILTER_LEVEL, value) } var logFilter_reverseOrder: Boolean get() = pref.getBoolean(PREF_LOG_FILTER_REVERSE_ORDER, false) - set(value) = pref.edit().putBoolean(PREF_LOG_FILTER_REVERSE_ORDER, value).apply() + set(value) = pref.edit { putBoolean(PREF_LOG_FILTER_REVERSE_ORDER, value) } } diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/service/ServiceClient.kt b/app/src/main/java/icu/nullptr/hidemyapplist/service/ServiceClient.kt index 1ca1694..ea3203e 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/service/ServiceClient.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/service/ServiceClient.kt @@ -73,4 +73,13 @@ object ServiceClient : IHMAService, IBinder.DeathRecipient { override fun log(level: Int, tag: String, message: String) { service?.log(level, tag, message) } + + override fun getPackageNames(userId: Int) = service?.getPackageNames(userId) + + override fun getPackageInfo( + packageName: String?, + userId: Int + ) = service?.getPackageInfo(packageName, userId) + + override fun listAllSettings(databaseName: String) = service?.listAllSettings(databaseName) ?: arrayOf() } \ No newline at end of file diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/adapter/TemplateAdapter.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/adapter/TemplateAdapter.kt index b0881d2..deef82f 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/adapter/TemplateAdapter.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/adapter/TemplateAdapter.kt @@ -29,8 +29,13 @@ class TemplateAdapter( fun bind(info: ConfigManager.TemplateInfo) { with(itemView as ListItemView) { setIcon( - if (info.isWhiteList) R.drawable.outline_assignment_24 - else R.drawable.baseline_assignment_24 + when (info.type) { + ConfigManager.PTType.APP -> { + if (info.isWhiteList) R.drawable.outline_assignment_24 + else R.drawable.baseline_assignment_24 + } + ConfigManager.PTType.SETTINGS -> R.drawable.baseline_settings_24 + } ) text = info.name } @@ -54,9 +59,13 @@ class TemplateAdapter( @SuppressLint("NotifyDataSetChanged") fun updateList() { - list = ConfigManager.getTemplateList().apply { + val allItems = (ConfigManager.getTemplateList() + ConfigManager.getSettingTemplateList()).toMutableList() + + list = allItems.apply { sortWith { o1, o2 -> - if (o1.isWhiteList != o2.isWhiteList) { + if (o1.type != o2.type) { + o1.type.compareTo(o2.type) + } else if (o1.isWhiteList != o2.isWhiteList) { o1.isWhiteList.compareTo(o2.isWhiteList) } else { Collator.getInstance(Locale.getDefault()).compare(o1.name, o2.name) diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSelectFragment.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSelectFragment.kt index c4054a5..0ebb12d 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSelectFragment.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSelectFragment.kt @@ -138,7 +138,7 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) { adapter.registerAdapterDataObserver( EmptyDataObserver( binding.list, - binding.listEmptyContainer + binding.listEmptyContainer.root ) ) @@ -159,7 +159,7 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) { binding.root.setOnApplyWindowInsetsListener { v, insets -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( + v.setPadding( barInsets.left, barInsets.top, barInsets.right, @@ -167,7 +167,7 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) { ) } else { @Suppress("deprecation") - binding.root.setPadding( + v.setPadding( insets.systemWindowInsetLeft, insets.systemWindowInsetTop, insets.systemWindowInsetRight, diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSettingsFragment.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSettingsFragment.kt index c4b6e54..13a2df2 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSettingsFragment.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSettingsFragment.kt @@ -9,6 +9,7 @@ import android.view.WindowInsets import android.widget.Toast import androidx.activity.addCallback import androidx.core.graphics.drawable.toDrawable +import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.clearFragmentResultListener import androidx.fragment.app.setFragmentResultListener @@ -35,6 +36,7 @@ import icu.nullptr.hidemyapplist.util.PackageHelper import org.frknkrc44.hma_oss.BuildConfig import org.frknkrc44.hma_oss.R import org.frknkrc44.hma_oss.databinding.FragmentSettingsBinding +import org.frknkrc44.hma_oss.databinding.LayoutListEmptyBinding class AppSettingsFragment : Fragment(R.layout.fragment_settings) { companion object { @@ -65,11 +67,6 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { saveConfig() } - override fun onDestroyView() { - super.onDestroyView() - saveConfig() - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack() } setupToolbar( @@ -88,7 +85,7 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { binding.root.setOnApplyWindowInsetsListener { v, insets -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( + v.setPadding( barInsets.left, barInsets.top, barInsets.right, @@ -96,7 +93,7 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { ) } else { @Suppress("deprecation") - binding.root.setPadding( + v.setPadding( insets.systemWindowInsetLeft, insets.systemWindowInsetTop, insets.systemWindowInsetRight, @@ -119,6 +116,7 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { "hideSystemInstallationSource" -> pack.config.hideSystemInstallationSource "excludeTargetInstallationSource" -> pack.config.excludeTargetInstallationSource "invertActivityLaunchProtection" -> pack.config.invertActivityLaunchProtection + "excludeVoldIsolation" -> pack.config.excludeVoldIsolation else -> throw IllegalArgumentException("Invalid key: $key") } } @@ -132,6 +130,7 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { "hideSystemInstallationSource" -> pack.config.hideSystemInstallationSource = value "excludeTargetInstallationSource" -> pack.config.excludeTargetInstallationSource = value "invertActivityLaunchProtection" -> pack.config.invertActivityLaunchProtection = value + "excludeVoldIsolation" -> pack.config.excludeVoldIsolation = value else -> throw IllegalArgumentException("Invalid key: $key") } } @@ -147,9 +146,11 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { getString(R.string.app_template_using, pack.config.applyTemplates.size) } - private fun updateApplyPresets() { - findPreference("applyPresets")?.title = - getString(R.string.app_preset_using, pack.config.applyPresets.size) + private fun updateApplyPresets(useWhitelist: Boolean = pack.config.useWhitelist) { + findPreference("applyPresets")?.apply { + isVisible = !useWhitelist + title = getString(R.string.app_preset_using, pack.config.applyPresets.size) + } } private fun updateApplySettingsPresets() { @@ -157,6 +158,11 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { getString(R.string.app_settings_preset_using, pack.config.applySettingsPresets.size) } + private fun updateApplySettingsTemplates() { + findPreference("applySettingsTemplates")?.title = + getString(R.string.app_settings_template_using, pack.config.applySettingTemplates.size) + } + private fun updateExtraAppList(useWhiteList: Boolean) { findPreference("extraAppList")?.title = if (useWhiteList) getString(R.string.app_extra_apps_visible_count, pack.config.extraAppList.size) @@ -225,6 +231,9 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { R.string.app_force_stop_warning, Toast.LENGTH_LONG).show() true } + findPreference("excludeVoldIsolation")?.let { + it.isEnabled = ConfigManager.altVoldAppDataIsolation + } findPreference("invertActivityLaunchProtection")?.let { it.summary = getString(R.string.app_invert_activity_launch_protection_desc) + "\n\n" + getString(R.string.app_global_activity_launch_protection_state, @@ -232,11 +241,14 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { ) } findPreference("useWhiteList")?.setOnPreferenceChangeListener { _, newValue -> + val useWhitelist = newValue as Boolean + pack.config.applyTemplates.clear() pack.config.extraAppList.clear() + pack.config.applyPresets.clear() updateApplyTemplates() - updateApplyPresets() - updateExtraAppList(newValue as Boolean) + updateApplyPresets(useWhitelist) + updateExtraAppList(useWhitelist) true } findPreference("applyTemplates")?.setOnPreferenceClickListener { @@ -246,9 +258,9 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { val checked = templates.map { pack.config.applyTemplates.contains(it) }.toBooleanArray() - MaterialAlertDialogBuilder(requireContext()) + + val dialog = MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.app_choose_template) - .setMultiChoiceItems(templates, checked) { _, i, value -> checked[i] = value } .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(android.R.string.ok) { _, _ -> pack.config.applyTemplates = templates.mapIndexedNotNullTo(mutableSetOf()) { i, name -> @@ -256,7 +268,21 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { } updateApplyTemplates() } - .show() + + if (templates.isNotEmpty()) { + dialog.setMultiChoiceItems(templates, checked) { _, i, value -> + checked[i] = value + } + } else { + val emptyView = LayoutListEmptyBinding.inflate(layoutInflater) + emptyView.root.isVisible = true + emptyView.listEmptyIcon.setImageResource(R.drawable.sentiment_very_dissatisfied_24px) + emptyView.listEmptyText.text = getString(R.string.title_template_manage) + dialog.setView(emptyView.root) + } + + dialog.show() + true } findPreference("applyPresets")?.setOnPreferenceClickListener { @@ -293,6 +319,37 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { .show() true } + findPreference("applySettingsTemplates")?.apply { + setOnPreferenceClickListener { + val templates = ConfigManager.getSettingTemplateList().mapNotNull { it.name }.toTypedArray() + val checked = templates.map { + pack.config.applySettingTemplates.contains(it) + }.toBooleanArray() + + val dialog = MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.app_choose_template) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(android.R.string.ok) { _, _ -> + pack.config.applySettingTemplates = templates.mapIndexedNotNullTo(mutableSetOf()) { i, name -> + if (checked[i]) name else null + } + updateApplySettingsTemplates() + } + + if (templates.isNotEmpty()) { + dialog.setMultiChoiceItems(templates, checked) { _, i, value -> checked[i] = value } + } else { + val emptyView = LayoutListEmptyBinding.inflate(layoutInflater) + emptyView.root.isVisible = true + emptyView.listEmptyIcon.setImageResource(R.drawable.sentiment_very_dissatisfied_24px) + emptyView.listEmptyText.text = getString(R.string.title_template_manage) + dialog.setView(emptyView.root) + } + + dialog.show() + true + } + } findPreference("applySettingsPresets")?.setOnPreferenceClickListener { val presetNames = SettingsPresets.instance.getAllPresetNames() val presetTranslations = presetNames.map { name -> @@ -343,6 +400,7 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) { } updateApplyTemplates() updateApplyPresets() + updateApplySettingsTemplates() updateApplySettingsPresets() updateExtraAppList(pack.config.useWhitelist) } diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/LogsFragment.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/LogsFragment.kt index b20fdc3..4d7648f 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/LogsFragment.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/LogsFragment.kt @@ -146,7 +146,7 @@ class LogsFragment : Fragment(R.layout.fragment_logs) { binding.root.setOnApplyWindowInsetsListener { v, insets -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( + v.setPadding( barInsets.left, barInsets.top, barInsets.right, @@ -154,7 +154,7 @@ class LogsFragment : Fragment(R.layout.fragment_logs) { ) } else { @Suppress("deprecation") - binding.root.setPadding( + v.setPadding( insets.systemWindowInsetLeft, insets.systemWindowInsetTop, insets.systemWindowInsetRight, diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/SettingsFragment.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/SettingsFragment.kt index 2173173..a26f724 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/SettingsFragment.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/SettingsFragment.kt @@ -14,6 +14,7 @@ import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.PreferenceDataStore import androidx.preference.PreferenceFragmentCompat +import androidx.preference.SeekBarPreference import androidx.preference.SwitchPreferenceCompat import by.kirich1409.viewbindingdelegate.viewBinding import com.google.android.material.color.DynamicColors @@ -34,6 +35,7 @@ import icu.nullptr.hidemyapplist.util.SuUtils import kotlinx.coroutines.launch import org.frknkrc44.hma_oss.R import org.frknkrc44.hma_oss.databinding.FragmentSettingsBinding +import org.frknkrc44.hma_oss.ui.activity.BaseActivity import java.util.Locale class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { @@ -60,7 +62,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen binding.root.setOnApplyWindowInsetsListener { v, insets -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( + v.setPadding( barInsets.left, barInsets.top, barInsets.right, @@ -68,7 +70,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen ) } else { @Suppress("deprecation") - binding.root.setPadding( + v.setPadding( insets.systemWindowInsetLeft, insets.systemWindowInsetTop, insets.systemWindowInsetRight, @@ -104,6 +106,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen "skipSystemAppDataIsolation" -> ConfigManager.skipSystemAppDataIsolation "disableActivityLaunchProtection" -> ConfigManager.disableActivityLaunchProtection "forceMountData" -> ConfigManager.forceMountData + "packageQueryWorkaround" -> ConfigManager.packageQueryWorkaround else -> throw IllegalArgumentException("Invalid key: $key") } } @@ -118,6 +121,13 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen } } + override fun getInt(key: String, defValue: Int): Int { + return when (key) { + "systemWallpaperAlpha" -> PrefManager.systemWallpaperAlpha + else -> throw IllegalArgumentException("Invalid key: $key") + } + } + override fun putBoolean(key: String, value: Boolean) { when (key) { "followSystemAccent" -> PrefManager.followSystemAccent = value @@ -131,6 +141,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen "appDataIsolation" -> ConfigManager.altAppDataIsolation = value "voldAppDataIsolation" -> ConfigManager.altVoldAppDataIsolation = value "skipSystemAppDataIsolation" -> ConfigManager.skipSystemAppDataIsolation = value + "packageQueryWorkaround" -> ConfigManager.packageQueryWorkaround = value else -> throw IllegalArgumentException("Invalid key: $key") } } @@ -144,6 +155,13 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen else -> throw IllegalArgumentException("Invalid key: $key") } } + + override fun putInt(key: String, value: Int) { + when (key) { + "systemWallpaperAlpha" -> PrefManager.systemWallpaperAlpha = value + else -> throw IllegalArgumentException("Invalid key: $key") + } + } } class DataIsolationPreferenceFragment : PreferenceFragmentCompat() { @@ -289,6 +307,14 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen } } + findPreference("systemWallpaperAlpha")?.apply { + setOnPreferenceChangeListener { _, value -> + (requireActivity() as BaseActivity).applyWallpaperBackgroundColor(value as Int) + + true + } + } + findPreference("clearUninstalledPackageConfigs")?.apply { setOnPreferenceClickListener { MaterialAlertDialogBuilder(requireContext()) @@ -313,9 +339,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen } } } - .setNegativeButton(android.R.string.cancel) { _, _ -> - // do nothing - } + .setNegativeButton(android.R.string.cancel, null) .setCancelable(false) .show() diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateManageFragment.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateManageFragment.kt index d0308fa..56bd92f 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateManageFragment.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateManageFragment.kt @@ -4,13 +4,12 @@ import android.os.Build import android.os.Bundle import android.view.View import android.view.WindowInsets -import androidx.core.view.doOnPreDraw import androidx.fragment.app.Fragment import androidx.fragment.app.clearFragmentResultListener import androidx.fragment.app.setFragmentResultListener -import androidx.navigation.fragment.FragmentNavigatorExtras import androidx.recyclerview.widget.LinearLayoutManager import by.kirich1409.viewbindingdelegate.viewBinding +import com.google.android.material.dialog.MaterialAlertDialogBuilder import icu.nullptr.hidemyapplist.common.JsonConfig import icu.nullptr.hidemyapplist.service.ConfigManager import icu.nullptr.hidemyapplist.ui.adapter.TemplateAdapter @@ -19,6 +18,8 @@ import icu.nullptr.hidemyapplist.ui.util.navigate import icu.nullptr.hidemyapplist.ui.util.setupToolbar import org.frknkrc44.hma_oss.R import org.frknkrc44.hma_oss.databinding.FragmentTemplateManageBinding +import org.frknkrc44.hma_oss.ui.fragment.SettingsTemplateConfFragmentArgs +import org.frknkrc44.hma_oss.ui.util.toTargetSettingList class TemplateManageFragment : Fragment(R.layout.fragment_template_manage) { @@ -30,16 +31,29 @@ class TemplateManageFragment : Fragment(R.layout.fragment_template_manage) { toolbar = binding.toolbar, title = getString(R.string.title_template_manage), navigationIcon = R.drawable.baseline_arrow_back_24, - navigationOnClick = { navController.navigateUp() } + navigationOnClick = { navController.navigateUp() }, + menuRes = R.menu.menu_template_manage, + onMenuOptionSelected = { + when (it.itemId) { + R.id.menu_info -> { + MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.title_template_manage) + .setMessage(R.string.template_usage_hint) + .setNegativeButton(android.R.string.ok, null) + .show() + } + } + } ) - postponeEnterTransition() - view.doOnPreDraw { startPostponedEnterTransition() } binding.newBlacklistTemplate.setOnClickListener { - navigateToSettings(ConfigManager.TemplateInfo(null, false)) + navigateToSettings(ConfigManager.TemplateInfo(null, ConfigManager.PTType.APP, false)) } binding.newWhitelistTemplate.setOnClickListener { - navigateToSettings(ConfigManager.TemplateInfo(null, true)) + navigateToSettings(ConfigManager.TemplateInfo(null, ConfigManager.PTType.APP, true)) + } + binding.newSettingTemplate.setOnClickListener { + navigateToSettings(ConfigManager.TemplateInfo(null, ConfigManager.PTType.SETTINGS, false)) } binding.templateList.layoutManager = LinearLayoutManager(context) binding.templateList.adapter = adapter @@ -47,7 +61,7 @@ class TemplateManageFragment : Fragment(R.layout.fragment_template_manage) { binding.root.setOnApplyWindowInsetsListener { v, insets -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( + v.setPadding( barInsets.left, barInsets.top, barInsets.right, @@ -55,7 +69,7 @@ class TemplateManageFragment : Fragment(R.layout.fragment_template_manage) { ) } else { @Suppress("deprecation") - binding.root.setPadding( + v.setPadding( insets.systemWindowInsetLeft, insets.systemWindowInsetTop, insets.systemWindowInsetRight, @@ -68,6 +82,13 @@ class TemplateManageFragment : Fragment(R.layout.fragment_template_manage) { } private fun navigateToSettings(info: ConfigManager.TemplateInfo) { + when (info.type) { + ConfigManager.PTType.APP -> navigateToAppTemplateSettings(info) + ConfigManager.PTType.SETTINGS -> navigateToSettingTemplateSettings(info) + } + } + + private fun navigateToAppTemplateSettings(info: ConfigManager.TemplateInfo) { setFragmentResultListener("template_settings") { _, bundle -> fun deal() { var name = bundle.getString("name") @@ -94,7 +115,42 @@ class TemplateManageFragment : Fragment(R.layout.fragment_template_manage) { } val args = TemplateSettingsFragmentArgs(info.name, info.isWhiteList) - val extras = FragmentNavigatorExtras(binding.hintCard to "transition_manage") - navigate(R.id.nav_template_settings, args.toBundle(), extras) + navigate(R.id.nav_template_settings, args.toBundle()) + } + + private fun navigateToSettingTemplateSettings(info: ConfigManager.TemplateInfo) { + setFragmentResultListener("settings_template_conf") { _, bundle -> + fun deal() { + var name = bundle.getString("name") + val appliedList = bundle.getStringArrayList("appliedList")!! + val targetList = bundle.getBundle("settingList")!!.toTargetSettingList() + if (info.name == null) { // New template + if (name.isNullOrEmpty()) return + ConfigManager.updateSettingTemplate( + name, + JsonConfig.SettingsTemplate(targetList.toSet()) + ) + ConfigManager.updateSettingTemplateAppliedApps(name, appliedList) + } else { // Existing template + if (name == null) { + ConfigManager.deleteSettingTemplate(info.name) + } else { + if (name.isEmpty()) name = info.name + if (name != info.name) ConfigManager.renameSettingTemplate(info.name, name) + ConfigManager.updateSettingTemplate( + name, + JsonConfig.SettingsTemplate(targetList.toSet()) + ) + ConfigManager.updateSettingTemplateAppliedApps(name, appliedList) + } + } + } + deal() + adapter.updateList() + clearFragmentResultListener("settings_template_conf") + } + + val args = SettingsTemplateConfFragmentArgs(info.name) + navigate(R.id.nav_setting_template_conf, args.toBundle()) } } diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateSettingsFragment.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateSettingsFragment.kt index 6fabf14..dfb5f4a 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateSettingsFragment.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateSettingsFragment.kt @@ -114,7 +114,7 @@ class TemplateSettingsFragment : Fragment(R.layout.fragment_template_settings) { binding.root.setOnApplyWindowInsetsListener { v, insets -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( + v.setPadding( barInsets.left, barInsets.top, barInsets.right, @@ -122,7 +122,7 @@ class TemplateSettingsFragment : Fragment(R.layout.fragment_template_settings) { ) } else { @Suppress("deprecation") - binding.root.setPadding( + v.setPadding( insets.systemWindowInsetLeft, insets.systemWindowInsetTop, insets.systemWindowInsetRight, diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/util/Fragment.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/util/Fragment.kt index f1db7f0..15722a9 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/util/Fragment.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/util/Fragment.kt @@ -12,7 +12,6 @@ import androidx.appcompat.widget.Toolbar import androidx.core.view.MenuProvider import androidx.fragment.app.Fragment import androidx.navigation.NavOptions -import androidx.navigation.Navigator import androidx.navigation.fragment.NavHostFragment import org.frknkrc44.hma_oss.R @@ -31,10 +30,6 @@ fun Fragment.navigate(@IdRes resId: Int, args: Bundle? = null) { navController.navigate(resId, args, navOptions) } -fun Fragment.navigate(@IdRes resId: Int, args: Bundle? = null, navExtras: Navigator.Extras?) { - navController.navigate(resId, args, navOptions, navExtras) -} - fun Fragment.setupToolbar( toolbar: Toolbar, title: String, diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/view/ListItemView.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/view/ListItemView.kt index f1efdad..2f726e5 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/view/ListItemView.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/view/ListItemView.kt @@ -19,7 +19,7 @@ class ListItemView @JvmOverloads constructor( defStyleRes: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) { - private val binding by viewBinding(createMethod = CreateMethod.INFLATE) + val binding by viewBinding(createMethod = CreateMethod.INFLATE) init { val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.ListItemView, defStyleAttr, defStyleRes) diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt b/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt index 6147f20..a04bb0e 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt @@ -6,7 +6,9 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import icu.nullptr.hidemyapplist.common.Constants import icu.nullptr.hidemyapplist.hmaApp +import icu.nullptr.hidemyapplist.service.ConfigManager import icu.nullptr.hidemyapplist.service.PrefManager +import icu.nullptr.hidemyapplist.service.ServiceClient import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.first @@ -74,14 +76,30 @@ object PackageHelper { isRefreshing.emit(true) val cache = withContext(Dispatchers.IO) { val pm = hmaApp.packageManager - val packages = pm.getInstalledPackages(0) - mutableMapOf().also { - for (packageInfo in packages) { - if (packageInfo.packageName in Constants.packagesShouldNotHide) continue - packageInfo.applicationInfo?.let { appInfo -> - val label = pm.getApplicationLabel(appInfo).toString() - val icon = hmaApp.appIconLoader.loadIcon(appInfo) - it[packageInfo.packageName] = PackageCache(packageInfo, label, icon) + + if (ConfigManager.packageQueryWorkaround) { + val packages = ServiceClient.getPackageNames(0) ?: arrayOf() + mutableMapOf().also { + for (packageName in packages) { + val packageInfo = ServiceClient.getPackageInfo(packageName, 0)!! + if (packageInfo.packageName in Constants.packagesShouldNotHide) continue + packageInfo.applicationInfo?.let { appInfo -> + val label = pm.getApplicationLabel(appInfo).toString() + val icon = hmaApp.appIconLoader.loadIcon(appInfo) + it[packageInfo.packageName] = PackageCache(packageInfo, label, icon) + } + } + } + } else { + val packages = pm.getInstalledPackages(0) + mutableMapOf().also { + for (packageInfo in packages) { + if (packageInfo.packageName in Constants.packagesShouldNotHide) continue + packageInfo.applicationInfo?.let { appInfo -> + val label = pm.getApplicationLabel(appInfo).toString() + val icon = hmaApp.appIconLoader.loadIcon(appInfo) + it[packageInfo.packageName] = PackageCache(packageInfo, label, icon) + } } } } diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/activity/BaseActivity.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/activity/BaseActivity.kt index c7b6f08..a3e628d 100644 --- a/app/src/main/java/org/frknkrc44/hma_oss/ui/activity/BaseActivity.kt +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/activity/BaseActivity.kt @@ -5,9 +5,11 @@ import android.content.res.Resources import android.os.Bundle import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity +import androidx.core.graphics.drawable.toDrawable import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColorsOptions import icu.nullptr.hidemyapplist.hmaApp +import icu.nullptr.hidemyapplist.service.PrefManager import icu.nullptr.hidemyapplist.ui.util.ThemeUtils import icu.nullptr.hidemyapplist.util.ConfigUtils.Companion.getLocale @@ -17,6 +19,11 @@ open class BaseActivity : AppCompatActivity() { enableEdgeToEdge() + // I add this manually because the E2E code is not working like I want + // They should give us a separate method to choice it for enableEdgeToEdge + // Source: https://github.com/androidx/androidx/blob/c0f9aabcf6f32029249ac7647711744b68e2a003/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt#L299 + window.isNavigationBarContrastEnforced = !PrefManager.systemWallpaper + DynamicColors.applyToActivityIfAvailable( this, DynamicColorsOptions.Builder().also { @@ -33,6 +40,20 @@ open class BaseActivity : AppCompatActivity() { } theme.applyStyle(ThemeUtils.getOverlayThemeStyleRes(this), true) + + applyWallpaperBackgroundColor() + } + + fun applyWallpaperBackgroundColor(value: Int = PrefManager.systemWallpaperAlpha) { + if (PrefManager.systemWallpaper) { + val color = (value shl 24) + if (ThemeUtils.isNightMode(this)) { + 0x00000000 + } else { + 0x00FFFFFF + } + + window.setBackgroundDrawable(color.toDrawable()) + } } override fun attachBaseContext(newBase: Context?) { diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetListAdapter.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetListAdapter.kt index 37f0701..e944661 100644 --- a/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetListAdapter.kt +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetListAdapter.kt @@ -30,8 +30,8 @@ class AppPresetListAdapter( } else { setIcon( when (item.type) { - ConfigManager.PresetType.APP -> R.drawable.baseline_assignment_24 - ConfigManager.PresetType.SETTINGS -> R.drawable.baseline_settings_24 + ConfigManager.PTType.APP -> R.drawable.baseline_assignment_24 + ConfigManager.PTType.SETTINGS -> R.drawable.baseline_settings_24 } ) @@ -88,7 +88,7 @@ class AppPresetListAdapter( list += appPresetNames .map { ConfigManager.PresetInfo( it, - ConfigManager.PresetType.APP, + ConfigManager.PTType.APP, appPresetTranslations[appPresetNames.indexOf(it)] ) } .sortedWith { a, b -> a.translation.lowercase().compareTo(b.translation.lowercase()) } @@ -117,7 +117,7 @@ class AppPresetListAdapter( list += settingsPresetNames .map { ConfigManager.PresetInfo( it, - ConfigManager.PresetType.SETTINGS, + ConfigManager.PTType.SETTINGS, settingsPresetTranslations[settingsPresetNames.indexOf(it)] ) } .sortedWith { a, b -> a.translation.lowercase().compareTo(b.translation.lowercase()) } diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/BaseSettingsPTAdapter.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/BaseSettingsPTAdapter.kt new file mode 100644 index 0000000..f6b63dc --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/BaseSettingsPTAdapter.kt @@ -0,0 +1,40 @@ +package org.frknkrc44.hma_oss.ui.adapter + +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.recyclerview.widget.RecyclerView +import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem +import icu.nullptr.hidemyapplist.ui.view.AppItemView + +abstract class BaseSettingsPTAdapter() : RecyclerView.Adapter() { + abstract val items: List + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = AppItemView(parent.context, false).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + } + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position]) + + override fun getItemCount() = items.size + + abstract fun onItemClick(item: ReplacementItem) + + inner class ViewHolder(view: AppItemView) : RecyclerView.ViewHolder(view) { + fun bind(item: ReplacementItem) { + (itemView as AppItemView).apply { + binding.icon.isVisible = false + binding.label.text = item.name + binding.enabled.isVisible = true + binding.enabled.text = item.database + binding.packageName.text = item.value ?: "null" + binding.root.setOnClickListener { onItemClick(item) } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/SettingsPresetListAdapter.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/SettingsPresetListAdapter.kt index ce43d35..398781e 100644 --- a/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/SettingsPresetListAdapter.kt +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/SettingsPresetListAdapter.kt @@ -1,37 +1,14 @@ package org.frknkrc44.hma_oss.ui.adapter -import android.view.ViewGroup -import androidx.core.view.isVisible -import androidx.recyclerview.widget.RecyclerView import icu.nullptr.hidemyapplist.common.SettingsPresets import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem -import icu.nullptr.hidemyapplist.ui.view.AppItemView -class SettingsPresetListAdapter(presetName: String) : RecyclerView.Adapter() { - private val presetItems by lazy { - SettingsPresets.instance.getPresetByName(presetName)!!.settingsKVPairs.sortedBy { it.name } +class SettingsPresetListAdapter(name: String) : BaseSettingsPTAdapter() { + override val items by lazy { + SettingsPresets.instance.getPresetByName(name)!!.settingsKVPairs.sortedBy { it.name } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val view = AppItemView(parent.context, false) - view.layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - return ViewHolder(view) - } - - override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(presetItems[position]) - - override fun getItemCount() = presetItems.size - - class ViewHolder(view: AppItemView) : RecyclerView.ViewHolder(view) { - fun bind(item: ReplacementItem) { - (itemView as AppItemView).apply { - binding.icon.isVisible = false - binding.label.text = item.name - binding.packageName.text = item.value ?: "null" - } - } + override fun onItemClick(item: ReplacementItem) { + // do nothing } } \ No newline at end of file diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/SettingsTemplateListAdapter.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/SettingsTemplateListAdapter.kt new file mode 100644 index 0000000..8fd8a35 --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/SettingsTemplateListAdapter.kt @@ -0,0 +1,21 @@ +package org.frknkrc44.hma_oss.ui.adapter + +import android.os.Bundle +import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem +import org.frknkrc44.hma_oss.ui.util.targetSettingListToBundle +import org.frknkrc44.hma_oss.ui.util.toTargetSettingList + +class SettingsTemplateListAdapter( + items: Bundle, + private val onItemClickListener: (SettingsTemplateListAdapter, ReplacementItem) -> Unit +) : BaseSettingsPTAdapter() { + override val items by lazy { + val list = mutableListOf() + list.addAll(items.toTargetSettingList()) + return@lazy list + } + + fun targetSettingListToBundle() = items.targetSettingListToBundle() + + override fun onItemClick(item: ReplacementItem) = onItemClickListener(this, item) +} \ No newline at end of file diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AboutFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AboutFragment.kt index f65a8ff..c084b90 100644 --- a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AboutFragment.kt +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AboutFragment.kt @@ -2,14 +2,19 @@ package org.frknkrc44.hma_oss.ui.fragment import android.content.Intent import android.content.res.ColorStateList +import android.graphics.BitmapFactory import android.os.Build import android.os.Bundle import android.view.View import android.view.WindowInsets import android.widget.LinearLayout import androidx.annotation.DrawableRes +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory import androidx.core.net.toUri +import androidx.core.view.isVisible import androidx.fragment.app.Fragment +import androidx.transition.AutoTransition +import androidx.transition.TransitionManager import by.kirich1409.viewbindingdelegate.viewBinding import com.bumptech.glide.Glide import icu.nullptr.hidemyapplist.service.PrefManager @@ -31,7 +36,7 @@ class AboutFragment : Fragment(R.layout.fragment_about) { binding.root.setOnApplyWindowInsetsListener { v, insets -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( + v.setPadding( barInsets.left, barInsets.top, barInsets.right, @@ -41,7 +46,7 @@ class AboutFragment : Fragment(R.layout.fragment_about) { binding.bottomPadding.minimumHeight = barInsets.bottom } else { @Suppress("deprecation") - binding.root.setPadding( + v.setPadding( insets.systemWindowInsetLeft, insets.systemWindowInsetTop, insets.systemWindowInsetRight, @@ -53,10 +58,6 @@ class AboutFragment : Fragment(R.layout.fragment_about) { insets } - } - - override fun onStart() { - super.onStart() val tint = ColorStateList.valueOf(homeItemBackgroundColor()) @@ -67,7 +68,7 @@ class AboutFragment : Fragment(R.layout.fragment_about) { } Glide.with(this@AboutFragment) - .load(R.mipmap.ic_launcher_round) + .load(R.mipmap.ic_launcher) .circleCrop() .into(appIcon) @@ -101,11 +102,28 @@ class AboutFragment : Fragment(R.layout.fragment_about) { with(binding.listDeveloper) { backgroundTintList = tint clipToOutline = true + } - // HMA-OSS devs + with(binding.devHeader) { + setOnClickListener { + if (binding.listHma.isVisible) { + binding.expandDevs.animate().rotation(0.0f).start() + } else { + TransitionManager.beginDelayedTransition(binding.listDeveloper, AutoTransition()) + binding.expandDevs.animate().rotation(180.0f).start() + } + + binding.listHma.isVisible = !binding.listHma.isVisible + } + } + + // HMA-OSS devs + with(binding.listHmaOss) { addDevItem(this, R.drawable.cont_fk, "frknkrc44", "HMA-OSS Developer", "https://github.com/frknkrc44") + } - // Original HMA devs + // Original HMA devs + with(binding.listHma) { addDevItem(this, R.drawable.cont_nullptr, "nullptr", "HMA Developer", "https://github.com/Dr-TSNG") addDevItem(this, R.drawable.cont_k, "Ketal", "HMA Collaborator", "https://github.com/keta1") addDevItem(this, R.drawable.cont_aviraxp, "aviraxp", "HMA Collaborator", "https://github.com/aviraxp") @@ -130,10 +148,12 @@ class AboutFragment : Fragment(R.layout.fragment_about) { val newLayout = FragmentAboutListItemBinding.inflate(layoutInflater) setOnClickUrl(newLayout.root, url) - Glide.with(this) - .load(avatarResId) - .circleCrop() - .into(newLayout.aboutPersonIcon) + newLayout.aboutPersonIcon.setImageDrawable(RoundedBitmapDrawableFactory.create( + resources, + BitmapFactory.decodeResource(resources, avatarResId) + ).apply { + isCircular = true + }) newLayout.text1.text = name newLayout.text2.text = desc @@ -142,6 +162,7 @@ class AboutFragment : Fragment(R.layout.fragment_about) { fun addTranslatorItem(layout: LinearLayout, avatarUrl: String, name: String) { val newLayout = FragmentAboutListItemBinding.inflate(layoutInflater) + Glide.with(this) .load(avatarUrl) .placeholder(R.drawable.outline_info_24) diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AppPresetFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AppPresetFragment.kt index 3ada7a2..b5953ca 100644 --- a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AppPresetFragment.kt +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AppPresetFragment.kt @@ -16,15 +16,11 @@ class AppPresetFragment() : AppSelectFragment() { override val firstComparator: Comparator = Comparator.comparing(PackageHelper::exists).reversed() - override val adapter by lazy { - val args by navArgs() - AppPresetAdapter(args.presetName) - } + private val args by lazy { navArgs() } - override fun getFragmentTitle(): String { - val args by navArgs() - return args.presetTitle - } + override val adapter by lazy { AppPresetAdapter(args.value.name) } + + override fun getFragmentTitle() = args.value.title override fun sortList() { hmaApp.globalScope.launch { diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/BaseSettingsPTFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/BaseSettingsPTFragment.kt new file mode 100644 index 0000000..4126076 --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/BaseSettingsPTFragment.kt @@ -0,0 +1,73 @@ +package org.frknkrc44.hma_oss.ui.fragment + +import android.os.Build +import android.os.Bundle +import android.view.MenuItem +import android.view.View +import android.view.WindowInsets +import androidx.activity.addCallback +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import by.kirich1409.viewbindingdelegate.viewBinding +import icu.nullptr.hidemyapplist.ui.util.navController +import icu.nullptr.hidemyapplist.ui.util.setupToolbar +import org.frknkrc44.hma_oss.R +import org.frknkrc44.hma_oss.databinding.FragmentSettingsPtBaseBinding +import org.frknkrc44.hma_oss.ui.adapter.BaseSettingsPTAdapter + +abstract class BaseSettingsPTFragment : Fragment(R.layout.fragment_settings_pt_base) { + val binding by viewBinding() + + abstract val adapter: BaseSettingsPTAdapter + + abstract val title: String? + + internal open fun onBack() { + navController.navigateUp() + } + + /** + * first - menuRes, second - onMenuOptionSelected + */ + abstract val menu: Pair Unit)>? + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack() } + + setupToolbar( + toolbar = binding.toolbar, + title = title ?: "", + navigationIcon = R.drawable.baseline_arrow_back_24, + navigationOnClick = { onBack() }, + menuRes = menu?.first, + onMenuOptionSelected = menu?.second, + ) + + binding.list.layoutManager = LinearLayoutManager(context) + binding.list.adapter = adapter + + binding.root.setOnApplyWindowInsetsListener { v, insets -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) + v.setPadding( + barInsets.left, + barInsets.top, + barInsets.right, + barInsets.bottom, + ) + } else { + @Suppress("deprecation") + v.setPadding( + insets.systemWindowInsetLeft, + insets.systemWindowInsetTop, + insets.systemWindowInsetRight, + insets.systemWindowInsetBottom, + ) + } + + insets + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/EditSettingFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/EditSettingFragment.kt new file mode 100644 index 0000000..3270377 --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/EditSettingFragment.kt @@ -0,0 +1,134 @@ +package org.frknkrc44.hma_oss.ui.fragment + +import android.os.Build +import android.os.Bundle +import android.view.View +import android.view.WindowInsets +import androidx.activity.addCallback +import androidx.fragment.app.Fragment +import androidx.fragment.app.setFragmentResult +import androidx.navigation.fragment.navArgs +import by.kirich1409.viewbindingdelegate.viewBinding +import com.google.android.material.textfield.MaterialAutoCompleteTextView +import com.google.android.material.textfield.TextInputLayout +import icu.nullptr.hidemyapplist.common.Constants +import icu.nullptr.hidemyapplist.service.ServiceClient +import icu.nullptr.hidemyapplist.ui.util.navController +import icu.nullptr.hidemyapplist.ui.util.setupToolbar +import org.frknkrc44.hma_oss.R +import org.frknkrc44.hma_oss.databinding.FragmentEditSettingBinding + +class EditSettingFragment : Fragment(R.layout.fragment_edit_setting) { + private val binding by viewBinding() + + private val args by navArgs() + + fun saveResult() { + val databaseName = getEditTextValue(binding.databaseSelector) + val settingName = getEditTextValue(binding.settingName) + + if (databaseName != null && settingName != null) { + val settingValue = getEditTextValue(binding.settingValue, false) + val isValueNull = binding.settingValueNull.isChecked + + setFragmentResult("edit_setting", Bundle().apply { + putStringArray( + settingName, + arrayOf( + if (isValueNull) null else (settingValue ?: ""), + databaseName, + ) + ) + }) + } + } + + fun onBack() { + saveResult() + + navController.navigateUp() + } + + fun getEditTextValue(textInputLayout: TextInputLayout, returnNullOnBlank: Boolean = true): String? { + if (textInputLayout.editText?.text.isNullOrBlank()) { + return if (returnNullOnBlank) null else "" + } + + return textInputLayout.editText!!.text.toString() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack() } + + setupToolbar( + toolbar = binding.toolbar, + title = getString(R.string.edit), + navigationIcon = R.drawable.baseline_arrow_back_24, + navigationOnClick = { onBack() }, + ) + + with(binding.databaseSelector.editText as MaterialAutoCompleteTextView) { + val values = arrayOf(Constants.SETTINGS_GLOBAL, Constants.SETTINGS_SECURE, Constants.SETTINGS_SYSTEM) + setSimpleItems(values) + setText(args.database) + + if (args.database != null) { + fillSettingNames(args.database.toString()) + } + + setOnItemClickListener { _, _, _, _ -> + fillSettingNames(text.toString()) + } + } + + with(binding.settingName.editText as MaterialAutoCompleteTextView) { + setText(args.name) + } + + with(binding.settingValueNull) { + setOnCheckedChangeListener { _, isChecked -> + binding.settingValue.isEnabled = !isChecked + + if (isChecked) binding.settingValue.editText?.setText("") + } + } + + with(binding.settingValue.editText as MaterialAutoCompleteTextView) { + setText(args.value ?: "") + binding.settingValueNull.isChecked = args.value == null && args.database != null + } + + binding.root.setOnApplyWindowInsetsListener { v, insets -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) + v.setPadding( + barInsets.left, + barInsets.top, + barInsets.right, + barInsets.bottom, + ) + } else { + @Suppress("deprecation") + v.setPadding( + insets.systemWindowInsetLeft, + insets.systemWindowInsetTop, + insets.systemWindowInsetRight, + insets.systemWindowInsetBottom, + ) + } + + insets + } + } + + fun fillSettingNames(databaseName: String) { + with(binding.settingName) { + isEnabled = true + (editText as MaterialAutoCompleteTextView).setSimpleItems( + ServiceClient.listAllSettings(databaseName) + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/HomeFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/HomeFragment.kt index faa64ed..f5a4d7e 100644 --- a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/HomeFragment.kt +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/HomeFragment.kt @@ -91,7 +91,7 @@ class HomeFragment : Fragment(R.layout.fragment_home) { binding.root.setOnApplyWindowInsetsListener { v, insets -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( + v.setPadding( barInsets.left, barInsets.top, barInsets.right, @@ -99,7 +99,7 @@ class HomeFragment : Fragment(R.layout.fragment_home) { ) } else { @Suppress("deprecation") - binding.root.setPadding( + v.setPadding( insets.systemWindowInsetLeft, insets.systemWindowInsetTop, insets.systemWindowInsetRight, diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/PresetManageFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/PresetManageFragment.kt index d740b9c..46fd978 100644 --- a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/PresetManageFragment.kt +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/PresetManageFragment.kt @@ -39,7 +39,7 @@ class PresetManageFragment : Fragment(R.layout.fragment_preset_manage) { binding.root.setOnApplyWindowInsetsListener { v, insets -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( + v.setPadding( barInsets.left, barInsets.top, barInsets.right, @@ -47,7 +47,7 @@ class PresetManageFragment : Fragment(R.layout.fragment_preset_manage) { ) } else { @Suppress("deprecation") - binding.root.setPadding( + v.setPadding( insets.systemWindowInsetLeft, insets.systemWindowInsetTop, insets.systemWindowInsetRight, @@ -61,11 +61,11 @@ class PresetManageFragment : Fragment(R.layout.fragment_preset_manage) { private fun navigateToPreset(presetInfo: ConfigManager.PresetInfo) { when (presetInfo.type!!) { - ConfigManager.PresetType.APP -> { + ConfigManager.PTType.APP -> { val args = AppPresetFragmentArgs(presetInfo.name, presetInfo.translation) navigate(R.id.nav_preset_inner_manage, args.toBundle()) } - ConfigManager.PresetType.SETTINGS -> { + ConfigManager.PTType.SETTINGS -> { val args = SettingsPresetFragmentArgs(presetInfo.name, presetInfo.translation) navigate(R.id.nav_settings_preset_inner_manage, args.toBundle()) } diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsPresetFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsPresetFragment.kt index c29bd46..313dd4a 100644 --- a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsPresetFragment.kt +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsPresetFragment.kt @@ -1,82 +1,45 @@ package org.frknkrc44.hma_oss.ui.fragment -import android.os.Build import android.os.Bundle import android.view.View -import android.view.WindowInsets -import androidx.fragment.app.Fragment import androidx.navigation.fragment.navArgs -import androidx.recyclerview.widget.LinearLayoutManager -import by.kirich1409.viewbindingdelegate.viewBinding -import icu.nullptr.hidemyapplist.ui.util.navController -import icu.nullptr.hidemyapplist.ui.util.setupToolbar -import org.frknkrc44.hma_oss.R -import org.frknkrc44.hma_oss.databinding.FragmentSettingsPresetBinding import org.frknkrc44.hma_oss.ui.adapter.SettingsPresetListAdapter /** * Use the [SettingsPresetFragment.newInstance] factory method to * create an instance of this fragment. */ -class SettingsPresetFragment : Fragment(R.layout.fragment_settings_preset) { - private val binding by viewBinding() +class SettingsPresetFragment : BaseSettingsPTFragment() { + private val args by lazy { navArgs() } + + override val adapter by lazy { SettingsPresetListAdapter(args.value.name) } + + override val title by lazy { args.value.title } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - - val args by navArgs() - - setupToolbar( - toolbar = binding.toolbar, - title = args.presetTitle, - navigationIcon = R.drawable.baseline_arrow_back_24, - navigationOnClick = { navController.navigateUp() } - ) - - binding.list.layoutManager = LinearLayoutManager(context) - binding.list.adapter = SettingsPresetListAdapter(args.presetName) - - binding.root.setOnApplyWindowInsetsListener { v, insets -> - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) - binding.root.setPadding( - barInsets.left, - barInsets.top, - barInsets.right, - barInsets.bottom, - ) - } else { - @Suppress("deprecation") - binding.root.setPadding( - insets.systemWindowInsetLeft, - insets.systemWindowInsetTop, - insets.systemWindowInsetRight, - insets.systemWindowInsetBottom, - ) - } - - insets - } } + override val menu = null + companion object { - private const val ARG_PRESET_NAME = "presetName" - private const val ARG_PRESET_TITLE = "presetTitle" + private const val ARG_PRESET_NAME = "name" + private const val ARG_PRESET_TITLE = "title" /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * - * @param presetName Name of the preset. - * @param presetTitle Title of the preset. + * @param name Name of the preset. + * @param title Title of the preset. * @return A new instance of fragment SettingsPresetFragment. */ @JvmStatic - fun newInstance(presetName: String, presetTitle: String) = + fun newInstance(name: String, title: String) = SettingsPresetFragment().apply { arguments = Bundle().apply { - putString(ARG_PRESET_NAME, presetName) - putString(ARG_PRESET_TITLE, presetTitle) + putString(ARG_PRESET_NAME, name) + putString(ARG_PRESET_TITLE, title) } } } diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsTemplateConfFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsTemplateConfFragment.kt new file mode 100644 index 0000000..f8ec0a8 --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsTemplateConfFragment.kt @@ -0,0 +1,136 @@ +package org.frknkrc44.hma_oss.ui.fragment + +import android.os.Build +import android.os.Bundle +import android.view.View +import android.view.WindowInsets +import androidx.activity.addCallback +import androidx.core.view.isVisible +import androidx.core.widget.addTextChangedListener +import androidx.fragment.app.Fragment +import androidx.fragment.app.clearFragmentResultListener +import androidx.fragment.app.setFragmentResult +import androidx.fragment.app.setFragmentResultListener +import androidx.fragment.app.viewModels +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.navArgs +import by.kirich1409.viewbindingdelegate.viewBinding +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem +import icu.nullptr.hidemyapplist.service.ConfigManager +import icu.nullptr.hidemyapplist.ui.fragment.ScopeFragmentArgs +import icu.nullptr.hidemyapplist.ui.util.navController +import icu.nullptr.hidemyapplist.ui.util.navigate +import icu.nullptr.hidemyapplist.ui.util.setupToolbar +import kotlinx.coroutines.launch +import org.frknkrc44.hma_oss.R +import org.frknkrc44.hma_oss.databinding.FragmentTemplateSettingsBinding +import org.frknkrc44.hma_oss.ui.util.toTargetSettingList +import org.frknkrc44.hma_oss.ui.viewmodel.SettingsTemplateConfViewModel + +class SettingsTemplateConfFragment : Fragment(R.layout.fragment_template_settings) { + private val binding by viewBinding() + private val viewModel by viewModels { + val args by navArgs() + SettingsTemplateConfViewModel.Factory(args) + } + + private fun onBack(delete: Boolean) { + viewModel.name = viewModel.name?.trim() + if (viewModel.name != viewModel.originalName && (ConfigManager.hasTemplate(viewModel.name) || viewModel.name == null) || delete) { + val builder = MaterialAlertDialogBuilder(requireContext()) + .setTitle(if (delete) R.string.template_delete_title else R.string.template_name_invalid) + .setMessage(if (delete) R.string.template_delete else R.string.template_name_already_exist) + .setPositiveButton(android.R.string.ok) { _, _ -> + saveResult(delete) + } + if (delete) builder.setNegativeButton(android.R.string.cancel, null) + builder.show() + } else { + saveResult(false) + } + } + + private fun saveResult(delete: Boolean) { + setFragmentResult("settings_template_conf", Bundle().apply { + putString("name",if (delete) null else viewModel.name) + putStringArrayList("appliedList", viewModel.appliedAppList.value) + putBundle("settingList", viewModel.targetSettingListToBundle()) + }) + + navController.navigateUp() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack(false) } + setupToolbar( + toolbar = binding.toolbar, + title = getString(R.string.title_settings_template_conf), + navigationIcon = R.drawable.baseline_arrow_back_24, + navigationOnClick = { onBack(false) }, + menuRes = R.menu.menu_delete, + onMenuOptionSelected = { + onBack(true) + } + ) + + binding.templateName.setText(viewModel.name) + (binding.workMode.parent as View).isVisible = false + binding.templateName.addTextChangedListener { viewModel.name = it.toString() } + binding.targetApps.binding.icon.setImageResource(R.drawable.baseline_settings_24) + binding.targetApps.setOnClickListener { + setFragmentResultListener("setting_select") { _, bundle -> + val targetSettings = bundle.toTargetSettingList() + viewModel.targetSettingList.value = targetSettings as ArrayList + clearFragmentResultListener("setting_select") + } + val args = SettingsTemplateInnerFragmentArgs(viewModel.targetSettingListToBundle()) + navigate(R.id.nav_settings_template_inner_manage, args.toBundle()) + } + binding.appliedApps.setOnClickListener { + setFragmentResultListener("app_select") { _, bundle -> + viewModel.appliedAppList.value = bundle.getStringArrayList("checked")!! + clearFragmentResultListener("app_select") + } + val args = ScopeFragmentArgs( + filterOnlyEnabled = true, + isWhiteList = false, + checked = viewModel.appliedAppList.value.toTypedArray() + ) + navigate(R.id.nav_scope, args.toBundle()) + } + + lifecycleScope.launch { + viewModel.targetSettingList.collect { + binding.targetApps.text = String.format(getString(R.string.template_setting_count), it.size) + } + } + lifecycleScope.launch { + viewModel.appliedAppList.collect { + binding.appliedApps.text = String.format(getString(R.string.template_applied_count), it.size) + } + } + + binding.root.setOnApplyWindowInsetsListener { v, insets -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) + v.setPadding( + barInsets.left, + barInsets.top, + barInsets.right, + barInsets.bottom, + ) + } else { + @Suppress("deprecation") + v.setPadding( + insets.systemWindowInsetLeft, + insets.systemWindowInsetTop, + insets.systemWindowInsetRight, + insets.systemWindowInsetBottom, + ) + } + + insets + } + } +} diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsTemplateInnerFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsTemplateInnerFragment.kt new file mode 100644 index 0000000..4e212c8 --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/SettingsTemplateInnerFragment.kt @@ -0,0 +1,90 @@ +package org.frknkrc44.hma_oss.ui.fragment + +import android.view.MenuItem +import androidx.fragment.app.clearFragmentResultListener +import androidx.fragment.app.setFragmentResult +import androidx.fragment.app.setFragmentResultListener +import androidx.navigation.fragment.navArgs +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import icu.nullptr.hidemyapplist.ui.util.navigate +import org.frknkrc44.hma_oss.R +import org.frknkrc44.hma_oss.ui.adapter.SettingsTemplateListAdapter +import org.frknkrc44.hma_oss.ui.util.toEditSettingFragmentArgs +import org.frknkrc44.hma_oss.ui.util.toTargetSettingList + +class SettingsTemplateInnerFragment : BaseSettingsPTFragment() { + private val args by lazy { navArgs() } + + override val title by lazy { getString(R.string.edit_list) } + + override val adapter by lazy { + SettingsTemplateListAdapter(args.value.items) { adapter, item -> + MaterialAlertDialogBuilder(requireContext()).apply { + setTitle(item.name) + setItems( + R.array.settings_template_inner_action_texts, + ) { dialog, which -> + when (which) { + 0 -> launchEditSettingFragment(item.toEditSettingFragmentArgs()) + 1 -> { + val index = adapter.items.indexOf(item) + if (index >= 0) { + adapter.items.removeAt(index) + adapter.notifyItemRemoved(index) + } + } + } + + dialog.dismiss() + } + }.show() + } + } + + override fun onBack() { + setFragmentResult( + "setting_select", + adapter.targetSettingListToBundle() + ) + + super.onBack() + } + + fun onMenuOptionSelected(item: MenuItem) { + when (item.itemId) { + R.id.menu_add -> { + val args = EditSettingFragmentArgs(database = null, name = "", value = null) + launchEditSettingFragment(args) + } + } + } + + fun launchEditSettingFragment(args: EditSettingFragmentArgs) { + setFragmentResultListener("edit_setting") { _, bundle -> + fun deal() { + val item = bundle.toTargetSettingList().firstOrNull() + + if (item != null) { + val index = adapter.items.indexOfFirst { it.name == item.name && it.database == item.database } + + if (index >= 0) { + adapter.items[index] = item + adapter.notifyItemChanged(index) + } else { + adapter.items.add(item) + adapter.notifyItemInserted(adapter.items.size - 1) + } + } + } + deal() + clearFragmentResultListener("edit_setting") + } + + navigate(R.id.nav_settings_templates_edit_setting, args.toBundle()) + } + + override val menu = Pair( + R.menu.menu_settings_template, + this::onMenuOptionSelected, + ) +} diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/util/ItemConverter.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/util/ItemConverter.kt new file mode 100644 index 0000000..3dd607a --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/util/ItemConverter.kt @@ -0,0 +1,22 @@ +package org.frknkrc44.hma_oss.ui.util + +import android.os.Bundle +import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem +import org.frknkrc44.hma_oss.ui.fragment.EditSettingFragmentArgs + +fun ReplacementItem.toEditSettingFragmentArgs() = EditSettingFragmentArgs( + database = database, + name = name, + value = value, +) + +fun List.targetSettingListToBundle() = Bundle().apply { + forEach { item -> + putStringArray(item.name, arrayOf(item.value, item.database)) + } +} + +fun Bundle.toTargetSettingList() = keySet().mapNotNull { + val item = getStringArray(it) ?: return@mapNotNull null + ReplacementItem(it, item[0], item[1]) +} diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/viewmodel/SettingsTemplateConfViewModel.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/viewmodel/SettingsTemplateConfViewModel.kt new file mode 100644 index 0000000..6e2e84f --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/viewmodel/SettingsTemplateConfViewModel.kt @@ -0,0 +1,36 @@ +package org.frknkrc44.hma_oss.ui.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem +import icu.nullptr.hidemyapplist.service.ConfigManager +import kotlinx.coroutines.flow.MutableStateFlow +import org.frknkrc44.hma_oss.ui.fragment.SettingsTemplateConfFragmentArgs +import org.frknkrc44.hma_oss.ui.util.targetSettingListToBundle + +class SettingsTemplateConfViewModel( + @Suppress("unused") + val originalName: String?, + var name: String? +) : ViewModel() { + + class Factory(private val args: SettingsTemplateConfFragmentArgs) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(SettingsTemplateConfViewModel::class.java)) { + val viewModel = SettingsTemplateConfViewModel(args.name, args.name) + args.name?.let { + viewModel.appliedAppList.value = ConfigManager.getSettingTemplateAppliedAppList(it) + viewModel.targetSettingList.value = ConfigManager.getSettingTemplateTargetSettingList(it) + } + @Suppress("UNCHECKED_CAST") + return viewModel as T + } else throw IllegalArgumentException("Unknown ViewModel class") + } + } + + val appliedAppList = MutableStateFlow>(ArrayList()) + val targetSettingList = MutableStateFlow>(ArrayList()) + + fun targetSettingListToBundle() = targetSettingList.value.targetSettingListToBundle() +} + diff --git a/app/src/main/res/drawable/keyboard_arrow_down_24px.xml b/app/src/main/res/drawable/keyboard_arrow_down_24px.xml new file mode 100644 index 0000000..3f4697d --- /dev/null +++ b/app/src/main/res/drawable/keyboard_arrow_down_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/switch_thumb.xml b/app/src/main/res/drawable/switch_thumb.xml index f74e617..5841dbb 100644 --- a/app/src/main/res/drawable/switch_thumb.xml +++ b/app/src/main/res/drawable/switch_thumb.xml @@ -14,7 +14,7 @@ - + @@ -30,7 +30,7 @@ - + diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml index f827918..cdeea33 100644 --- a/app/src/main/res/layout/fragment_about.xml +++ b/app/src/main/res/layout/fragment_about.xml @@ -1,5 +1,6 @@ - + android:layout_height="wrap_content"> + + + + + + + android:layout_height="wrap_content"> + + + + + + - - - - - - + layout="@layout/layout_list_empty" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_settings_preset.xml b/app/src/main/res/layout/fragment_settings_pt_base.xml similarity index 100% rename from app/src/main/res/layout/fragment_settings_preset.xml rename to app/src/main/res/layout/fragment_settings_pt_base.xml diff --git a/app/src/main/res/layout/fragment_template_manage.xml b/app/src/main/res/layout/fragment_template_manage.xml index 93f7681..d48b222 100644 --- a/app/src/main/res/layout/fragment_template_manage.xml +++ b/app/src/main/res/layout/fragment_template_manage.xml @@ -1,7 +1,6 @@ @@ -24,42 +23,10 @@ android:orientation="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"> - - - - - - - - - - @@ -70,6 +37,13 @@ app:icon="@drawable/baseline_add_24" app:text="@string/template_new_whitelist" /> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_settings_template.xml b/app/src/main/res/menu/menu_settings_template.xml new file mode 100644 index 0000000..85d9700 --- /dev/null +++ b/app/src/main/res/menu/menu_settings_template.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_template_manage.xml b/app/src/main/res/menu/menu_template_manage.xml new file mode 100644 index 0000000..5a94f2a --- /dev/null +++ b/app/src/main/res/menu/menu_template_manage.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 1a4bfc9..65291b9 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 4ae7d12..0000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index c9b80dfa7b9451c8bb74e4915698ecdc75c4e1b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1195 zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84mJh`hS0a0-5D5IiacE$Ln>~)o%7m1I#uR) z{ab~?tTR3x8j6MbZdV>~pRGxZSu{Jpr+Z(Z+OZBdb#YGVrLH^ITyWZMH0jdX$3_Qw z&RTTbnv}6wTbk!oR9MyG5~tI?5AQ!Xdj7eku7|4HmgP@B{rIgaZ?U)F(D%cYb++d@ z&oeGqv}n)*|%&uuGYkNR4evBIcf+o>}Kj?JrbZ(j)A zeo!@8x@4~ZymMi~F?RWBx7l8p$xYYKe9QiImX6vJMrPG>E4Iyd<2|&rm}9Q)%Ehan zGS2uCdD81wdQH}9x8$U-@*cOdS`p{gIqfzqE%1D%#_laKb#j3JBj29z*r)8$PagD5 z>{DK`xz*EL;YA2*;Y?wHB@MH>!V+0aKPY#;4PL%&O}&@8h6m^UsquY(Cq3ePba>6- z6D*m(maOsQIK@yJxqU;ERZ`Qr73;hrCkrjne0x*0N$Q5d{tI*T9IsCjU!wQ+u4q$* zyovcz_kh}`{VE+S6BP_u-(C-WZ0u|LDRbS?o^G~{EPLyh3bWtU+fsdZ)5cAI_tfom z*KusST_(fH_F>=oW@lkPnWEeSwvEccbuYiJEja!Ds5x7mfcJ!t?|3!u+~pL%Cnw!| z+_3F1qdaF9SJ5N|ArL&iLTf55_tw>2f@H?nslVdN}tgH($JuDL!uvA0iIAsa{wAu~BkjBIEPt&#yo1|M^*4TRU3m&vT)De_xw!WSJWId-20V zi6vHZ3wOlmd5Ul*JxohWGvj>Zq9iEf(&Q2FsmW{Y^`!;f-Q6#~|GxPA^V-Am`ntM* z_p|Q3nds!6A?5tJ*uqx)-~+a0&z~)MzWr26h1mUHJN*izFOmA0>+#EP zVpfxvtz_d=a#Ya>ZR-0P@u9q5y8UNr_{=*`rpNqd-Tma2T@io!jU^>jWn#9C4l@4& zIQ}OT8~*zh_QCZ~#S`&^cF%UZw=XToD@(HY_90Q`an2^Gr1VQF9j(<*zUB!%NeJc@ za%sxwI4P7ODcNQAvOr?*L4~U2%dT_=C0de)tzP{THtf=_lDb=s5m4 z@zC3-GXD3n57C<0o}Ouox~sk$#x(@1|6McDRrRgNu2(M>-OIQ?fq(j8)vNQkHudZb zy4I3!Qt*gHyo4dn?hBuYIP1b)G7I0Ccx~D?d#l=6=aa4ctIceke2CWcyc}$y0RA%lGf8E_?FC=Hx#6^Cyy@7{}dx{N(ti6z8&U z!G+&BCIrrWlVNorC3WLmyY0&#N>)re+-|JMyHtQhOG|5&ZD2j~kLe-?g#}Y=85kHC NJYD@<);T3K0RUHpKH>lX diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/app/src/main/res/mipmap-hdpi/ic_launcher_background.png deleted file mode 100644 index b2b85164a7dfea52a5072aa8dc6ef7826ee661d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 524 zcmeAS@N?(olHy`uVBq!ia0y~yU|0mg9Bd2>42M36Ni#4oUiNfx45_&F_R>N|1_2S) z1KT(0dCp3^yI$I%@S)j`CEFh@G}Wpun(XW%=<4Dk=qe%z#eps^B7rV~f`P~qqzWR8 z5b>wP93*E1@}W2oVFTRtq&gC8IKrQSHYgT=Wf4I`s^JLtP4S~n2>iLr$hf10ZLRd= RV+;%o44$rjF6*2UngHZrazFq8 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png index e46d785cbd16db99c9deb34369d10b655d4dee87..069ca79f4a8427341d9029d60bddc907b3f2c57f 100644 GIT binary patch literal 4512 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 delta 957 zcmZ3We2IO6ay!lvNA9*C?tCX`7$t6sWC7# zv@kIIVqjosc)`F>YQVtoDuIE)Y6b&?c)^@qfi?^b%mJP*jv*Dd-rn8V6%#6P;NyGi z^ml2(ny9?OU%Klfs+xz^^Zed0Syx>69iPE~_@Vb8=Td&<( z+VMldc)lIi`j=vVqddKSe}3)#?fdp$SGqN4 z`IVs8W!IvXC?0t#Tb^>x&En1dz2DuX+ddw8K4sHg+tNoq)0Es4_2Q*(#pg=AbIU$_ z=OTYGsKRWe2PCD75LT1_;t(Fb}#|{p`mK{ZE+gg9LaO>PmO)K~4nK|?6K2DFY zq%D?;)7It5Ti^Zl?|eq_vy6HpuWMC%u2@ZK6PW(;c1OkUgf-o}wr-VOD;piN=Hi8Q zl|T1&bj;>&+4chBb%XO!>s9XTD13Z$;nwwD&!XL*n$ESYzV_;@^P1mLpWXlWZ`f+q z+wpSF+iaJTuwN}Za^9b1xv}i>%cmbJVw4~4tgLR1dVP1Yy8pg8Gmk$}Jd#>}bMDVy zx7J2)pEuJ-O*;#+S?b^As>&(-iX_&o`=Z3`YhP-Q4fnRTZ zeZBtr8GYl=y^BB1inA&|=k(2a&DUAkx=$zf?9e}SEy`tfePq%v9S=pjwuk>7`7|89 z@cll|+FJR;bI!M&$ys{s^U^8b`Sto7I=sIho_l+HzTfxn_Wd1s2RnA`FaP!B{nl&g zPdC1+N;%cc@w0iP7u(@v!*qDLe4~IM$kTbp3gffW zH%*D>w+%em6V!FJU-b5r$|F4;*ZtnUi<{}Aw*SZ<%{gz}7SD}(U75*II5U0!{lB|+ zO`5s%_N`qOuXZ_i^L{twE}YqR%}#IT@$~Dn@7nO2L41sp?7w`!Mek72I`-0JkQz@{ KKbLh*2~7YUioinv diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index b6080e82e35cdd3f43d2ccdab289a2211089a6b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2925 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 Dim~)y=W-Npuoej zVf&dl#sr4lN7-Z~7b$r5{yVqo+`N1tHJ=# diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png index 349d52b37ad843c6ae8caf250e3d657eb3ab546d..e2d91e6b8b0f16872142eadd7a706b4e5116c549 100644 GIT binary patch literal 2331 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 Y8u8-3t_Ld_7#J8lUHx3vIVCg!09-+ch5!Hn diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index bf2475ad6b05bc05b7a05470efa75ed6ce4bae71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1607 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^Ts_&i-4Ln>~)oty15Ib7nn ze2%Qo+X(HjuRI0Hg3^9 z*tN7^y+v2C^MZtO0U0ZkOSx{F`fFY?aV9%1KiguGYx`L1G27!^i$ld;dYUh=@E5r* z`!-bLyUnp3^U*`3dk3E~e}Uneiy$ahzTv0pP` z{W|`n>E|bIn(TOhqoa48AJaUC19^9SJL10WnlhJ%DMaA&#WT;t90Jd6j%fOo@bl8n zpt8eJ4EIf*q)%iJa$xdc;8b8#X<(VaAoL)mD9>tN^$rH{>91Np)@2I*n)*hOv6=J6 z)GqsLArEIBV_P`I^vc68i`hL7B;3*SAc!a9Tna>eFRvwye_=Vk;b3wWz z#N7@|9u0?Be!RKSH0w-CVT$VFtp9#O5Bm7MzW$hev0?vA-$OrcrX1-|R#izbShdAv z&9=BB_wL1YzI&JV=GCjB#{c(z&Rc%)+TGS-zbTU%4({2Lti7$I%tP_x0$(-ZYgex9 zNHCGwxOwwrmJX2%*RHj(H8ZYWz54E@TerNRf%kw_^uoP+|2!DYX7{q3&^=&X%N=EX zYv}~N_xM{kX1@ zV9@Q|z2T(bx}7UI&r9=EtlM>q)j4;qN(T#vNIvUb&M~|(3y>GT#FaIr7sb=H5YE9$18*`7RiW{&wIj1}S zX}ibBnR&~)@2SVm7eenHAL?!VklHSveDtvXoulC$+5%$7@()Ov{fcLjJjJb~^rO>Z za^kx=5g0JXmuBfm*)jh(;ote6TkKr#)JJu&!>uE&iF>RY{(A5M;*Fj=c(irvby_sW=q%u5d(U+uqQ zxliN~<4Nyk+89fA&;G(z|KIZxD?{1}(^;&mI#z0jY*q?enda9WsFQPzEBW7>&{dJf zVJrUrx%XhE$ITnYpQaUmvF?7~QIqiH1?Pju!e`?AQ(FuVwOb|ziS65W(4g)Qi>7jQ zm{V8uQ}d@6b3CPvr?4Da5hyGD*Q6`^XG`asC+S_d#K6G7;OXk;vd$@?2>{&3-D3a% diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png deleted file mode 100644 index e3c518a6e3a80e8f755241cbbef3543f9a5f0124..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 752 zcmeAS@N?(olHy`uVBq!ia0y~yV7LLo9Bd2>44n$PZy6YvwtKobhE&{odwC-xgMa|b z!R$!A<&3v#V>xCdSl{rh(yqNEHPyD%_%Wl}0Tzh_CZ7g4gVO*if{SsC*{1;{H-iDr z5Ke%K;9~T!&tL${F|xrJY6qYqxEPZB28>`iCLS0A>`Vq>sC)4+5Pkx?6685T3?wgs z90~Rt0S1zfKyCzkjQ|75Lm)STeMW!*_B2S1PXi;HL;}bHNTlJ>jI1ZEf)v-h0FFd0F%tu}x*C R85kHCJYD@<);T3K0RXI*w(kG{ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png index 51a676dc0d8766f409b02616d4d881cb303fe4ba..26dbf8b2273abe2941e35d52401aacaa48e0cf61 100644 GIT binary patch literal 7681 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 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index f461505db7b73a94eee70a5367e8d8ad351ebbcf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4093 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^U1k9fK`hE&{o8=Dy-5-zq+ zgjdPhrA5Qg&9GxfuiC7u7Y(znG)Sp*u(68r{Jz&`SaP+9<7VaHZ=Ono{ z|8lN-_IH67Z%fmcgsdl)mA!xZ_Z+{lExq6N&5ef+@`9TxJJMRVP2=8rOE4tU@y5K? zKP93oF2x`I#=64j+@s^~H~wvV>!0)g@mv3YTW9~N-nZcQh1!qlIT~C|wm*!IN-H+h zm@6(8_v+cVMMR6;q0WtkEytQ|z1(g28x#7TE-$@zb6av#Zzo1)vgByW zFL*AQqwu9kP@gSsWy#?M?GFQgi?O|$#<*ej2Gg!Jo!g&wlA)=* zKLU9}mpWG|36@!{TYE~btF)4v?ROtX3Dc)oPR8rzvHTea-8gohwioZ%(Ja6HKwsBF ztDwxS2cvju^45u8`?gi$!+qBS+(nA~FWNXSs3vD;F78VYnfkYHX{PQsj`e2ek7~Ku zdaAdsRj6f@`x@?YAbac0khB>L8%;l^aJa-A?4LO6v%<^ON2{9yR!+)IU8OJgb+_vQ zZlh+Oyt&E_29EPMIB%RPKYYKt*7c@P`p(9%#a|^i|EP&&Sa?zAfV4Yt+qSzp!qb0+ynbot1eBMx-4VMj2#Lx93LD0Y^mRJsVYTqTi(=- zEC#oO7JY5YJ({0!?&cd6j)T+0LSFu^d@%d$vafAxe6HFuZP~bRreIJEZ>pu-tOq&Q zCa(AUeB|J^Fq2o&I$Sj`IRuuk9p;zN&Wnz&HC(&Rw`>&Uh~-a=H^5T_OPXU^Db^uHfPjv&N?zvu*vJIUtrmh zllH$p2Zb(b$iDgDw0pz0^;?!oIIi^4T`$g&x6G?DYD$(_w9SuCLJcM}FRI04i#%;T zHCd9Av2Ba^r;}?Yf84cRr6G%-=CN)IUQ!D-Ro|>-)wX<{?&q<fIXUp6=s;pzL)&AcU z`r>Im-=gN_uYL0Z<=;-6&mhF_@wsn{E!Spo@5ii87tVHmK5(hHQ)q+H)fHi%ew=;! zqWSSwsQ^3sLY}wlEqlJnU)=s`mhy|wlhxPsGOQH|U9*d+aN^%x@>3)kBdUU~m9W<& z@#n5Qz#_A>p(ZfC{hRDBw%TuB!`X8GPjtTK!H}6~{!mNuU{)&Y(Q_G0Ef?oY+q3ll zyT5Dp*B1f}?%((2TPr-+FjZ*7)+IB&F765~cbF-VvPXpTb!phLoHy@Yyboo0QQ`Ql zY;Wa9J=S|$#MzQR)J;@+{yvmNKwqK%HCJ8hju#KDN<*e^u{U4pu&QZwxZr_33ucO? zuioUfON_fE&aGmH_O*YXgHH6@F_zlSXHZnuI=i34IIW_5pTA1RexuC1@=yP^aXz?w zAy_@I^sS(m)9g0mCCtbBqO2L$=tb<8a`ZcO=-e@;g|D6}m{%^Jvi6za>+XxzTidrD zND%5!7qGl!JZD){qT;o(QXi?(S8K`*mVJ{AKi<@>;_^H3!av>A!@XY`roE|>eQR6A zQd{rWh1)Rkz`fO77-WWt%H+UzDvr_$=wtzWUarYy;^_ZW-)zzRGMD zR4DY_V76S2ji{JX~B zNpmyKO>~&^ORaZf)z=0y25Tq3psg`16>CnqZmhoNka~6gf={pfebdxtPI}Y9U=+LZ z+%K-=H*4-s6R3-nlX=6nQ**gSf{<`R``QPOzhAui`ufGQv(0_8G}-OU^ckJvS7+52jpP!rSoPKUj=4B}6@lqb z?lml*C$Z$dtSCpv3~LeQdhb4-75<50zm~k)!8Yaca{tAL+xexp+`1K2^7Pcyd5#Us zR43L;KRYXz*}=fK=o#zDQ06Ua3-;~X=gg!Rzwgdw4u!1_E+;Jh`gkZP80DC-z20xe z^h9aF1AdO##uo(`zX=%T_w+K%Zxa%k(tK+#ggEX9 z7Yf+)$;`$$wI`8D&F@S5o+;TyOBSx>+)?n5iFN0)Wy^e5uU@@)WmdnJb9YhRfyIxR zG_G0wRS4@SeDLlaujR>2B1zv^C11R~byzAO@6HZK_a95Wr{6MJd0;ySlZUF0TzL9? zW_fx0uF}=hOlGsQ6|}!;VJ_OLl(s*p)vxyYh2L6<3q==tDX-}A_nz3yRw-yZG9z@+=@U0@ zUA(kqadg6CDVCGo+8W1l{Z4EUpPO*9c;YrrNlCR7Ep9=V)}ui^hY!p0p6#$a^hNXW z#y@|ulpP+4Y_WLH=TrN~vuk5x>7ufdO$-Ovr+6OEW%01lT<>MwyHVD|&}@fG;j=S# zKh}#c(Yc=(EvmSXB{!h&aijZ>ZKGUMr|OrKr-fAyyQffox3MWUy@+rF8VML_=r zzvk&O&&sXZM#|H+l#8#jtmm7%tw zn5KWrXJg8YvZ7?8Cw$3nJ`AakbTxy53>nj{91jR)t2qeQOx>OsazUjlb@>zbm?;xY zofw!CZZ3Ko(RAWdmNesB{(WalbTj@;x~|#Ab6PLXyva33U&8W_;R&xFD|g3T=;laR z96$G`F$=rjLJ7ZlZ&L1r2L1Y~JiY9D`_YF}CrrPjtN%ijg=6u2lY2>GA%Sn0nC~8V z@%!e6hzGrke|W@r#lP{3T_D^dEp=hxty|xkKYV=-HpfX{n{eQ_;L)x` zwUeQn-~705_OtQ6Ex+@pO{@RdMoI17W@RPoTb0RttL#JZmsi{4XI^o-SL+=2p>=iY zQ`PwP#=r7QBP6H(l(=UhVbXEuLW01bw;MBJ6wRfyUHw`kPt=z7d9FRb%jxIRlW{l>+;((^p74ndbEFf_RV)&4mNJzZf(ESjBAm2 zh_jy%_o-<h6)H?1o~CHPv{eZ@%A<$S)_SBgfFwn#$cDVZ(VzXaTEz z?$5x20tx-)@1!RwvHtk^^TF|hUl@|au4FtpA(Y${!eVeXy>{M}8_7TJs0Z*!h;bP_ zl#O}o;`oy>r~aVf!-k`5&)x|g2s)c~_D^0C&&0XyFLq`(uRHmELyG(L9bex2zcX-o z=VZ>N^!#1p7tup=KT1`zFgndUU-!5*;pd^fAyp?WHy4+)7~k7HW8#BXuMSrq($Fh; z);(d*AHCef?0nCRIHryi3Hw)(^~*JW>usN~Y}VozJB@A{YX8_(^yFC?zlEisP}5ua z`5R=C=I`ga**WbYZ|vUgNflQvd-tivJzjQ6NqfdTWy^5mlYYNd7%Cc;tM4=lnQ-X% zbIy(#zwP+KJd77AUw+E3qTH}`^6U)nnKt?-oi`}Gaz47(E+tI6W8UoL%a<>0)K_a< zlBj1PzmMOZPx+^z`PWXKIjiDY&Qu(fj#!p*YRcARrl=pPEw>z2`{X=Gv!8nO`H#at zii;kezqlwr^Tb8b1A2PG^h$Pz1isA=tF%`Tmlswa8(>|y(O&%mqjey#D24L8>x z>N;v4)SqzaND_;pv)+0Ejs&60hfeccuJ|M+`H}UdebH&9_|5en{>`jeAbU)H_w1!! ze(9T0MKhoO7Y)TL(Dux`w0Px* zJ9EA(=)GcFa#Ydk^|G%#g?BO@?RCkHniRGF-VtHVJHhjMOFn5&Es7C-vOKjMw;J=c%`7rH5^f4jT$aFdNWyi0UGR?mc9RaC<-f~m zC|Ei{;Ipybt67<6PI$Wg@rlV!`qJB5!?Lqte$Jl!W87y0CKO8BuYa60|Nco^V_oNm z&&^wF)P1#28cs+~w0eI?UYXstLb#(~+0T;u`~F#M7u%Dh!pL^}@Hc)Qu7_&AK2M#} zLk<-y<~v{cqhDwi+W+`?sz=8^Mxp8dSWbG^FLawX`TB|fC#n}6+TYSK;cm=}%Ts4u z5&8X)QSpg!MC!O`edA0iozucYr zKkxTEHPd4P2S3ib-9DXB-)g60QN9xY8Rxc7lSEH2Tg?%3kCHz3KVPC&|7QCeZ@cC{ z7PGcqi2d)Uug v&}x4C8eM1_lOCS3j3^P64A0#j?OXv84O{~Yy)U{6|KIHr>380;xSg-J$$RIV(|h7SrJ3yIH2-X8`~A$`V6T>g z2?i28Y|ZFYT$#_5DJjcV2J7ZcZB}Bx+WDfvaPq_p6(=SiTVc9L_+sy-8AncD{kvQI z=(;yPg{yZ31i37@oe~|S@YW|(`S#`A0pE_D+tOYh7$5Fym-Mo1Uc{eM1zp`|mfkoK z{pTy=`QUl#d6RpNs85-^%xm5!n+H2xZ_X~(v^L!%*1uzqW~;j0C);_e|M;fl&HdtX ztUE~GGP5sbdF;}+D;H)d6g}$fo$>aQTG*%k-65Z^?1;T2oK=yyYU!-9C1IyLTx70H zJ7VeEePXA`G1r!Bk2-rRP945u^^!Adox}fUD_y3{JfmS*RTBKRQ^xvdEB9KN0Lu>& zToaflR`~Yrb#!j4IIUOux8#{X_M#W5pJVl+456B!Mge%5Jdw+7aP$i2U`xXga_<)^1zgw=mt+SRe&#Nq0JWDAF@pGyC} z+MoI3z_(4ov3kkpuBz9BneY2wxq@*OqugP}RTF2w^u5@h@vG(Err_AHg%<+&cRo2g z_on;1T80xh8iJCvGEXfzxG6aHn2@!WtRD9HaBjeQ% zMusas48DI7W-PwEa^5e-Sw?vZ45q>kiHq+sDliy{DCjd(`56iIa-HCAVBo-qVv;-K zPu5&tpIG<$x|ZncYhM|bSS?u4!>jY|xwDS-dzITWzjp^o?#UNtSjn@(^-|V0Yy1Ac zQCZ-FN4O%2qvbV%D5?oN>ZzW~o_wTjv(A9to7u*GX{q z|9>svNMUa;M*|O=#~MBN&;I)b79{_%D70Zefu!{NB2F<>=w$-y@cNNZ!-B}vEvPJe5zr!kKuM@Us^6u|D`|i%p#W8CC zzt}RYueBG7#tHYlbGCX92BrnK4td231!!Uk?Y-xY z|M*l?)^@l;(BaVz?>`j`Mad2e}FUtE1Obw?NP>6@q0-rqiJcXPk{$~}LtK4)mj zS9v7e$-v@(4=u^LBn-_a9)%9_t-Oyav=~=NGW;qyQ}CCewXN!eyjh}8eOGq{hXWh? zls(S`d+W+qyt%T`!sJ)P6aLp156@2uyK|8tl)3*QL+I)2H#(}Xm@0Uby^4^Lsy!nj z@ZfCx?MtgvD}^rX5)D0&Y~Wy-89HU>#K0qq>?@|f-Qsul7sIRT>zA^K*d^;8XLfL7 z-jY0-Ilzl&@y+0%)akXqe!O5kaU}V1W%HjuyDolW6&0FzBY=6ruLhQRZ?1Tq@=9Db zwfo(qet-R&sR;|FUt6o!u;$78`+fV%mKiSW&bY~Rd^WpF7IV>~hqKc!?|RyEtiNlD ztkte9uQ)w&w$+@tZQZcH%-mmUveW!lW<*S+*B-)_0N>(h0+XM%^7d>>wZf9cZCo@;uk zMa6IX1kWEjay2g*3%Zo$DirF<8Q7os_0jKT zs-NG~Ts`?nwzJyq;FH(4gUg=3xUlN^tH-;zI?tA5&-1&Lwr2g+EZGCbCl=@4o;dBE z?Xt+G>hqgezL(5zVfoAxprW{0r}>xP_lnhTJ??pSyl^X7QhL?%^|@u=L1sj5dFnr> z!`@%Oe&@a#*H_2?-|;`(Vp8ZLzDf9E?^&@WrB|a~pSvWo`ut{rpC7k87nFXjXJh-r z^ZTQhufskHehgG!#5{ZL?rWY6*Cx*As`%IKVbhVlaPFKNGxn~GO}5VZ=w8zMx%T~n zQbnuGrKL|+a><3e_<4lA-Suki+#GLRyN-2*``+tr(aVW47n{CsiuCi&nOh?SR3E)@ njFaebx$prKIf`I*xPfuKa{0-1bGCVS)7ju9278gF>nEMMJ(Gm+By`Q z6q7m1LhE&A8ots_~bG>q1 z@=mp#g_ESGOaH#*C1SnP+%M;5*KXO4OB^(~j&$oU3 z``f+ebL@W`J8>ws2vCoh@O{?neP3G7vNy#!Mf?am*1mWxw^NM}*TjhzudyoHakic~ zk@31oV1A2JO3Ic}#}0odMI)nIyA+P7FBFiJ%#9UzG&!K7r)QfU$45^M7dN+P@s=Md zB1+1m#thrA$*#$GyEps)v(^89t#1@jTCB_GRMWK8eBIw8yG&p2`*=n6{JzguV)d`x z{dCt_M?`7yT45)<3qOATjQxBi_Wa-5>+`A~9$KGQeeTDPx96?o_m|4%{rcwbplEcf zO7RKv=~(-UC;9UGKAsG(t2}L-y#LQhV}Wp+n$MSCeLa>R)WOs0QPa$S_xIkd*X=(n z-gzyI;&?)~3C9E|^y z@pjQ0Ciz`2J-2Gtyg2Uv@SnV0o9X>Zf%E_WR6aTSB;k4X`v8!e>?Xu~eq6u*Yn$}` zs_K_#uisyKr{wS49ben33!ZPUYuml=Z}FX9^5u`0t-sqjUH*2@rj{g==OzdLZ=DNv zTva@RUOh8W|B%m4PP zS?`iJ?|Qs|eitCr64)|TFJ1TIyu~m0W?!6lx2g8_cd)nD+v z>XzNsHQPNwA!W|H)tfZd`&k?b?LDfv&hLiqqt8uDznhr3+bXY2zy4^(|HLUro-Q<8 z9p_sdrhUtJ_Qrhn))N68Pq&~Z?PhCnpX+YFj`J@kEx7F6w9bQ5OOA1! z$A!6-*RPtXuPgS8@I8IuyZ^$~dqjIBw>owCW}MDAIPdz-Hn2I)J;&tdnV+jax^08Z z%MG{Er>ZI*RGrQeD!FU7qidJH#|2e~=c^cOg-VVu!YXSs_@XZJjSS)N5!R0=T7f(=>PHN zv!71)>rF4XraylYdT`Q@O3%3TqvxG^yw#R#xu5=G#K$hTL_m^j;-3E<>pnOu{ZHF| ztGks$wkY?4sZ_Pg3#rc7*Uep4Qt@Vd)w}HTf36IF{;D*rE1>7hqpYb$Ut(GXruT3i z>X%s#He>$@K}o(lZ)1Y2T+LsE98WxN_3+fP&gI4>{l^yljuu>Si*=ow=z=#aOBtTd zdbq~BEo`%Jw{cg8u$baOSILi?OOJi6y>U?(obJB!`}qD{x+x`EKV`*q3HQaXbA=bW-vk9x z<@_15XaAm(TljLugolgL_ZFm@h}~Uq$E2|L*t~TYzTQ+*PJI!{|7F^Oo29Wu<+a*I zCOdaK?~Kz({__=FdH8YuT-@yXC;#{)C1@= zx=x#Szy9puXy(EwtxF;!S@w=9_;jzJavARjI4#5 zqR~SUrJuqIZcqI=CDS@SRxCB1lDw&E$F03?8PkszW%Y+X-$5I(g@NW(lJEM-OBtP^<`UQe_7KGW%a^ObdT zlix2kl9OE5cW~94J#Hyqt#{hJc*pcKL=^*E!LmwbE6I_?(cPTAqQ{Cmy}55`@`Qoe5f zwOvoKYQ6HQ^D;9fC3AU&Kg~-tow+Y#`z`AyjoGE z_57T$fBK4bqPtRGSo%HIbuRt$wWO)&@R4enY2jyoJxF!>GHvefS1)B^Cr!D3a^fxT zDQtPG4Ay15o-yHjOY6+m*P^S9mf9V;TD^1i_$!>eccTv@T z`iZb(@%bNj*1w-L@A|BT?u*`;x?R6-5pwa<4PNENYm=S+B?Pqh-x8a?IEKHpwD**@ zd)6KQB^S$D=Uu!}9NJoX)9vJ{7h7cSpGseUzmnx;lz++px!XgozJ65>4isJCPwb1! z+PzQpJTJ33&vq(x`@PB(jm?`9KfQk4oW=g!RH@qP(A0_7H+yc{WcNaJ`i=_}znc=;X%&)q?zPC7mohVEmnD>)>f7lleMb0nRv%kCxVpU;E#>89 zmpga!mdba5-)t5f{JKIfJpDy2|EBMHn^qS`zZHsAD(>GS$GPf$^~v`}mb?DVuAD0} zk9XO|REah*!@Jh)C-sbv-RhCZn{g=NDaS7^tBdmk`~NKo;yLy-`F|Uvmj2$yzVFk4 z~KNI@i_J=_YZqQ}S$&xI`rS|0?SGw`%U+gqCoeWGqG?b1&EjVljJ0<2#hm_lL)U5j-IUOl z>1#!++!B}nX4v}Y=2hKwrve%yOByG?P5UyfZ;|R^@zPG&6XF`ztNd3LmN(y%*1Wg<*2+Nl$5;6-Dj%A;QMJcJ>SE1G z@z9NHHM+ALKEBKnX-!+KXTf*aJ;|{2g-ly{yMw%Jb7%5#!!OSmeOTqhjYNWMw09q_ z(D6{5=j-s|S1-8Ox9=&&<7w;vhwS|M%X(t9A@{k|>$z1y9rNa~6+U%A2J zj7)#~PZuViN2}~bIw#sX&N%DUs_EHLbiM9HlV5_J79+RPv==I&T?_TW3F{w&-2R^* z_gDW>e|_ow?}LZ^6kYzjInJN7Bwyg%(yP_eY}5Ht%PVds|FNCuWK!8u{xeo}-uczx z?Ju~#YV@vgbaY|;q|_BqVH03e3yb#gIn@5zT3vqgvTR)0o@1+(zr=}`l(w!eUtCe%Q5?*7W!V;m?xtEA)P3{Ly@!~S;8po;Y8-;cX5zE}3Yx3%u_`n>wQmlvb2Kb-geFVps#zj`k7 zJDN5<35eIzZ+%g)UnlOiY}_|H;n1el$J4{?PH(&!J*|qJr&-KUPJHpF0Gnfd$JTUx z*dns9dhrvVMOCKrJH)PA81fzOzGxBnxAMo?y#~wT8W!&t`}R&tVsdgKM|XqfCmTMy zk0#)D*!O47=kI*JRO^3#@5L?O`ksII@%H?qd++UAZvRW>mD0+(Qh2kN?PBqrW2!Fi ztEb#OH2I=UqubPl)!~({lRmBJ{gJn2o%~!yr=+6ZfWBkPm;SjUco$ULm9+$JGM=)y zxaWn?V^{GRO-E;hyl8SZ+*8XhmQ|D>zp8zwneeVBpJ#Y`I-hXsJHylJQRjc{{^qB* z&)@lbX~7GDP)WN_lb07BH-CTFe}B0=+wNai-d!*@s^&{s&Awr;%ML3&@0XS3?epG; z*T1)Hw=mz@vvEnx*Eb8aoI>lIYMxJuHJUO}X-am}b0OFC84ax&AB#(DawIDQxK1UU z);?BpBCtosreS6qj}HI!gLZcsW`1#zsr(lSE->DoEB>DMi+$p(<=6JSsQI)`T*3Ot z@Bg0#@01<3{c&|}e{xpJAyt?2y4Ca8_f?&f-Q~Js@A@0XyXTfK-|?w{t^CW~sux#$ z1uUhw72TF{aGpA6Ai4Qd`p4atn$CuL(dU*YSXv5u)k(@6eHw92yJ_>PxL#F#?#bzg z45h^Rj)xdeIhm&OJ?!C!s&(LGA{$w~_`dqQ{okLic>eD0i<+vlRW^msKmT~D>;Ldv z{@r$7{#=K;5Vo}Cy?KgVe1!-9GDMWOzo_m1)O7Lp#@N+&7yhbro%C-1)cf6ql@`m{ zg4_F(zpa@PzsS3(NIY_$a)|X|m(Z4LKfE`ji#lqqYS_F;?A$4<8(iLr+Ir1FvHaDQ zs$$aJ27~;|F%y-HM0l(bv}Oe!leR^6NPVgv)L9k3B8j@xPt_ z;oYxw87EdbyZagYEDmniweXQ;k+SuX)4QGf--MM<*}Hz$?N3)M46O5xJ~(ONBgc32 z%u9>!9dF+8EIv}9)3QTgE>m=s-JGLS3#MIl&|KLR6tRx$qN3H|r%g$PYny{^vv?Qk zO=DkeIIoy*+e$GD-du~y6mf83-k<)NdG`P3#ou$a#GH-5c)6Uj zd!hBOQ@<}vz0Gs?z>Ms_7iv$>({lOh8W^|z*-E97wX#)9UexZ*2`M{$>4I(NKil>z ze1YXQP8}CY&lNm-!aBqM*s9rT+s-gqoOX4O2vk>zSl@LaQeoGjJ3<x*}|dRSPKbKWPuP(JSQi zU1Yy*f1b0Wk6zpAc7uBcT`RwN_FUmxw0{eCu&i@d`wF{Hr(gd|t$cEoab;TxKGPtkemR_s;jO|pxpBH`* zXC6C${{5`<_qX?a|M}ZY`}Mn<4YIHQ1k4WW+_+0nqUwuNMVLkz`PwwdYs;+c*99yxrx(W$V7Xd;1A5i&o!gV99=T8AE~7 zqYXC=Z`$?!J7so5x9odk&UNl3VfW@dS9Q6r)^*+S&FQ-BRm;2f_=RlemV9^oz_i*K z7GiA9IVwCKpBv1c#Bq71$BnL2vEQ}X+mh6jZkbAjo3EU$er{KqY2TZq2&G4fHZqLa ziIQhBSI#)=)A}z#;!JAhhM7@KdUDvlWUK%G=)=By; z7g^}truQT`M@M4KD}mUDo3dlV-Uoc#qm=OV&cmkbukE)=Yp>RyT)y5?N=BmR{DA|j ze;fXI#mMvaPXEt6B|gXJH!j^L@T?``jEY*4=5mf>&C3n;KIcd~7u&Gdt*k@0;M(>> zH!pB4T_DpfSUAJ7K8Kb##wjI6CLhqX1PuQ2%V9z{&iFM}NoHU8p}S zcibUV|C!sFfN5{zg!afR4{oe0a5`~@>2}j^hi$tK@2P6<`t{5I{d3t}PhZ$7Rom;7 z)m2FabJvvJ?j-@3R@#tLLIYU?caelUC+L0eNlP7ik+)?u4drMMLxj;|g z^9?ak%uCntc8MevPJJPue?Uft@$bF>ohPEn`xdgCa*}^zEW3dx?7 zHe4+4Pk1oZp=Xa^&qrm&h&;`sNy&E4UKtq%&){+XB6&tdHCfHXi$kC1GCSWviAuK5 zFK2EDH9Zg)(%JfWqk*gi%hT7&uah}dR$iy=RI;DjweRe`e&)||>v?sX4d(kc zXxgwbM>89I$zpK3$9KfZb(%!^=fqVWM}y+0z7RQ`;J1t6@y%ib4n?VN?auOIT{oX_ z8ys~>R@0JN)|?b0w%_<2Z?oP5i8G>07dgv_8OaDsiaXu$2Uikrb9N*jK0bec_FHMr z<>#Ztb;Uw!{+s%h=3cZg(>#{iZlzUi&+_g1E{E?|e+MS4D_^$b-dv?t%g~tTRnI*` zjF$1aBow@^XF zrze*$Iy2w%$P4SFl6#w^ZExQ@l9Vm@W^!-97u^WCmB%(sc@!~uLOkCx{|-Ha7ZP6% zCeB!WvNd^|^r;yADL>^5)xICxc%gabs+_{9{@>-qWgoS?5YTjKb5hx_%y0AIKzsh~ zf9I1nni}Wr@ZeK`)(+s=n}hJ&Y4~LO1oLaqTobJ{US5T zW0yBd*cS*SGyXQLvhb)qvD(?|;tjs%KH@UR_#)a~Z&0vun=SCU4wKajfmB zE}{#RmRQ`Hz`grNZ@+KiU8E-g}!b{QY-+9ogu-yJ@+a`|&yVl(+oJ zk(etocVY5Y=aT-jS<7GST;*OMlV`ZgJ>7r$ieQ6)o8A8o6kNZ&?tEv*>OICs!y?$c z-R4zIKk4Jevn<)~K!|FJWlZPBRoyQ&!{PNUlPO zU+aPjOLJE^+znX>8kGA}Uv!xFwO!Tc>-E3xUY}Q~x_0HFQ(D%}p&bDR*#=2vS#@7e z^zK%^(syp%=8incRfThd=gcozV7ptew(G^-}%Ab?@CFh*?P*kHKU$p*sMAga7^*ob5-Zv z)qgK+T?w9`u~L8X{n4@4`G00_wXZEnj&Zrt61cwn)YhXo*?tKsW_11qL#9?%T38$yPS6} zTy(;Bs<0!Z-zl^6VbTBZ*K3~lKHskPJm$;{@uZf#3ZIS(`;3%MFHhNR<$V6~CfnET zeBsYm*nMz(r>AYetGn1@6^rTZCc`aHV|(_!?C0G7cSeo5M6grSWv8}ZvF!`)SBt!z zyvwkH=jC?o^8e4De^@>LkI28z@9mmj9JssTZ13)+FJ1{< zeRo0DLvfys3#d4%e1D_hxUBsCpVH?43l1lrcXyNFG4}iBZ)q#7wc0&@kK9jH{`Bg; zTPMy1$nBq5mb9x}kTu;q;AfhI+BW$^JO0~ADES?#&|+$Pd_2+S<-eLwJVx`P`y1xl z_x!f|-@oJY=J+FP=l`?0_UCWuj_>dHx7_~!j{C>6_`8m<0_G}&lej?ODnH4eDqvn&fe#BdkPMJFX(^4moI3v z=kez2U49==?|8oXe@C>-^osM(|8e@qeXkeXo!k9FDAp@{NFXOy__VI^f|G$nhRQqrH?*H`lk0#cO+1LMyvibXT{o?~? zzdt%Nt9|0vM^!qn*kZT8Ub{wpUEf*oEMlV5J!6KL*qOzRVWrUO-k(aYtz-^eKx_PXa7!d<@G<4Yr+}6Bqq+_v+Z4wU(de# z-45aJ9TR_wU#}NVv@Uz}PQRWtd;gzMmiu27y#6{Hyea3{byzV%BCFlVoMn0H4O6q~ zYr@mjD_+Yjc8fmTvS+!Dl=%J)7K^{cl-;|qw{lTg+ox4sfd}7AX_^_xUUlkt!OIA_ zOU;)PEM_yPnu>d6@;*xrGW=Gi(00E@{PFK5gB{iOe6_D{Tl~KkedFhc#Tutixs@du z<^6sm{^8a2{r!t{cN=Uo7ukI9p~1ZVqcQ2MBEj||mHeA+mb|@Jn$~`zV$s@or+dLE z(|6dsekbI+j@`VX#p3xpfv3A3-r2(Z%yXik^{%A?&aDFdDU0m?Fiq)ky8fEs)vQF{ z^T)5;6Yyb^3z7dORsH^a!HavlFGk1rKRxPtgq7{#&-Jy!j@$1w@7vClU{@rwYzGU^ z5%+_);@Mp9Gd@4lAThT+to20oOv&;sU%gLM_f=NCv{F1`cvJP<>ep>?N>h^N6s?#k z>NH1k+s+n=N!?ePrw0^ku=TA;(s;K#{`86Fo6j~EN>r+IsOsk&d6&JvW7{1c#UrdH z@q0SD?lQjc_BiAd%k0DZRl>vnKu)aMl#NjumvsxIem|Ha8x!j-l5Fgr=H?c?yJgSw z6MBVZS!Ny{7hm4;h>SHh@%I+g(v$SFNRZjIaCMHzOZValWg5bj2S08|<5o1=a#+pf zg}~fJoA7RzrmXdo0>o>nzD)9UZ-&X4>*=#GPBO& zuJyS+rTrgWqPMsF3C!s4{yifvUmD@RthN|;ZZ!o^F*$v+0eP9;;U`JwbE6O zH}9IKab5K2i=6cz3jep;~Vb;sFt z8zaj)ix+v%kw12_U|(?SLeR7fgS=7i>}xs_GMiuhS|~9&-Ns2q*hwb3Y32Q{g>K4T z$=O%<3^fgSUpjiu*rTy)Pn(^F>0GB4r?k>sr>?i_%Jr|Ct$Lqs#?p4MNJ-3l=g)|9 zUX4Lh^!}N}pV%PdwSL0GfUOcUU6)(ld?Pj6b@~evUI#<|M^84^LTWDEy?gh{&!4+x z&fLqIemgspq$cYxn||YBI|LqWST^6^sfY8-IlLO z3k8zfy}MQk%sz6SH^S$9W8U{fowySXdv^+ZtF~@|OWtW4g=J z)!+JEUh#s*J=VyCCo18^_Jmc*a&~(p*Sc>eUo?2j+4|6f zMds?-MZdEf7w-ux=~(o7^}6u+D{MEuHfY=aHfX7aYS#M~&3cNWwbtJj{Oz5aQCrGx zwe5|=@3!0*_dc+-#ocZF``sQ=N7v7IHRD%bX3ot7k+};KD+JpV6%R9VfBDNj; zbzblB3)ALG)G9mtF^_!oTTCOCdBc>jWE%~hzxwZmgzhvq>Q-Oaov6O+TK@5S^Y4MX zEtT~XVi)Bds0r#h<+t|*Pil!%+pajxBbGfTvoB7$+&k&8cw&dwVW$Y5v}PrPr}9l7 zW!V#ilHPFIa8<`@tGRC95fH%U9%?(sspIraR*AZ|3~ce0?85Kak~J;4&uxmbn7un8 z`{ki0FDt&}-P2ClA$?c>jnnyGwj2?kxxwAb-^T+!A2Dy?D7CsM>Gz#e@Y|W>Rn>Bn z=WdqBH(k8EhGlJH<_mtC=6B`&3+vn^ith0p|M0p!aCavEqxdTJ&#qHfR3+Q%?b#!J zmEHf)gjtNUCp`XPeca%SSA%!gZoWiKR}aJeK0Q}^3pxa=o&_=fy3ghGzI*q@-G&Yv z6P1mf6(@b4c<9if{+_KqtgnBG&AGhSsU@~}6_5ID*Qj)ZI~gv)W#*gwMHC9-x%A%n zxqN&5a7DeU#K-q8506yU^SG-%e#Bk9A^q)cj=C&$KfCXIo3_1iJAJJD;(kpBm!4zm z_jGgqSKhEJ#o?rWX=(S`yAf+L4_&xt@FjPGtP(gC)-GGU;B~y3)!F2rHeuN`9}Ypk zEi(*m<{XOn%u}VU9x(An!qw^>2^Q2-n^C`or(X z`n# z_9e`B!M`BsO^3J(J{G7=YQ8i-2wf@TYI1!CbFH z7oy!S{A{w{75ByY{<66e-}w(Z#aPL(J}uzV)Drz_v9sD79L#^&>vp8Axws>9&&?F+ ze3KPHGQx8odNlJbcIsg^wJMp$w@_zYnC%+fr89(TI5pWX2|O3?{JcA9nmH2OxqJDGEY0)JW@~gwCgQF zMYoH(r(C!U*=%-ti$0XIbn1R1ypqSRb?1xj7dQ7v@14!Rp!_joNj`_e@8Wz;&%EOo zUjJUm-|Kcmdp&qWWSz{f)9(8;Q!MP1QZ!mMQZ0g(i#yG6i+?Jz%iI0pjJutWW_UfB zqjO~Gg_szdS*=r?r%$LckQL0IbKu|d@11&u>$Th}d+*3}%v_Sgv#(SjR{GDy&4u<= zaku)GFlYm&)GwZk)HuKtyS0Q%86A?+*!2Z``_A_4kd(UO8ve%MwC& zA0|u{NIEJ~<#qgGm_@^{p0d)KbNxEbWiE=B`kyN3x^x&?$R6L`n)E-Iah1S#yN%N9 z^X_zh+mPYIHrMrex3%kZ35{Jx{yviGDXY||-u&Z_m%^X-d-_3(n2J&xEoye`Px|w4 z;jNYD9=^&<^*9kw*0EP~@(bPh4(S&=tgKEif9Rnp=5|u>)?M8$K`ToO-=6*Mf*MP9 z{GVCt)U$iymnZ?Bi7Q{!RrbGNd-_6W$&SqZKlbp?l`czqu+^Dk$NTBvYEhg2=ba<- zEq-B9@6=7XUN^0iH|=Y zRgUzyF~5hq`q2b|8BISLR7Bo&9!fc&`6Y+T;k#QsPY$=x+(ZMmc>Y6A7Eb1f+&>W# zc)^0UpH{+48eC&^M(02 zB;WZu+_~p+DN6=W8TH+?>Z9B?0URHz&T&`$c=f)9Jdd}rnNb#gfo7cljIzA z`1-BSzx=orzmI%IbbTZ?0V{ z?p>WEFr(+s_QQssz6oAbedm7N+q#v9f2EVm%{qbK^*=4ZnfH~W9nT`g#osUc?%W%n ze^zqGR@3YU8-JZy7ykP4?Ix|sQbk?Kt9_G7%AU>9aeDT#W=Z=Kg|`uAL43g`##;>uI)Rffui?O^b?ttf9m`)cJF(2_p`*UZSu9B8u@3J zD}P|TxAIUx$C364cM}s`&cFQ9?Avimq`9$n`GxPF?7rk%HZ)ZKaBxv(l+rGK|VFg zyuat)asZX8A9Y_HdTlqWa>YxhTa9c--fOvEk+$rpvt^gAKX$y{P(*2G*97JFK8c_1 z^N5MnIsM*!zkN?K?{<|R;SrmhZwdYlvs-lk#Nl7;+n{R+m+uSf4T?H2xfTCCXVw&3o)9Qw9@tUyuxh9-n_`l%66mu zR)XiQ9T|R}H37fN_iIm#-t^z-+uNo)i#qaD-mW}$%>5oXuws55IRAdu&VS4Hb{V}7 zNjUZ?g@29s!-@ zYfyPh4PDylw54s>)^J z=bkE_F%@x?FO9RWefOp|Xx6R&+n4Apc(Y#1uT<<^)l&^{7@s;eW8%k?s*ej6H&trP zC{7nE(hY3n>`D?){?f7N#_|O>)Dz-m#IAd4Y)gzdF1^rNxbvm)#HG7-?D!uzecCti zPYK(;-PhpPt$Z=JmwlS1i(9mGOH81|ZRvkk_n8@mbNg>Wg-N*2)~89J||7=l<=#_uuX6&L01~nw((W z))N)iSrx-&K0D{ym)%I8wv=OT)}9m&MQ4eylob}s?ik64D}R=dxmMS+T>a4{>rQUN z{B-Mc`=>U~+98;peaj)xx#Zv0d;ibz@BiG)z%}vXI!>o`7H4Ej?{CnT6brLI#5vUhgen$~@(gR$hfp7rcW?VqHC zPKPh~v9x~Qw^WdUwodCTbYfHIZ`Swejo+51k@7;ss6^}XBJDXP{U?Q;n$~FqbtrX} z3LLxU<&y7vbY}SG!m@0$Rp)&ds2}fJcSm)pYOT`dS23UePy2taH2&A2G_HvkugNQh zi+r-^y=oD$@0KK&q7`q!DZ`t0B~P6dxhbfX#Y-Y|qs8 zX;Umq;x;WZu9l3gJbmt&iF4GsiF3{eg4X5#PiK&m=_QJK&r%av8(_cjD zf9W|nPp5L7^Nj5E4tHj+wAic4{jzcEi&I-VEiO#6>OaS$=yp-_S=-hn|BrwDzp>jX zWy@Fh6Qb=)7ypX;ed)`jTe41h3r>_ef1j~O=}_m@a{(;gMJaLzV!S2w_Gr34^SN@& zZ-I5RVBrGw+kM-%ux?3@2&hf;iv0fBcQI&1I4If-V0=qWa-feo;y}9CTUF{;~u}#n!lT+k@X`r;qGe?mQ*CW1X^D@~ahZUhzE*JyjrbDn@?F zMzx;!Q!cOO36+;?v}Op$E)4zq=B3b5jr$d54d6Ulxk|SD!YVs z=_y*RU0e{=_VCKqLl)NB8niSdn8^{(EDyZV$wB7bJs! z@SCRJcFR`IPT1VD%Pr+}#|w_56*k5kM=vm^Mx7{FAoXoqk}PHHopm=R-rS}CyFj*x>Gnm5VBYqH{9XH`PgNMp9Nt>+CG^m}*hW=D zE&lYYi}i0e#qG>{;kR63_U+4SoZ5<4bYEQj=ZZlQ|MrE-#esW!^VQ`APPYViJkeTU zY4ltFc96B#X8x@T-vg|>_)HH5gfgXGP<2`weqzIB9&cY&r#4fG6Om5-(|G5;^nMYR ze^prd^HS9wHeaD2)EmH=-KVtLRHhfoY?~o)z6!7wROj%w&%` zvSLreJsb8}lg?^b88%Fphj!OKU7Wf-{{F;Ex$CS9yEbi5oYL}D`TvRuj|4Ajx?M@$ zlp`dZYF5(Wx54sY&$T0!TU0vF8Dz?x?R>QRNTkUTslduA9!bXDjE?II_j?E~{={_3 zzxPp4fUueUFEdE(l&-V>*ZX5$zoN6we_L!+!}2t-S%dqnTl6D^lC5GqPa`i#nK%C` zt`d~ZI_I~*EK7>l(Cv!5^wsmC>h2Sz?=;R@VW{X_x%`yPDc9{0H8lcHCoaCRabh-j zM+DOoz0VGAr;V8_Cx2f1@$k88KLo#|NnDs~*PLd_Q#;+!xt>rZ=TszlZBT370i&Th$SGWsa2l*UXEuZhnh`YSxK7F1WbS&M@iw zBJFIk+C`JsSXnPS6*x60=Fo3efWIX^y$Rf`I%Phf4d&u`SQoI z&%Znk)vQAdPp$i~;{`|Rp*BVH#H@3DNm~weeKS$+YL)Rm{421uil_9V)s^EfE()Z( zWOoTXnwAXCD66Mi?Elt3RX*?U@>7#*_ph?F6^kw}%Lysz^4j`B?DSEOnEE;y<)z&j z-ZLF{O3Xdo$G&v|g{>@-5=#{wwod ztz6wN=kET>L@hh##pyVw<`*oh{rVRvB^}W{Vi@AybRz2gVR@YXH9Kpb#gSIjK28?{p<{9b1oO? z><_G3^CkcEq1$zLB#iehR!%iruYcR>=Ip&W_jga-4O-7wBeL^aL`BsH;aKtI{|Z-R zeB38Kzs3?&zm__6_!r%szOHtr6J)1d(cS6$Ho!RGS>0Wu+wMlUBz`1kpC$FSjD8IL bCx1inz_X7#KWV{an^LB{Ts5pGfHS literal 1632 zcmeAS@N?(olHy`uVBq!ia0y~yU~~at4mJh`hWJk44ofvPP)Tw7+U|>mi z^mSxl*x1kgCy|wbfk7eJBgmJ5p-PQ`p`nF=;THn~L&FOOhEf9thF1v;3|2E37{m+a z>EaktaqI0}|8AA1vIjoi5B3i)^*{eWXOij~p6-tuW;96X9~3pL`ml{X zzGcFkTE&y0it80wKB_4ydN2v~%<8TZii{DO8k@Ln`R-M#=gG+I{gIxYUe$c{?@x#O zY4aN6L+h7k{j(8eWEfD;6J^v?`1|z!`@bu1f4A@MxNmM5Z#*%-`eCQ~+~;#n9^r74 zJsj_TM1J-hc{5&tBXhq#|9-z#ODV3uquqzuY_U;OVbm=D3;v!w37eevQ%<++&^C$8*B{*mMICzL1A*k(oD9>W?NrF$J6&X*a&JFM4E`7}qO zN!vw9Y3Y|+d+pLB+A?l`JDn(Dr@hofF!0@X=`^pG8!~6Ls|hdXYC7SuHFx)p+TY)* zW3R{dcN`8nRl9!TrSSdTD^_Xo@$=vQ`}gm$l)}?zR(z?wuP@epe`{{_-YG)QJ0HHx zt(+3H=>6{<#n1gVN39iG)~#SNcHN@nnv@=F&e;7C!JhnIm@1&}%wzV~@pLzxcZ^I)g$DXP@=!5pzrlDLPka zH-G;nle6|gUiWjpRPEpQ@6Md!m|Z0+=lU%#zMMMyreU?Wsju<=nxCJ(^4d8a$h*m* zWbdbXDnIDYhvHDb{9^vYhgTfX{cPqv@t>Gr{45rZN9U}qtbQpd<+&V5U&h#^(dF)* z?|S6(-3#k|m~rN_ZQe#rAAenUmyezKtj1L7-m0KaJ#XKC{E^&mdEQbuf6>HW&)el= zRtEhF_Ieq9@2x_Ib*|k?c~R#ZI_Fd6RtkMA2Pc0QzwhS~?|{vAeHM{}eRkQ;EwOUlyEkK@W+9^1u9t5^E>SEvuaZvd`1i&t;ucLK6V? C&0;$M diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index f345995229e76103b9e3185fb655bed63c99cbd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6230 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 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png deleted file mode 100644 index 4bfd7e88fb3dd8b740d0c571e976ac55c25e4652..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1915 zcmeAS@N?(olHy`uVBq!ia0y~yVB7%09Bd2>3@7{yv=|uJojhF}Ln>~)y}FT?L4k+a zalMa!uLQ%!yctbuyB@i1u%EfOA?@6%JG^@(tvMt(Boq=95*ivB!H|)Ojfo8+h>!pa zA|ycSAv(Yk91<`c5J8YZPzjJh$i}oaz$GAtKy-iwkZad8ir_6Xhcp?$Ub5N zr6+{{6%x+zB0>~z#Gu75%b6RF;B6$R|W diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png index b101495750a219ed203930268c3191d420795f63..0b194232bdd196a266f55ce77575458e35592898 100644 GIT binary patch literal 26389 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 C5c3!S literal 1893 zcmeAS@N?(olHy`uVBq!ia0y~yVB7%09Bd2>3@7{yv=|r|7>k44ofvPP)Tw7+U|>mi z^mSxl*x1kgCy|wbfk7eJBgmJ5p-PQ`p`nF=;THn~L&FOOhEf9thF1v;3|2E37{m+a z>EaktaqI0}|JBl=GRGg@_e`5~=5O?_eRo@w^hA!%?e6|^_Q$*$LA@GQ z5Pwm}f}rLL>wfo_%&ImvKHkc)ZcA?3vspiEULVrD@Aq!GI_Dh@hG7mo)Dkr2*Zuyg zzWrHuzxv5!vu)My_obKc#U(QR`u4NmK1G|sdG-v3k4!8)ADILUzMV|JU#lF~(6F)o zTw1X*!{Se>e0e_acAbdr>j>YwXKDT4&6-O+CVRHz+ch;fzJHi?J0mV{QTD8>3hYZF z{7y%TTy;9}prMj`;>5>SkAD4iwBTb`$BB(u>(_^0e=RO})4f%F+S!I9rFQb);GZSkE$YMYBJ1r01BS~(?x zy);iZo&DYPc z9gzMgDY19Q_jlD^EMRBkB{no1T|90S6VikKDl;1v+Wh$YeUAp0^PPt7ZtnHD zeDmh(@jSY?*!?EgfeC7A4tp3Fo%bB!7BFBCFmU_u;i2<({RESJM;!Bms`l#d+nOs~ z8hgBK_g|yucfS7kK10N{FfufBO6p5_HWr>=!PiS|DnF_0TG!pNL*`M>^YinM-@F+) zXYO1{8NLbI1tjm5?e0C^FaKY3{lO=59^c%Y9(aB0MaKgP<*&c~sykPC=JUKLSr(pO zI~sM5+r0nv>({iajt3IbEz=ztS$G&2nc>Lc00RVpUCAI|z`(+TK#a}iQ-VH8Phw?H*?fxC?ssyJ$dqE{vfa9dC$!qnj0MT%{T0*{awZ*yKzd;ocZ&QU%WW+ z;zI^ewFhc4va&~O?D}`DOWu9AZf5bjDxT|0G`dc&TD3^WJGr^xp#ABI%12krD^GqB)2~l=_3gXG6%yXee_WKt z;&9-GzP(+=gtZJD64lG+R7`0o{CS{B`l6X{Ol+*{?QMcP_n(gT(p=^$*nL!K(u$@A z$N8_mTE(ro?mYkFmoI<*T+6XDw~*2J@0uDid%8Y*f4Gaw_0sM0>}!8L=j9hLxN-IL zu762uHW!`SxH5ZjbHl-Rx0e0PIP-bdvYq**0tPpJx=ksT`+Y`y8aphmAh84?G2;rV z>aoC*j*cnE?1cpkZmd<)?0WfSwPF99X-}6v1jYWHLq4RvE@Y`&|zN^8~Q z$AOPZtLo$~FEX%_(O947R$f#k)qPZHo!RV++usu3^Or{6i_{S_oaxug%fzznPKsVZT!tYDz}~r p+hLinKRxa?DKR$$)$W;R&+s!<_qpo3v%Mhad%F6$taD0e0sxQDPx=4= diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 2b23a8c9145eef16e8f3088bdfa00c1ed549a70c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8868 zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Bd2>3_*8t*clj~)jb)Dr4c`{` z{GRuFg>OwANv^JoH}cK8!5ty6rh#>7`2;ON#~wqqV@5Mi?%A_v<{6(;r+ti0F3B|N z?20w))ST5BKTCgRiqYg{lA_;kzm4IW&i(MxJIn8HKG(h$Zj9dX{Qvb|;Ww+9JG^5a z2~FQ|L{+b_6T#g2dD4PCcNi{Sbjy1BRBiT}hlOmvK&=@nQ)>?(w)!uP0oe zz^QaXQO~;S%Y1fA#@E-@)&o_)_dFJ6^G}oW1o`FnyhfYmrth0$GN{)zAS!xU17az z+~hrFpWok2QES<8BvtrDYUjl->FWX}S@PTt(m1Ji{Qp0}=8w8L@kI=a^)^}ko0Y%u zd&B+H?>4D^D7YF>A+q27bhqF^l@ki<=70XurgmTdj3n36o7o$l+aB2a(Oj2da^+#Lv>(RAue{WN?i1^DZb0d_wy-e;v{Q8A08@`!$o>0)MI$5<(&_U?# zLX%>ysnV*E?i*@TMGJT)Y!^AO?s=Ql%_rAaW`B_@3ucPA6@H^HLA%*GH2A^8qVH-G z8)xh&nSN%LRH(nlqR3g6oazfiB?6Xj_?yD|g(qi|_`8|~x6^i?e)aIcIjbA{KZ~*b z$^ElcRkH3-8CNvxpG{dpHh&77i+m@geVWX4s(dV?oqaa z_k%BIgT@Q#9>J!G3)gW<@`dhaWG_!Wba3v$uurUt{W1~HJS+<5bUJ?4@K>4r`IATR zwJ8kK!rFUX+mEIE5SsijaE|$z91+GAo1zI>e#*K2lW$&Mqq6Q6%idg;4Q_2!+(vtj zO-grNr?ARhYP!|a%zF`!R1zDmn|=JI)42A!$%or+3`>1><*I63In)??@q#45&ugc}4(xw>;lTR}CKG{1Pi0lXxVFDn zFT0uqv|r0-__yuPy*#g*?aBzf%B3L2miIW^6vL5Kk(j)$z)2v)X>Gu zSN#wC`^{#uO00ABWL5vbFdeqvrgu-t{uVkgOJ^6`Z|&q(l~+0^m8<_XG0E$c^Sz9F zx1yQBH}zuUtN2;f>?%SWo>v+tEjK6@V*BIz@N1|mL-xf5Vsdv3BRv-NO|dx|*(ven zzIKEDo_)JG7Ranuh_C1Wt!2jTc_r?{z z-t=eV^Z%P&r@AxjjbzFR=4KR_ub&kEeszu5sp4InLN}QHt&LRd3S_IDZobu%VM#={ zgVI6E8=*p49v5akyLRnMp~MGy&b{j^nNB)cTCU)(-1Lq#4 z`nE}zvi@82MN*7ck1^%Ax&t%kx4i$1THMcGbh8-!_#AY|@WFn82iH{@B{)y)uRgWE z<ChZp>e3k-Tb~r-J(4%+-58@>;2v>{oDDeR}b4t&JjD zyEvp5{XKg(iT71qnyX|x%MVt@9JPb@-g0bvZsTR>QpD){l=)4H^QD)uiT-!rZ`0*x zeWT%ItK}_oFXnrgg%D$eokQ48(bQwXI-2}nE;M|Zs9?WVUnISD(T%+ePdDg4ye{+g zfM3YpPuwrgr~56st`}EOG5hP4{~(3BUOi zcWf7NOss0!wYWj2*2wJJflJSst3BkCT=?zF-sI~tFZ*U=RrGLwz zCrr5DzgH!J#lRu(*xzq=jxMbKYW8LK<9svjKjHp!UG!zGyW*^VEz2!?K1zS&&KcPYp%szT5ifx@$<;XGT{ane$!Km?CK8A z`3ceAPD^B~71ukMUP{k?WmK)YZ>^exFS`K4X+=i{YqcX+k8%_RJ<@pg=AL4j^6Her z-O}IwnST5BuZh80)}CuZ=fzKVHgBlt3SS)S`sT*RqxbA{_e$;AuW-O`u1lj33+qZr z8^yA1+rNKrdDQbcYvvabmVyFhQAH`%qI-?3+fn_Ud9_8ES*fLH=iq-Tv`2kv4cxXr;)zD>{NM2hPi?ceN3UP z97g6xgLTRh%OlqPp1nZhaiwWxy<@}NUtLToKT`^i3HG=?U-z2(#4Y>c(;`O?UMX#2 zXksXP$@gAk2j@!8;$7>Mj%=AG$aVSq>cZaj3JvQP9mw64u}tBsVb@8&^UNu4=g+yo z-(_U~>{h%ni$bx@Th#-nkN0;*Dwqm3yiwnx`@J|q+<3`nZKoavw-f%pA<>_1OEFFG z^fS78Q|^8Jk2jf)3|mzXTXzels6GqKDT^{X<2C=toPtLm7u}i^fAd$^bW?l2vz{Mb z%?vKlxus@ZDK+tVb;Ek$X^Pb+*& ziTJl9rTD}3)oXt#m$ltqmd-Tc?$XyU8)BXvdn>Y9)`MZ^ug5&DFVC;s_)XvEJ4=F5 zM@TbQP=85|smC`F{yJGB`3^6>4~+5J_L z6&kF*3*X%+>Ue2a?;fcu?`|q|x-+Do@Lw&~9?ikDVxNpx*~HT~N;;CJC2WrsUi9gK zbc43YGWoFTpTPnS#~-MNDkwFdxTg7YrK!Z`c_O>dG;a6)KRdyCWcv-iOWnr zOXCF@C7YVS2i7kG|m%~@)mGWELaf$Mr9cji#4Q}qadCVn3twB2__v9t5AMI~e zIy|kf6|*h;WMQj&X`=3lML&!veR1)rXr zEE8@xq3*~qRk-0#^sLXOI(xE(=5rS1+A>N+-%+s2l3}~DpM{Zy(ZsW1)0=$7tUQ*Z zMYA~scIPOGe4c!tm63&Ui(A8|J+C+9oV&YCxZ&?6>mz#edk)q+3pfZk6tgHi7Pwtp z-=zBad616(tS8s1m^Q?hwVR$^p6GB_ghhbmf(qlQ&v^$gv2trn6W1-u*Jb2MV>;sI zXDr{W!lA&iz?A9Ez>`@Hc^uKIyZKOYye{BQ%gX>sa>`onu>8t1Az z1PDxa;7;#pd(`t^7~&SMP5YWURtD!zcQ9g1^Wkhg)U!HC#Hq(Aqex_t!DHhY5_adx zm^K_WkTb}+!Jy%@U#0Eg5ra9;I5w;oa;!TgDq&M0anz{zRok_^_CsQa8CaYgZ)qCx z=^k6S)toQZ@f=Szck&MYqeipyH+M3qWWHdlJh?urmqGb^*h2pGaiZKwUv??=2sGqO zn!WX4!(>XG?F5G%LL5+jw%Mz9oepNBq+J}xz@^EChv6rlK#o8&a#weqbK z%3GK@8hU!aXBGzjdBR*B@b)P`3*(nv8vAy&j^1dx=!R5aaI~^m zdL4W5GS?s;08S+%Ou<8-gaV8|M%eCgdKYR6Ir^A53w*_nZt1Xa32#(_O$TeH*D;`KO9@<%M$R7 zX_w=drlV0Yl4=|a4ztV%Y4F;dcc|%Rp~&tvbMl+aa{9E(oBt}-q)7O+{MQ2|!e4v_ zl1-<5|A`#ynd7rDJ6U*5q2`nvb;na4DGM~rU#d=I=U`e9_kXh>hY_<$L(=rnhMrtS zhSe;U)xR%$1)Tbo1yvA!k?+HLjkKGJm3rHzIY@^${rdiW@y(K)Ct5xY(N1ifOe=OV zhRv##R(if9;EWN|jTpwP7|u`Mzb{i>x@6^s&?k&d46p79#VY-(cX=Vwb<-@YK}!8l zPOJmNwz>%$UrH7x?NMmR5`IwaJ#mZbJAHQ9My@kc&P)#L=Jon3S-!S(tP~8G@sEG)35891 z2X^YP@60`2Tw(l9^ZMUE{UH;6@%rp9Hax0zI(F{uSq#y7{a>DVpKek}{;VCP(Oxy> z`C`%iwJf3gzSvlOxRqG)q4fB+&i?;V_n)4>o9f}!xB8%jtjoqzRS~(@{!goHkglj= zyJVwax2>buXY11oa#K}BzHF7RX}I_IgLCYSNA`am??3fds!v+x)t`L@L7FZ-8sQ?++7?qA1wV7tS_PeK1VCm#|I>iPCk_`vJ` z$G!YXZxb3)F(vh9ODG3#SRztK7BEj`}r)^Q_=7Dwx7FpZBg*^^S4vd^C4vzMkBGjsK)OM6!;@2P)Wv_hwu?TZ}uPS5wNCo&xTey^Fc z;GWfw`}Oj&wuMZ43*SV{ev{$LyX(U_>m~-R+yC89-6;|M^=+=lM$cFO-|EzFQ)%9_ zAbR_~5VqWiuLAu{vlI_xzBzfDtL|o&-`t>7kqfGfC%&oQ{w%mA`d@UHXPfW(zA5&; zsRGuOyXAf6nuvc2{BW)X$wD5jFG~%|-HeVVZO_|VaroNG#ZUb&FO!JOWWFGN zTfn35zjQB?)=M64rWZ>-N5?v`-Sa1HCrYT>#oAJm|V#cHZ=GK?1I+&UmtUmnP z@=>&$F*)DjsDkw6!uLM!^K~V^9X#{eeRqC$n!2-J&|axyOIR6YYTmVH{;!HKSly6x z{``9Tqe<#&`*r6l94@;r#nzb}-@G=nte>fgf$!blaxuls%d>><{Qmy@-u=bKlkY#X zKD?{+0@Z;pEs{YXRUi3!CP=0>G zpL~rYE^m)=8hW>N8@;;f(s0Xr`i0rY`?pK}d9pD*EBmOy99ywHQ_>V8HvR|~Nw%|V zt`NPnS=(#=+LNp`1tKq;XTE%5BBg%h`9g)OddfmQ3}^eD=hy$vEoqXO=Iht9{b1II zOeF}fvaQ+?L%~a&7aX^MO&9A%tORxD`#nuyr zj`fzsyIeO2a9$P@=1zK}P5f};c2%9M zcm6g_PrYHI3isQZpOqVx&Im5yS9FLpGg=e*Pvz*8Zf}mG5#rbX=2}MFmTyNlV4=>e@SWYO{rcb9UZ!(3 za*M6&4l8a65jC`w3%Y)PL9$S+1gDA&Yg5_O#jB>zTmHKFf7LslZJYUWjpx^#Ik?21 zb<(Eoe^`vw)dO`ZtNEX0UwS%IKD44fd-9@vCFybE(-oIQr+0K#aTuAMWO;FEm4Kzv z*7Q(LsSe>}ck}b?+Ol51CM234KBc;Up=`YVdPR|7p6I-98r8Sv32ZKKy;mV|7TXuXie=9v?wYs>U^4pcc>rN-b{ zwf(tr=Hpr0eH$BtbxZcocRlPK%(B7EQ0hSVdtptJLoQm*g&U_UW^Yz#l;d+CpT6lP<=)%X^mXI>Pcs)rGo7$fXebI^ zz2rysv5kqRGcTPsxHv!AW%925rav3@9R0=chrM5gv%m1pjEs)>O5X_%=7JBzVz18@ z`rrET+=r_sFTZ}4W_^?J`kjpOx+smxTUxD8{x$ID=djH5G_cE2J#suwxah<|PKOl! zkAF@U#!IR9$FF9npP=+I^xALLf(hO;MNaz~ePZV~nXFJ#(j&6{QLvSH$c(z^DIT(2 z3|~e5SZ_AFyB2#hWC$dXj|1q{sV`bD;f zl`z+3cV|pdF?i16=jZoO!1Vw32|L6(HG_Hu8ye>4BsaaEy`|{ouEONY@6+AP@B}X#q3vdaomDKk0VQc8J6BtKlyH2>3pd)zmrQIl$XgJ zeV;l(>7nR@d_}`)-b(J zsmBu@{CqO+VYPW%{~`W>DOOLj`WfoERVK_%&1vV1Q#>U9D&la{O!lQeZpgnh(bSyU zm60INbRus4oGTu)qG!&oGtr6upuO(<)0A?9{q43tY_Gbm+`M>Js$Gp<%Ns^XCudFd z#=<`@z6RwyvEEQA`)K*)JC|xrUTA@g=rOSgXnY~_|Jc>{Qp@k|?7Sn*_b>3vyp7f3 zD_(ry`f%I8?BS{QMJMDYys=PAe=eBv+I5lcMqdM+Ie#Vk*sd$iH9I$9-D1ad;ReS2 z4@u*DtWP7c~SB1$**d4!e81ZrJl31 zeDeK5hI(nw1#1L;7U^nwFPhkuVQ|l&{Fza9kc2iToPKZ%debZWBX%oP*@eqkK2)IQ$I81x2j03SR-^XL%^uO(B)jM zTUYq@-wtkl<`|BHFI(@Q& zx4aotKXe{fj~AXhe|kx9SM1b0laMpE&V}S+t|9uz1^@0|)F+HQKM6c&D&T?wEaY|4$Wzo%+_ZmDWlbzpw+`s@Mq`|ADLXWfF1 z9jo`sp8mh}`sc%E52P2RTm1K7|8U--q5j#S*S9CKOnVx%Gf3owbFsjCm%a?A7RBai z63@<6L_`Vx+_xn$RMvM!q_eN)#8;;N4Bi)nJBv3+1?KyQrHd}PH_dGQ?*kiZF0SuY zZr90VsWCfd&{W^%_{W$xB&0&;^lYX-WqoYZHm%sLWS`)opptOXNVVzY+1#$gPc1c? zMen*Vy-K~Va>-l4*R*V3q;tvzCPfa$HICbw@BRe(6-D^tiUqK~LCgMFkt5aXev>cAY1X_vU{6 zLdB$4e41JJ1dSy<9?hApb6RERaK2+hx%Jv7GaTjRtB-6bC==Bb z*WUA2qG}eub|znN#h-m#52`<&zY-Zzu|>ICr&Gb5#nPQ)Y3Sm%PcI|*x(Xg2sO#pv z{9b3e*x5SAuFgG5s%w4;Zabp5D`CFxA~RK%-@A%C4{nm@tKgk(@{ILxQ{?U5g^CkxR;C_M7ixd`+aT`rbkn-|VGQvN@rPYFo^;Br zjA#Em>0W`9=nnUgNe7?2mQIwguHv4?{d?((o$X6+tk4d+)Ajzv3s*0uMckzx{~XHp zq%BbhyYFFF+H-aG{P_YCPMAzOGFhWlxJtA3aJk5bkB05M-r_O_KKqnUURisa=jZzj zma0$Njb<9R)U*BlnJ%Q!@cxI(hbN`48SWjJ_%x8?dyDcJp_Q2>67C#{GNwxR400cp z9saYsUSBuzLz{^3*TyY*N3UB1#Vo(NG{uMKQiJl76TV3-njXn2iSEbEoPfd9BOxp37)09ugPF^q9nQFoF z<*?|zxM`NQKhqx`wwGqCVOMXOqjUOcaB9elbjP;Dw3$~d(j``ZSo640$+Gv1|hwH)X299HCi<<1O@82sjF;T#u=cS^2(RRs-t1gT- zs+uX%#~rN>K6zzz_R8MhGRg1nb@v=(p7zki)1PwxB!9|&+Ff%aXOGkN z_Gm`y)psUX*6{E8W6;CDjQ8pL$_a-qe}7azyWaTTJ&lI-`&Ugg(%KQB=&UfEqjra1 zn2^$x>hMKN-5YJR9=x-YtA6m&k2f$mXSdI^q#u?ii)Y8T?@_DHy?I!h@&5e%&*%Ng z-@vlByLG#GsH~vqnLtNRHhw+9nw@^rI4{oj?qu8(X4m1}qbSqkY-#XP@5UU3#kx6b zT2231GXL=SCv*5maoeZs91qu9PT1dG_s8~R1OJ2fH)sFnowh*yUR=ytwdT!A=@U2= z-8=GP!oEBaTFlR$T+eq#f$vfRt7nRIPU5NgypQ@NPs~qds6SWt$F%C>^*874H@|t9 zdf@b|dyx%sF>h6yO`T2%9-4caOP|jneqIDyK>}ORgl`WTrgkbt=jWYze{%ozW_z;< z_TdcmdGY_E;{I&CD=K$S>H+JEqgNGEHmJ0i2JI*^*rln|w!BH@UKdBw*(dX>HRYZ! zWY{TP&zqgFovnhgs<2d2Q>RmL@?lR$p>)>BH8VezPw6)`WiDYXD_q$paCYM13p|l) l8gE@-I>GwD`oph!5mT|n^Hyf)GcYhPc)I$ztaD0e0st>Mi_!o9 diff --git a/app/src/main/res/navigation/home_nav_graph.xml b/app/src/main/res/navigation/home_nav_graph.xml index be77128..4fda2b5 100644 --- a/app/src/main/res/navigation/home_nav_graph.xml +++ b/app/src/main/res/navigation/home_nav_graph.xml @@ -50,6 +50,18 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index db8e8b3..d65af25 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -75,4 +75,9 @@ @string/app_force_stop_launch @string/app_launch + + + @string/edit + @string/delete + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 626698b..31e61b1 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -7,6 +7,8 @@ #375634 #8F3232 + #6D6D52 + ?colorPrimary ?colorOnSurfaceInverse ?colorSurfaceContainer diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 7530e7b..f8aa354 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -9,5 +9,7 @@ 6dp 1dp + 4dp + 8dp 16dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d6e4d43..6011d8f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,6 +7,7 @@ Settings Manage templates Template settings + Settings template configuration Manage apps Select apps App settings @@ -31,6 +32,8 @@ No Search System + Add + Edit Follow system @@ -73,12 +76,14 @@ Establish templates for \"restless\" apps, controlling applist they can obtain.\n\nBlacklist (recommended): the apps selected in the template will be invisible to the apps applying the template.\nWhitelist: the apps not selected in the template will be invisible to the apps applying the template. Create a blacklist template Create a whitelist template + Create a settings template Are you sure to delete the template? Template name Name invalid Delete Template Template name already exist Applied to %d apps + %d settings added %d apps visible %d apps invisible @@ -92,6 +97,7 @@ Using %d templates Using %d presets Using %d settings presets + Using %d settings templates %d additional apps visible %d additional apps invisible Risky package @@ -120,10 +126,18 @@ Custom ROM apps Suspicious apps Detector/Checker apps + Shizuku/Dhizuku apps Accessibility Developer options + Input method + + + Settings database + Setting name + Setting value + NULL Save logs @@ -161,6 +175,8 @@ Clear uninstalled app configs This option allows you to create a config without remnants but you\'ll have to reconfigure apps when you installed them again. This action cannot be undone. + Alternative package query + Don\'t enable this option if you see the package list in this app correctly. Language Participate in translation diff --git a/app/src/main/res/values/themes_overlay.xml b/app/src/main/res/values/themes_overlay.xml index c3ca1c8..dae0333 100644 --- a/app/src/main/res/values/themes_overlay.xml +++ b/app/src/main/res/values/themes_overlay.xml @@ -23,7 +23,6 @@ diff --git a/app/src/main/res/xml/app_settings.xml b/app/src/main/res/xml/app_settings.xml index bd381ca..78d201e 100644 --- a/app/src/main/res/xml/app_settings.xml +++ b/app/src/main/res/xml/app_settings.xml @@ -55,6 +55,15 @@ android:summary="@string/app_invert_activity_launch_protection_desc" /> + + + + @@ -66,6 +75,10 @@ android:icon="@drawable/outline_assignment_24" android:key="applyPresets" tools:title="@string/app_preset_using" /> + + + () - var loggerFunction: ((String) -> Unit)? = null + private val manifestDataCache = mutableMapOf() + + var loggerFunction: ((Int, String) -> Unit)? = null companion object { val instance by lazy { AppPresets() } } + fun readManifest(packageName: String, zipFile: ZipFile): String { + var cache = manifestDataCache[packageName] + if (cache == null) { + loggerFunction?.invoke(Log.DEBUG, "@readManifest cache is null, reading manifest for $packageName") + + val manifestFile = zipFile.getInputStream( + zipFile.getEntry("AndroidManifest.xml") + ) + val manifestBytes = manifestFile.use { it.readBytes() } + cache = String(manifestBytes, Charsets.US_ASCII) + manifestDataCache[packageName] = cache + } else { + loggerFunction?.invoke(Log.DEBUG, "@readManifest returning cache for $packageName") + } + + return cache + } + fun getAllPresetNames() = presetList.map { it.name }.toTypedArray() // fun filterPresetsByName(names: Array) = presetList.filter { names.contains(it.name) } fun getPresetByName(name: String) = presetList.firstOrNull { it.name == name } - fun reloadPresetsIfEmpty(pms: IPackageManager) { + fun reloadPresets(pms: IPackageManager) { + presetList.forEach { it.clearPackageList() } + val appsList = getInstalledApplicationsCompat(pms, 0, 0) for (appInfo in appsList) { runCatching { - appHasGMSConnection(appInfo, appInfo.packageName, loggerFunction) + tryToAddIntoGMSConnectionList(appInfo, appInfo.packageName) { + loggerFunction?.invoke(Log.DEBUG, it) + } }.onFailure { fail -> - loggerFunction?.invoke(fail.toString()) + loggerFunction?.invoke(Log.ERROR, fail.toString()) } presetList.forEach { runCatching { it.addPackageInfoPreset(appInfo) }.onFailure { fail -> - loggerFunction?.invoke(fail.toString()) + loggerFunction?.invoke(Log.ERROR, fail.toString()) } } } - presetList.forEach { - loggerFunction?.invoke(it.toString()) - } + presetList.forEach { loggerFunction?.invoke(Log.DEBUG, it.toString()) } + + manifestDataCache.clear() } fun handlePackageAdded(pms: IPackageManager, packageName: String) { + if (presetList.any { it.containsPackage(packageName) }) { + return + } + var appInfo: ApplicationInfo? = null var addedInAList = false @@ -62,11 +93,11 @@ class AppPresets private constructor() { if (appInfo != null) { runCatching { if (it.addPackageInfoPreset(appInfo!!)) { - loggerFunction?.invoke("Package $packageName added into ${it.name}!") + loggerFunction?.invoke(Log.DEBUG, "Package $packageName added into ${it.name}!") addedInAList = true } }.onFailure { fail -> - loggerFunction?.invoke(fail.toString()) + loggerFunction?.invoke(Log.ERROR, fail.toString()) } } } @@ -76,10 +107,14 @@ class AppPresets private constructor() { appInfo = getPackageInfoCompat(pms, packageName, 0, 0).applicationInfo if (appInfo != null) - appHasGMSConnection(appInfo, packageName, loggerFunction) + tryToAddIntoGMSConnectionList(appInfo, packageName) { + loggerFunction?.invoke(Log.DEBUG, it) + } if (addedInAList) - loggerFunction?.invoke("Package add event handled for $packageName!") + loggerFunction?.invoke(Log.DEBUG, "Package add event handled for $packageName!") + + manifestDataCache.clear() } fun handlePackageRemoved(packageName: String) { @@ -93,7 +128,7 @@ class AppPresets private constructor() { ignoredForRiskyPackagesList.remove(packageName) if (itWasInAList) - loggerFunction?.invoke("Package remove event handled for $packageName!") + loggerFunction?.invoke(Log.DEBUG, "Package remove event handled for $packageName!") } init { @@ -101,6 +136,7 @@ class AppPresets private constructor() { presetList.add(RootAppsPreset()) presetList.add(XposedModulesPreset()) presetList.add(SuspiciousAppsPreset()) + presetList.add(SDhizukuAppsPreset()) presetList.add(DetectorAppsPreset()) } } diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/Constants.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/Constants.kt index e0e8274..d1cc3b1 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/Constants.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/Constants.kt @@ -4,8 +4,8 @@ import org.frknkrc44.hma_oss.common.BuildConfig object Constants { const val PROVIDER_AUTHORITY = "${BuildConfig.APP_PACKAGE_NAME}.ServiceProvider" - private const val GMS_PACKAGE_NAME = "com.google.android.gms" - private const val GSF_PACKAGE_NAME = "com.google.android.gsf" + const val GMS_PACKAGE_NAME = "com.google.android.gms" + const val GSF_PACKAGE_NAME = "com.google.android.gsf" const val VENDING_PACKAGE_NAME = "com.android.vending" const val TRANSLATE_URL = "https://crowdin.com/project/frknkrc44-hma-oss" @@ -14,6 +14,20 @@ object Constants { val gmsPackages = arrayOf(GMS_PACKAGE_NAME, GSF_PACKAGE_NAME) val riskyPackages = arrayOf(VENDING_PACKAGE_NAME) + gmsPackages + const val SETTINGS_GLOBAL = "global" + const val SETTINGS_SYSTEM = "system" + const val SETTINGS_SECURE = "secure" + + const val SETTINGS_TYPE_GLOBAL: Int = 0 + const val SETTINGS_TYPE_SYSTEM: Int = 1 + const val SETTINGS_TYPE_SECURE: Int = 2 + // const val SETTINGS_TYPE_SSAID: Int = 3 + // const val SETTINGS_TYPE_CONFIG: Int = 4 + + const val FAKE_INSTALLATION_SOURCE_DISABLED = 0 + const val FAKE_INSTALLATION_SOURCE_USER = 1 + const val FAKE_INSTALLATION_SOURCE_SYSTEM = 2 + val packagesShouldNotHide = setOf( "android", "android.media", diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/JsonConfig.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/JsonConfig.kt index acd11b0..47065da 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/JsonConfig.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/JsonConfig.kt @@ -1,14 +1,10 @@ package icu.nullptr.hidemyapplist.common +import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import org.frknkrc44.hma_oss.common.BuildConfig -private val encoder = Json { - encodeDefaults = true - ignoreUnknownKeys = true -} - @Serializable data class JsonConfig( var configVersion: Int = BuildConfig.CONFIG_VERSION, @@ -19,7 +15,9 @@ data class JsonConfig( var altAppDataIsolation: Boolean = false, var altVoldAppDataIsolation: Boolean = false, var skipSystemAppDataIsolation: Boolean = true, + var packageQueryWorkaround: Boolean = false, val templates: MutableMap = mutableMapOf(), + val settingsTemplates: MutableMap = mutableMapOf(), val scope: MutableMap = mutableMapOf() ) { @Serializable @@ -30,6 +28,13 @@ data class JsonConfig( override fun toString() = encoder.encodeToString(this) } + @Serializable + data class SettingsTemplate( + val settingsList: Set + ) { + override fun toString() = encoder.encodeToString(this) + } + @Serializable data class AppConfig( var useWhitelist: Boolean = false, @@ -38,8 +43,10 @@ data class JsonConfig( var hideSystemInstallationSource: Boolean = false, var excludeTargetInstallationSource: Boolean = false, var invertActivityLaunchProtection: Boolean = false, + var excludeVoldIsolation: Boolean = false, var applyTemplates: MutableSet = mutableSetOf(), var applyPresets: MutableSet = mutableSetOf(), + var applySettingTemplates: MutableSet = mutableSetOf(), var applySettingsPresets: MutableSet = mutableSetOf(), var extraAppList: MutableSet = mutableSetOf() ) { @@ -48,6 +55,11 @@ data class JsonConfig( companion object { fun parse(json: String) = encoder.decodeFromString(json) + + private val encoder = Json { + encodeDefaults = true + ignoreUnknownKeys = true + } } override fun toString() = encoder.encodeToString(this) diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/RiskyPackageUtils.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/RiskyPackageUtils.kt index 9c51e3a..0a35b4e 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/RiskyPackageUtils.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/RiskyPackageUtils.kt @@ -11,28 +11,20 @@ object RiskyPackageUtils { fun appHasGMSConnection(query: String) = query in ignoredForRiskyPackagesList - internal fun appHasGMSConnection(appInfo: ApplicationInfo, query: String, loggerFunction: ((String) -> Unit)?): Boolean { - if (query in ignoredForRiskyPackagesList) return true + internal fun tryToAddIntoGMSConnectionList(appInfo: ApplicationInfo, packageName: String, loggerFunction: ((String) -> Unit)?) { + if (packageName in ignoredForRiskyPackagesList) return try { ZipFile(appInfo.sourceDir).use { zipFile -> - val manifestFile = zipFile.getInputStream( - zipFile.getEntry("AndroidManifest.xml") - ) - val manifestBytes = manifestFile.use { it.readBytes() } - val manifestStr = String(manifestBytes, Charsets.US_ASCII) + val manifestStr = AppPresets.instance.readManifest(packageName, zipFile) // Checking with binary because the Android system sucks if (manifestStr.contains(GMS_PROP) || manifestStr.contains(FIREBASE_PROP)) { - if (ignoredForRiskyPackagesList.add(query)) { - loggerFunction?.invoke("@appHasGMSConnection $query added in ignored packages list") + if (ignoredForRiskyPackagesList.add(packageName)) { + loggerFunction?.invoke("@appHasGMSConnection $packageName added in ignored packages list") } - - return true } } } catch (_: Throwable) { } - - return false } } \ No newline at end of file diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/SettingsPresets.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/SettingsPresets.kt index 85d5be9..4302c06 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/SettingsPresets.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/SettingsPresets.kt @@ -3,6 +3,7 @@ package icu.nullptr.hidemyapplist.common import icu.nullptr.hidemyapplist.common.settings_presets.AccessibilityPreset import icu.nullptr.hidemyapplist.common.settings_presets.BasePreset import icu.nullptr.hidemyapplist.common.settings_presets.DeveloperOptionsPreset +import icu.nullptr.hidemyapplist.common.settings_presets.InputMethodPreset class SettingsPresets private constructor() { private val presetList = mutableListOf() @@ -12,11 +13,11 @@ class SettingsPresets private constructor() { } fun getAllPresetNames() = presetList.map { it.name }.toTypedArray() - // fun filterPresetsByName(names: Array) = presetList.filter { names.contains(it.name) } fun getPresetByName(name: String) = presetList.firstOrNull { it.name == name } init { presetList.add(DeveloperOptionsPreset()) presetList.add(AccessibilityPreset()) + presetList.add(InputMethodPreset()) } } diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/Utils.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/Utils.kt index 1572f2c..522f41b 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/Utils.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/Utils.kt @@ -28,6 +28,14 @@ object Utils { return result } + fun getInstalledPackagesCompat(pms: IPackageManager, flags: Long, userId: Int): List { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + pms.getInstalledPackages(flags, userId) + } else { + pms.getInstalledPackages(flags.toInt(), userId) + }.list + } + fun getInstalledApplicationsCompat(pms: IPackageManager, flags: Long, userId: Int): List { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { pms.getInstalledApplications(flags, userId) diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/BasePreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/BasePreset.kt index bd02e62..7d0f98e 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/BasePreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/BasePreset.kt @@ -13,6 +13,8 @@ abstract class BasePreset(val name: String) { val packages get() = packageNames + exactPackageNames + fun clearPackageList() = packageNames.clear() + fun addPackageInfoPreset(appInfo: ApplicationInfo): Boolean { val packageName = appInfo.packageName if (!containsPackage(packageName) && canBeAddedIntoPreset(appInfo)) { diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/CustomROMPreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/CustomROMPreset.kt index c112019..d1a83ca 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/CustomROMPreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/CustomROMPreset.kt @@ -3,7 +3,11 @@ package icu.nullptr.hidemyapplist.common.app_presets import android.content.pm.ApplicationInfo import icu.nullptr.hidemyapplist.common.Utils -class CustomROMPreset : BasePreset("custom_rom") { +class CustomROMPreset : BasePreset(NAME) { + companion object { + const val NAME = "custom_rom" + } + override val exactPackageNames = setOf( "io.chaldeaprjkt.gamespace", "powersaver.pro", @@ -13,7 +17,7 @@ class CustomROMPreset : BasePreset("custom_rom") { val packageName = appInfo.packageName // LineageOS overlays - if (appInfo.sourceDir.contains("_lineage_")) { + if (Utils.containsMultiple(appInfo.sourceDir, "_lineage", "lineage_")) { return true } @@ -78,6 +82,11 @@ class CustomROMPreset : BasePreset("custom_rom") { return true } + // Xiaomi.EU apps + if (packageName.startsWith("eu.xiaomi.")) { + return true + } + // TODO: Add more custom ROM apps return false } diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/DetectorAppsPreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/DetectorAppsPreset.kt index 404bb56..2695fcb 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/DetectorAppsPreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/DetectorAppsPreset.kt @@ -2,7 +2,11 @@ package icu.nullptr.hidemyapplist.common.app_presets import android.content.pm.ApplicationInfo -class DetectorAppsPreset : BasePreset("detector_apps") { +class DetectorAppsPreset : BasePreset(NAME) { + companion object { + const val NAME = "detector_apps" + } + override val exactPackageNames = setOf( // Detector apps "com.reveny.nativecheck", diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/RootAppsPreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/RootAppsPreset.kt index 0e744fa..eafeded 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/RootAppsPreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/RootAppsPreset.kt @@ -4,7 +4,11 @@ import android.content.pm.ApplicationInfo import icu.nullptr.hidemyapplist.common.Utils import java.util.zip.ZipFile -class RootAppsPreset : BasePreset("root_apps") { +class RootAppsPreset : BasePreset(NAME) { + companion object { + const val NAME = "root_apps" + } + override val exactPackageNames = setOf( // rooted apps "io.github.a13e300.ksuwebui", @@ -40,6 +44,7 @@ class RootAppsPreset : BasePreset("root_apps") { "me.twrp.twrpapp", "com.slash.batterychargelimit", "com.valhalla.thor", + "me.itejo443.bindhosts", // Scene's "Core Edition" cannot be detected in the Xposed preset "com.omarea.vtools", diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/SDhizukuAppsPreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/SDhizukuAppsPreset.kt new file mode 100644 index 0000000..7f4f1f8 --- /dev/null +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/SDhizukuAppsPreset.kt @@ -0,0 +1,37 @@ +package icu.nullptr.hidemyapplist.common.app_presets + +import android.content.pm.ApplicationInfo +import icu.nullptr.hidemyapplist.common.AppPresets +import icu.nullptr.hidemyapplist.common.Utils +import java.util.zip.ZipFile + +class SDhizukuAppsPreset : BasePreset(NAME) { + companion object { + const val NAME = "shizuku_dhizuku" + const val DHIZUKU_PROVIDER = "\u0000c\u0000o\u0000m\u0000.\u0000r\u0000o\u0000s\u0000a\u0000n\u0000.\u0000d\u0000h\u0000i\u0000z\u0000u\u0000k\u0000u\u0000.\u0000s\u0000e\u0000r\u0000v\u0000e\u0000r\u0000.\u0000p\u0000r\u0000o\u0000v\u0000i\u0000d\u0000e\u0000r" + const val SHIZUKU_PROVIDER = "\u0000r\u0000i\u0000k\u0000k\u0000a\u0000.\u0000s\u0000h\u0000i\u0000z\u0000u\u0000k\u0000u\u0000.\u0000S\u0000h\u0000i\u0000z\u0000u\u0000k\u0000u\u0000P\u0000r\u0000o\u0000v\u0000i\u0000d\u0000e\u0000r" + } + + override val exactPackageNames = setOf( + "com.rosan.dhizuku" + ) + + override fun canBeAddedIntoPreset(appInfo: ApplicationInfo): Boolean { + val packageName = appInfo.packageName + + // All Shizuku apps + if (packageName.startsWith("moe.shizuku.")) { + return true + } + + ZipFile(appInfo.sourceDir).use { zipFile -> + val manifestStr = AppPresets.instance.readManifest(packageName, zipFile) + + if (Utils.containsMultiple(manifestStr, SHIZUKU_PROVIDER, DHIZUKU_PROVIDER)) { + return true + } + } + + return false + } +} \ No newline at end of file diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/SuspiciousAppsPreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/SuspiciousAppsPreset.kt index 919ccfd..bbd3aa3 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/SuspiciousAppsPreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/SuspiciousAppsPreset.kt @@ -3,13 +3,16 @@ package icu.nullptr.hidemyapplist.common.app_presets import android.content.pm.ApplicationInfo import java.util.zip.ZipFile -class SuspiciousAppsPreset : BasePreset("sus_apps") { +class SuspiciousAppsPreset : BasePreset(NAME) { + companion object { + const val NAME = "sus_apps" + } + override val exactPackageNames = setOf( "com.reveny.vbmetafix.service", "berserker.android.apps.sshdroid", "com.iamaner.oneclickfreeze", "com.shamanland.privatescreenshots", - "com.aistra.hail", // Remote desktop apps "com.devolutions.remotedesktopmanager", @@ -57,11 +60,6 @@ class SuspiciousAppsPreset : BasePreset("sus_apps") { return true } - // All Shizuku apps - if (packageName.startsWith("moe.shizuku.")) { - return true - } - // All RealVNC apps (categorized as suspicious, because some of apps checking for them) if (packageName.startsWith("com.realvnc.")) { return true diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/XposedModulesPreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/XposedModulesPreset.kt index 7c7a078..5abfd87 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/XposedModulesPreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/XposedModulesPreset.kt @@ -3,7 +3,11 @@ package icu.nullptr.hidemyapplist.common.app_presets import android.content.pm.ApplicationInfo import java.util.zip.ZipFile -class XposedModulesPreset : BasePreset("xposed") { +class XposedModulesPreset : BasePreset(NAME) { + companion object { + const val NAME = "xposed" + } + override val exactPackageNames = setOf() override fun canBeAddedIntoPreset(appInfo: ApplicationInfo): Boolean { diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/AccessibilityPreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/AccessibilityPreset.kt index 10e3cbb..9a60286 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/AccessibilityPreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/AccessibilityPreset.kt @@ -1,6 +1,7 @@ package icu.nullptr.hidemyapplist.common.settings_presets import android.provider.Settings +import icu.nullptr.hidemyapplist.common.Constants class AccessibilityPreset : BasePreset(NAME) { companion object { @@ -11,10 +12,12 @@ class AccessibilityPreset : BasePreset(NAME) { ReplacementItem( name = Settings.Secure.ACCESSIBILITY_ENABLED, value = "0", + Constants.SETTINGS_SECURE, ), ReplacementItem( name = Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, value = "", + Constants.SETTINGS_SECURE, ), ) } diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/BasePreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/BasePreset.kt index bfbdee3..29c679c 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/BasePreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/BasePreset.kt @@ -1,14 +1,6 @@ package icu.nullptr.hidemyapplist.common.settings_presets abstract class BasePreset(val name: String) { - /* - companion object { - const val SETTINGS_GLOBAL = "global" - const val SETTINGS_SYSTEM = "system" - const val SETTINGS_SECURE = "secure" - } - */ - abstract val settingsKVPairs: List fun getSpoofedValue(key: String) = settingsKVPairs.firstOrNull { it.name == key } diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/DeveloperOptionsPreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/DeveloperOptionsPreset.kt index 53f4540..dc90e68 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/DeveloperOptionsPreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/DeveloperOptionsPreset.kt @@ -1,8 +1,10 @@ package icu.nullptr.hidemyapplist.common.settings_presets import android.provider.Settings +import icu.nullptr.hidemyapplist.common.Constants class DeveloperOptionsPreset : BasePreset("dev_options") { + @Suppress("DEPRECATION") override val settingsKVPairs = listOf( ReplacementItem( Settings.Global.ADB_ENABLED, @@ -16,6 +18,15 @@ class DeveloperOptionsPreset : BasePreset("dev_options") { Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, "0", ), + ReplacementItem( + "hidden_api_policy", + null, + ), + ReplacementItem( + Settings.Secure.ALLOW_MOCK_LOCATION, + "0", + Constants.SETTINGS_SECURE, + ), /* ReplacementItem( "debug.force_rtl", diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/InputMethodPreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/InputMethodPreset.kt new file mode 100644 index 0000000..2faae7d --- /dev/null +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/InputMethodPreset.kt @@ -0,0 +1,23 @@ +package icu.nullptr.hidemyapplist.common.settings_presets + +import android.provider.Settings +import icu.nullptr.hidemyapplist.common.Constants + +class InputMethodPreset : BasePreset(NAME) { + companion object { + const val NAME = "input_method" + } + + override val settingsKVPairs = listOf( + ReplacementItem( + Settings.Secure.DEFAULT_INPUT_METHOD, + "com.google.android.inputmethod.latin/com.android.inputmethod.latin.LatinIME", + Constants.SETTINGS_SECURE, + ), + ReplacementItem( + Settings.Secure.TTS_DEFAULT_SYNTH, + "com.google.android.tts", + Constants.SETTINGS_SECURE, + ), + ) +} \ No newline at end of file diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/ReplacementItem.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/ReplacementItem.kt index 784e7a7..9792ad1 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/ReplacementItem.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/settings_presets/ReplacementItem.kt @@ -1,13 +1,17 @@ package icu.nullptr.hidemyapplist.common.settings_presets +import icu.nullptr.hidemyapplist.common.Constants +import kotlinx.serialization.Serializable + +@Serializable data class ReplacementItem( val name: String, val value: String?, - // val database: String = BasePreset.SETTINGS_GLOBAL, + val database: String = Constants.SETTINGS_GLOBAL, ) { override fun toString() = "ReplacementItem { " + "'name': '$name', " + "'value': '$value', " + // "'database': '$database'" + " }" -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index 415b007..8e05b18 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,4 @@ android.experimental.enableNewResourceShrinker.preciseShrinking=true -android.enableAppCompileTimeRClass=true android.useAndroidX=true -android.disableMinifyLocalDependenciesForLibraries=false android.enableJetifier=true org.gradle.jvmargs=-Xmx2048m "-XX:MaxMetaspaceSize=1024m" diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt index dfff0ce..0a7b560 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt @@ -5,13 +5,16 @@ import android.content.pm.ApplicationInfo import android.content.pm.IPackageManager import android.os.Build import android.os.UserHandle +import android.provider.Settings import android.util.Log +import com.github.kyuubiran.ezxhelper.utils.isStatic import icu.nullptr.hidemyapplist.common.AppPresets import icu.nullptr.hidemyapplist.common.Constants import icu.nullptr.hidemyapplist.common.IHMAService import icu.nullptr.hidemyapplist.common.JsonConfig import icu.nullptr.hidemyapplist.common.RiskyPackageUtils.appHasGMSConnection import icu.nullptr.hidemyapplist.common.Utils +import icu.nullptr.hidemyapplist.common.app_presets.DetectorAppsPreset import icu.nullptr.hidemyapplist.xposed.hook.AccessibilityHook import icu.nullptr.hidemyapplist.xposed.hook.ActivityHook import icu.nullptr.hidemyapplist.xposed.hook.AppDataIsolationHook @@ -30,7 +33,7 @@ import java.io.File import java.util.concurrent.ExecutorService import java.util.concurrent.Executors -class HMAService(val pms: IPackageManager) : IHMAService.Stub() { +class HMAService(val pms: IPackageManager, val pmn: Any?) : IHMAService.Stub() { companion object { private const val TAG = "HMA-Service" @@ -70,8 +73,8 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() { instance = this loadConfig() installHooks() - AppPresets.instance.loggerFunction = { logD(TAG, it) } - AppPresets.instance.reloadPresetsIfEmpty(pms) + AppPresets.instance.loggerFunction = { level, msg -> logWithLevel(level, TAG, msg) } + AppPresets.instance.reloadPresets(pms) logI(TAG, "HMA service initialized") } @@ -170,7 +173,18 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() { logI(TAG, "Hooks installed") } - fun isHookEnabled(packageName: String) = config.scope.containsKey(packageName) + fun isHookEnabled(packageName: String?) = config.scope.containsKey(packageName) + + fun isAppDataIsolationExcluded(packageName: String?): Boolean { + if (packageName.isNullOrBlank()) return false + + return config.scope[packageName]?.excludeVoldIsolation ?: false + } + + fun getEnabledSettingsTemplates(caller: String?): Set { + if (caller == null) return setOf() + return config.scope[caller]?.applySettingTemplates ?: return setOf() + } fun getEnabledSettingsPresets(caller: String?): Set { if (caller == null) return setOf() @@ -201,8 +215,17 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() { if (!appConfig.useWhitelist) { for (presetName in appConfig.applyPresets) { val preset = AppPresets.instance.getPresetByName(presetName) ?: continue - if (preset.containsPackage(query)) - return !isAppInGMSIgnoredPackages(caller, query) + + if (preset.containsPackage(query)) { + // Do not hide detector apps from Play Store if they are connected to GMS + val overriddenCaller = if (presetName == DetectorAppsPreset.NAME && caller == Constants.VENDING_PACKAGE_NAME) { + Constants.GMS_PACKAGE_NAME + } else { + caller + } + + return !isAppInGMSIgnoredPackages(overriddenCaller, query) + } } } @@ -210,14 +233,12 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() { } fun shouldHideActivityLaunch(caller: String?, query: String?): Boolean { - if (shouldHide(caller, query)) { - val appConfig = config.scope[caller] - if (appConfig != null) { - return if (appConfig.invertActivityLaunchProtection) { - config.disableActivityLaunchProtection - } else { - !config.disableActivityLaunchProtection - } + val appConfig = config.scope[caller] + if (appConfig != null && shouldHide(caller, query)) { + return if (appConfig.invertActivityLaunchProtection) { + config.disableActivityLaunchProtection + } else { + !config.disableActivityLaunchProtection } } @@ -225,25 +246,31 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() { } fun shouldHideInstallationSource(caller: String?, query: String?, user: UserHandle): Int { - if (caller == null || query == null) return 0 - if (caller == BuildConfig.APP_PACKAGE_NAME) return 0 - val appConfig = config.scope[caller] ?: return 0 - if (!appConfig.hideInstallationSource) return 0 + if (caller == null || query == null) return Constants.FAKE_INSTALLATION_SOURCE_DISABLED + if (caller == BuildConfig.APP_PACKAGE_NAME) return Constants.FAKE_INSTALLATION_SOURCE_DISABLED + val appConfig = config.scope[caller] ?: return Constants.FAKE_INSTALLATION_SOURCE_DISABLED + if (!appConfig.hideInstallationSource) return Constants.FAKE_INSTALLATION_SOURCE_DISABLED logD(TAG, "@shouldHideInstallationSource $caller: $query") - if (caller == query && appConfig.excludeTargetInstallationSource) return 0 + if (caller == query && appConfig.excludeTargetInstallationSource) return Constants.FAKE_INSTALLATION_SOURCE_DISABLED try { val uid = Utils.getPackageUidCompat(pms, query, 0L, user.hashCode()) logD(TAG, "@shouldHideInstallationSource UID for $caller, ${user.hashCode()}: $query, $uid") - if (uid < 0) return 0 // invalid package installation source request + if (uid < 0) return Constants.FAKE_INSTALLATION_SOURCE_DISABLED // invalid package installation source request } catch (e: Throwable) { logD(TAG, "@shouldHideInstallationSource UID error for $caller, ${user.hashCode()}", e) - return 0 + return Constants.FAKE_INSTALLATION_SOURCE_DISABLED } return if (query in systemApps) { - if (appConfig.hideSystemInstallationSource) { 2 } else { 0 } - } else { 1 } + if (appConfig.hideSystemInstallationSource) { + Constants.FAKE_INSTALLATION_SOURCE_SYSTEM + } else { + Constants.FAKE_INSTALLATION_SOURCE_DISABLED + } + } else { + Constants.FAKE_INSTALLATION_SOURCE_USER + } } override fun stopService(cleanEnv: Boolean) { @@ -333,4 +360,30 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() { override fun log(level: Int, tag: String, message: String) { logWithLevel(level, tag, message) } + + override fun getPackageNames(userId: Int) = Utils.binderLocalScope { + Utils.getInstalledPackagesCompat(pms, 0L, userId).map { it.packageName }.toTypedArray() + } + + override fun getPackageInfo( + packageName: String, + userId: Int + ) = Utils.binderLocalScope { + Utils.getPackageInfoCompat(pms, packageName, 0L, userId) + } + + override fun listAllSettings(databaseName: String): Array { + val settingClass = when (databaseName) { + Constants.SETTINGS_GLOBAL -> Settings.Global::class.java + Constants.SETTINGS_SECURE -> Settings.Secure::class.java + Constants.SETTINGS_SYSTEM -> Settings.System::class.java + else -> throw IllegalArgumentException("Invalid database name $databaseName") + } + + val readableVariables = settingClass.declaredFields.mapNotNull { field -> + if (field.isStatic && field.type.simpleName == "String") field.get(null) as String else null + } + + return readableVariables.toTypedArray() + } } diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/UserService.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/UserService.kt index 64a993d..8c1294a 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/UserService.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/UserService.kt @@ -52,9 +52,9 @@ object UserService { } } - fun register(pms: IPackageManager) { + fun register(pms: IPackageManager, pmn: Any?) { logI(TAG, "Initialize HMAService - Version ${BuildConfig.APP_VERSION_NAME}") - val service = HMAService(pms) + val service = HMAService(pms, pmn) try { appUid = Utils.getPackageUidCompat(service.pms, BuildConfig.APP_PACKAGE_NAME, 0, 0) diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/XposedEntry.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/XposedEntry.kt index 0764690..2e90d20 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/XposedEntry.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/XposedEntry.kt @@ -14,6 +14,8 @@ private const val TAG = "HMA-XposedEntry" @Suppress("unused") class XposedEntry : IXposedHookZygoteInit, IXposedHookLoadPackage { + var targetsLeft = mutableListOf("package", "package_native") + var targetStorage = mutableMapOf() override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) { EzXHelperInit.initZygote(startupParam) @@ -28,13 +30,31 @@ class XposedEntry : IXposedHookZygoteInit, IXposedHookLoadPackage { serviceManagerHook = findMethod("android.os.ServiceManager") { name == "addService" }.hookBefore { param -> - if (param.args[0] == "package") { + val name = param.args[0] as String + if (targetsLeft.contains(name)) { + when (name) { + "package", "package_native" -> { + targetStorage[name] = param.args[1] + targetsLeft.remove(name) + } + else -> { + // skip if there is no package_native available + if (targetStorage.containsKey("package")) { + targetsLeft.remove("package_native") + } + } + } + } + + if (targetsLeft.isEmpty()) { serviceManagerHook?.unhook() - val pms = param.args[1] as IPackageManager - logD(TAG, "Got pms: $pms") + val pms = targetStorage["package"] as IPackageManager + val pmn = targetStorage["package_native"] + logD(TAG, "Got pms: $pms, $pmn") thread { runCatching { - UserService.register(pms) + UserService.register(pms, pmn) + targetStorage.clear() logI(TAG, "User service started") }.onFailure { logE(TAG, "System service crashed", it) diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/AccessibilityHook.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/AccessibilityHook.kt index a3e1360..e7b364f 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/AccessibilityHook.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/AccessibilityHook.kt @@ -1,12 +1,14 @@ package icu.nullptr.hidemyapplist.xposed.hook import android.accessibilityservice.AccessibilityServiceInfo +import android.content.pm.ParceledListSlice import com.github.kyuubiran.ezxhelper.utils.findMethod import com.github.kyuubiran.ezxhelper.utils.hookBefore import de.robv.android.xposed.XC_MethodHook import icu.nullptr.hidemyapplist.common.settings_presets.AccessibilityPreset import icu.nullptr.hidemyapplist.xposed.HMAService import icu.nullptr.hidemyapplist.xposed.Utils4Xposed +import icu.nullptr.hidemyapplist.xposed.logD import icu.nullptr.hidemyapplist.xposed.logE import icu.nullptr.hidemyapplist.xposed.logI @@ -24,11 +26,11 @@ class AccessibilityHook(private val service: HMAService) : IFrameworkHook { hookList += findMethod(ACCESSIBILITY_SERVICE) { name == "getInstalledAccessibilityServiceList" - }.hookBefore { param -> hookedMethod(param) } + }.hookBefore { param -> hookedMethod(param, true) } hookList += findMethod(ACCESSIBILITY_SERVICE) { name == "getEnabledAccessibilityServiceList" - }.hookBefore { param -> hookedMethod(param) } + }.hookBefore { param -> hookedMethod(param, false) } hookList += findMethod(ACCESSIBILITY_SERVICE) { name == "addClient" @@ -46,14 +48,23 @@ class AccessibilityHook(private val service: HMAService) : IFrameworkHook { } } - private fun hookedMethod(param: XC_MethodHook.MethodHookParam) { + private fun hookedMethod(param: XC_MethodHook.MethodHookParam, returnParcel: Boolean) { try { val callingApps = Utils4Xposed.getCallingApps(service) if (callingApps.isEmpty()) return for (caller in callingApps) { if (service.getEnabledSettingsPresets(caller).contains(AccessibilityPreset.NAME)) { - param.result = java.util.ArrayList() + val returnedList = java.util.ArrayList() + + logD(TAG, "@${param.method.name} returned empty list for $caller") + + param.result = if (returnParcel) { + ParceledListSlice(returnedList) + } else { + returnedList + } + service.filterCount++ break } diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/AppDataIsolationHook.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/AppDataIsolationHook.kt index dde9af6..2286493 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/AppDataIsolationHook.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/AppDataIsolationHook.kt @@ -13,7 +13,7 @@ import icu.nullptr.hidemyapplist.xposed.HMAService import icu.nullptr.hidemyapplist.xposed.logD import icu.nullptr.hidemyapplist.xposed.logE import icu.nullptr.hidemyapplist.xposed.logI - +import org.frknkrc44.hma_oss.common.BuildConfig @RequiresApi(Build.VERSION_CODES.R) class AppDataIsolationHook(private val service: HMAService): IFrameworkHook { @@ -36,7 +36,7 @@ class AppDataIsolationHook(private val service: HMAService): IFrameworkHook { "com.android.server.am.ProcessList" ) { name == "startProcess" - }?.hookAfter { param -> + }?.hookBefore { param -> if (service.config.altAppDataIsolation) { val isEnabled = XposedHelpers.getBooleanField( param.thisObject, @@ -55,8 +55,7 @@ class AppDataIsolationHook(private val service: HMAService): IFrameworkHook { } if (service.config.altVoldAppDataIsolation && !voldHookSkipped) { - val fuseEnabled = Build.VERSION.SDK_INT > Build.VERSION_CODES.R || - SystemProperties.getBoolean(FUSE_PROP, false) + val fuseEnabled = SystemProperties.getBoolean(FUSE_PROP, false) if (!fuseEnabled) { voldHookSkipped = true @@ -87,19 +86,53 @@ class AppDataIsolationHook(private val service: HMAService): IFrameworkHook { ) { name == "needsStorageDataIsolation" }?.hookAfter { param -> - if (service.config.altVoldAppDataIsolation && service.config.skipSystemAppDataIsolation) { + if (service.config.altVoldAppDataIsolation) { val app = param.args.find { it.javaClass.simpleName == "ProcessRecord" } val uid = XposedHelpers.getIntField(app, "uid") + val processName = runCatching { + XposedHelpers.getObjectField(app, "processName") + }.getOrDefault("") + val mountNode = runCatching { + XposedHelpers.getIntField(app, "mMountMode") + }.getOrDefault(0) + val isolated = runCatching { + XposedHelpers.getBooleanField(app, "isolated") + }.getOrDefault(false) + val appZygote = runCatching { + XposedHelpers.getBooleanField(app, "appZygote") + }.getOrDefault(false) + val apps = Utils.binderLocalScope { service.pms.getPackagesForUid(uid) } ?: return@hookAfter - val isSystemApp = service.systemApps.any { apps.contains(it) } logD( TAG, - "@needsStorageDataIsolation $uid - ${apps.contentToString()} isSystemApp: $isSystemApp" + "@needsStorageDataIsolation $uid and ${apps.contentToString()} - $processName value without override: ${param.result}, mount node: $mountNode, isolated: $isolated, appZygote: $appZygote" ) - if (isSystemApp) param.result = false + + // Do not isolate this module for safety + if (apps.contains(BuildConfig.APP_PACKAGE_NAME)) { + param.result = false + return@hookAfter + } + + if (apps.any { service.isAppDataIsolationExcluded(it) }) { + param.result = false + } + + if (service.config.skipSystemAppDataIsolation) { + val isSystemApp = service.systemApps.any { apps.contains(it) } + logD( + TAG, + "@needsStorageDataIsolation $uid and ${apps.contentToString()} - isSystemApp: $isSystemApp" + ) + + if (isSystemApp) { + param.result = false + return@hookAfter + } + } } }?.let { hooks += it @@ -112,8 +145,7 @@ class AppDataIsolationHook(private val service: HMAService): IFrameworkHook { }?.hookBefore { param -> runCatching { if (service.config.altVoldAppDataIsolation) { - val fuseEnabled = Build.VERSION.SDK_INT > Build.VERSION_CODES.R || - SystemProperties.getBoolean(FUSE_PROP, false) + val fuseEnabled = SystemProperties.getBoolean(FUSE_PROP, false) if (!fuseEnabled) { logE(TAG, "StorageManagerService - FUSE storage is not enabled, disable hooks") @@ -165,7 +197,7 @@ class AppDataIsolationHook(private val service: HMAService): IFrameworkHook { } ?: continue for (app in apps) { - if (app in service.systemApps) { + if (app in service.systemApps || app == BuildConfig.APP_PACKAGE_NAME) { logD( TAG, "@remountAppStorageDirs SYSTEM $pid - $packageName is marked to remove" diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/ContentProviderHook.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/ContentProviderHook.kt index 883c803..3095345 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/ContentProviderHook.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/ContentProviderHook.kt @@ -10,6 +10,7 @@ import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem import icu.nullptr.hidemyapplist.xposed.HMAService import icu.nullptr.hidemyapplist.xposed.Utils4Xposed import icu.nullptr.hidemyapplist.xposed.logD +import icu.nullptr.hidemyapplist.xposed.logI class ContentProviderHook(private val service: HMAService): IFrameworkHook { companion object { @@ -21,7 +22,7 @@ class ContentProviderHook(private val service: HMAService): IFrameworkHook { // Credit: https://github.com/Nitsuya/DoNotTryAccessibility/blob/main/app/src/main/java/io/github/nitsuya/donottryaccessibility/hook/AndroidFrameworkHooker.kt override fun load() { hook = findMethod( - "android.content.ContentProvider\$Transport" + $$"android.content.ContentProvider$Transport" ) { name == "call" }.hookBefore { param -> @@ -32,13 +33,16 @@ class ContentProviderHook(private val service: HMAService): IFrameworkHook { val name = param.args[3] as String? for (caller in callingApps) { - // logD(TAG, "@call caller: $caller, method: $method, name: $name") + if (!service.isHookEnabled(caller)) continue + + logD(TAG, "@spoofSettings received caller: $caller, method: $method, name: $name") when (method) { "GET_global", "GET_secure", "GET_system" -> { - val replacement = getSpoofedSetting(caller, name) + val database = method.substring(method.indexOf('_') + 1) + val replacement = getSpoofedSetting(caller, name, database) if (replacement != null) { - logD(TAG, "@getSettings returned replacement for $caller: ${replacement.value}") + logI(TAG, "@spoofSettings $name in $database replaced for $caller") param.result = Bundle().apply { putString(Settings.NameValueTable.VALUE, replacement.value) putInt("_generation_index", -1) @@ -51,18 +55,22 @@ class ContentProviderHook(private val service: HMAService): IFrameworkHook { } } - fun getSpoofedSetting(caller: String?, name: String?): ReplacementItem? { + fun getSpoofedSetting(caller: String?, name: String?, database: String): ReplacementItem? { if (caller == null || name == null) return null - val presets = service.getEnabledSettingsPresets(caller) - if (presets.isEmpty()) { - return null + val templates = service.getEnabledSettingsTemplates(caller) + val replacement = service.config.settingsTemplates.firstNotNullOfOrNull { (key, value) -> + if (key in templates) value.settingsList.firstOrNull { it.name == name } else null } + if (replacement != null) return replacement - for (presetName in presets) { - val preset = SettingsPresets.instance.getPresetByName(presetName) - val value = preset?.getSpoofedValue(name) - if (value != null) return value + val presets = service.getEnabledSettingsPresets(caller) + if (presets.isNotEmpty()) { + for (presetName in presets) { + val preset = SettingsPresets.instance.getPresetByName(presetName) + val replacement = preset?.getSpoofedValue(name) + if (replacement?.database == database) return replacement + } } return null diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget28.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget28.kt index 12ab1bb..cc50017 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget28.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget28.kt @@ -19,8 +19,11 @@ class PmsHookTarget28(service: HMAService) : PmsHookTargetBase(service) { } // not required until SDK 30 - override val fakeSystemPackageInstallInfo = null - override val fakeUserPackageInstallInfo = null + /* + override val fakeUserPackageInstallSource = null + */ + override val fakeSystemPackageInstallSourceInfo = null + override val fakeUserPackageInstallSourceInfo = null @Suppress("UNCHECKED_CAST") override fun load() { diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget30.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget30.kt index caccaa7..ca94788 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget30.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget30.kt @@ -24,7 +24,24 @@ class PmsHookTarget30(service: HMAService) : PmsHookTargetBase(service) { private const val TAG = "PmsHookTarget30" } - override val fakeSystemPackageInstallInfo: Any by lazy { + /* + override val fakeUserPackageInstallSource: Any by lazy { + findConstructor( + "com.android.server.pm.InstallSource" + ) { + true + }.newInstance( + VENDING_PACKAGE_NAME, + VENDING_PACKAGE_NAME, + VENDING_PACKAGE_NAME, + false, + false, + psSigningDetails, + ) + } + */ + + override val fakeSystemPackageInstallSourceInfo: Any by lazy { findConstructor( "android.content.pm.InstallSourceInfo" ) { @@ -37,7 +54,7 @@ class PmsHookTarget30(service: HMAService) : PmsHookTargetBase(service) { ) } - override val fakeUserPackageInstallInfo: Any by lazy { + override val fakeUserPackageInstallSourceInfo: Any by lazy { findConstructor( "android.content.pm.InstallSourceInfo" ) { diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget31.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget31.kt index 6442771..747ae02 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget31.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget31.kt @@ -24,7 +24,11 @@ class PmsHookTarget31(service: HMAService) : PmsHookTargetBase(service) { private const val TAG = "PmsHookTarget31" } - override val fakeSystemPackageInstallInfo: Any by lazy { + /* + override val fakeUserPackageInstallSource = null + */ + + override val fakeSystemPackageInstallSourceInfo: Any by lazy { findConstructor( "android.content.pm.InstallSourceInfo" ) { @@ -37,7 +41,7 @@ class PmsHookTarget31(service: HMAService) : PmsHookTargetBase(service) { ) } - override val fakeUserPackageInstallInfo: Any by lazy { + override val fakeUserPackageInstallSourceInfo: Any by lazy { findConstructor( "android.content.pm.InstallSourceInfo" ) { diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget33.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget33.kt index 71fe3f9..d0846ea 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget33.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget33.kt @@ -29,7 +29,11 @@ class PmsHookTarget33(service: HMAService) : PmsHookTargetBase(service) { } } - override val fakeSystemPackageInstallInfo: Any by lazy { + /* + override val fakeUserPackageInstallSource = null + */ + + override val fakeSystemPackageInstallSourceInfo: Any by lazy { findConstructor( "android.content.pm.InstallSourceInfo" ) { @@ -43,7 +47,7 @@ class PmsHookTarget33(service: HMAService) : PmsHookTargetBase(service) { ) } - override val fakeUserPackageInstallInfo: Any by lazy { + override val fakeUserPackageInstallSourceInfo: Any by lazy { findConstructor( "android.content.pm.InstallSourceInfo" ) { diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt index 5b8de07..f89f40a 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt @@ -31,7 +31,11 @@ class PmsHookTarget34(service: HMAService) : PmsHookTargetBase(service) { } } - override val fakeSystemPackageInstallInfo: Any by lazy { + /* + override val fakeUserPackageInstallSource = null + */ + + override val fakeSystemPackageInstallSourceInfo: Any by lazy { findConstructor( "android.content.pm.InstallSourceInfo" ) { @@ -46,7 +50,7 @@ class PmsHookTarget34(service: HMAService) : PmsHookTargetBase(service) { ) } - override val fakeUserPackageInstallInfo: Any by lazy { + override val fakeUserPackageInstallSourceInfo: Any by lazy { findConstructor( "android.content.pm.InstallSourceInfo" ) { diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTargetBase.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTargetBase.kt index 29373a6..10cd7fd 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTargetBase.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTargetBase.kt @@ -25,16 +25,40 @@ abstract class PmsHookTargetBase(protected val service: HMAService) : IFramework protected var lastFilteredApp: AtomicReference = AtomicReference(null) protected val psSigningInfo by lazy { - Utils.getPackageInfoCompat( - service.pms, - VENDING_PACKAGE_NAME, - PackageManager.GET_SIGNING_CERTIFICATES.toLong(), - 0 - ).signingInfo + try { + Utils.getPackageInfoCompat( + service.pms, + VENDING_PACKAGE_NAME, + PackageManager.GET_SIGNING_CERTIFICATES.toLong(), + 0 + ).signingInfo + } catch (_: Throwable) { + null + } } - abstract val fakeSystemPackageInstallInfo: Any? - abstract val fakeUserPackageInstallInfo: Any? + /* + protected val psSigningDetails by lazy { + // TODO: Implement vending signing details + null + } + + // TODO: Spoof PM install source + internal val fakeSystemPackageInstallSource: Any? by lazy { + try { + findField("com.android.server.pm.InstallSource") { + name == "EMPTY_ORPHANED" + }.get(null)!! + } catch (_: Throwable) { + null + } + } + + abstract val fakeUserPackageInstallSource: Any? + */ + + abstract val fakeSystemPackageInstallSourceInfo: Any? + abstract val fakeUserPackageInstallSourceInfo: Any? override fun load() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { @@ -74,7 +98,55 @@ abstract class PmsHookTargetBase(protected val service: HMAService) : IFramework } } + if (service.pmn != null) { + findMethodOrNull(service.pmn::class.java, findSuper = true) { + name == "getInstallerForPackage" + }?.hookBefore { param -> + val query = param.args[0] as String? + val callingHandle = Binder.getCallingUserHandle() + + val callingApps = Utils.binderLocalScope { + service.pms.getPackagesForUid(callingHandle.hashCode()) + } ?: return@hookBefore + + for (caller in callingApps) { + when (service.shouldHideInstallationSource(caller, query, callingHandle)) { + Constants.FAKE_INSTALLATION_SOURCE_USER -> param.result = VENDING_PACKAGE_NAME + Constants.FAKE_INSTALLATION_SOURCE_SYSTEM -> param.result = "preload" + else -> continue + } + } + }?.let { + logD(TAG, "PMN getInstallerForPackage is hooked!") + hooks.add(it) + } + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + /* + findMethodOrNull(service.pms::class.java, findSuper = true) { + name == "getInstallSource" + }?.hookBefore { param -> + val query = param.args[0] as String? + val callingUid = param.args[1] as Int + val user = UserHandle.getUserHandleForUid(param.args[2] as Int) + + val callingApps = Utils.binderLocalScope { + service.pms.getPackagesForUid(callingUid) + } ?: return@hookBefore + + for (caller in callingApps) { + when (service.shouldHideInstallationSource(caller, query, user)) { + Constants.FAKE_INSTALLATION_SOURCE_USER -> param.result = fakeUserPackageInstallSource + Constants.FAKE_INSTALLATION_SOURCE_SYSTEM -> param.result = fakeSystemPackageInstallSource + else -> continue + } + } + }?.let { + hooks.add(it) + } + */ + findMethodOrNull(service.pms::class.java, findSuper = true) { name == "getInstallSourceInfo" }?.hookBefore { param -> @@ -83,13 +155,15 @@ abstract class PmsHookTargetBase(protected val service: HMAService) : IFramework val user = Binder.getCallingUserHandle() val callingUid = Binder.getCallingUid() if (callingUid == Constants.UID_SYSTEM) return@hookBefore + val callingApps = Utils.binderLocalScope { service.pms.getPackagesForUid(callingUid) } ?: return@hookBefore + for (caller in callingApps) { when (service.shouldHideInstallationSource(caller, query, user)) { - 1 -> param.result = fakeUserPackageInstallInfo - 2 -> param.result = fakeSystemPackageInstallInfo + Constants.FAKE_INSTALLATION_SOURCE_USER -> param.result = fakeUserPackageInstallSourceInfo + Constants.FAKE_INSTALLATION_SOURCE_SYSTEM -> param.result = fakeSystemPackageInstallSourceInfo else -> continue } @@ -114,8 +188,8 @@ abstract class PmsHookTargetBase(protected val service: HMAService) : IFramework } ?: return@hookBefore for (caller in callingApps) { when (service.shouldHideInstallationSource(caller, query, user)) { - 1 -> param.result = VENDING_PACKAGE_NAME - 2 -> param.result = null + Constants.FAKE_INSTALLATION_SOURCE_USER -> param.result = VENDING_PACKAGE_NAME + Constants.FAKE_INSTALLATION_SOURCE_SYSTEM -> param.result = null else -> continue }