Full Code of mirfatif/PermissionManagerX for AI

master 164ffaec204b cached
512 files
5.3 MB
1.4M tokens
1844 symbols
1 requests
Download .txt
Showing preview only (6,082K chars total). Download the full file or copy to clipboard to get everything.
Repository: mirfatif/PermissionManagerX
Branch: master
Commit: 164ffaec204b
Files: 512
Total size: 5.3 MB

Directory structure:
gitextract_19owviso/

├── .gitignore
├── .gitmodules
├── 404.html
├── LICENSE
├── PRIVACY.html
├── README.md
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── mirfatif/
│       │   │           ├── err/
│       │   │           │   └── AdbException.java
│       │   │           └── permissionmanagerx/
│       │   │               ├── about/
│       │   │               │   ├── AboutActivity.java
│       │   │               │   ├── CrashReportActivity.kt
│       │   │               │   ├── PrivilegesAdapter.java
│       │   │               │   ├── PrivilegesDialog.java
│       │   │               │   └── TransCreditsDialogFrag.java
│       │   │               ├── app/
│       │   │               │   └── App.java
│       │   │               ├── backup/
│       │   │               │   ├── BackupFileSelector.java
│       │   │               │   └── BackupRestore.java
│       │   │               ├── base/
│       │   │               │   ├── AlertDialogFragment.java
│       │   │               │   ├── BaseActivity.java
│       │   │               │   ├── BottomSheetDialogFrag.java
│       │   │               │   ├── DialogBg.java
│       │   │               │   └── MyListAdapter.java
│       │   │               ├── fwk/
│       │   │               │   ├── AboutActivityM.java
│       │   │               │   ├── AdbConnectSvcM.java
│       │   │               │   ├── AdvSettingsActivityM.java
│       │   │               │   ├── AppM.java
│       │   │               │   ├── CrashReportActivityM.java
│       │   │               │   ├── CustomButton.java
│       │   │               │   ├── DaemonRcvSvcM.java
│       │   │               │   ├── DialogHelpIcon.java
│       │   │               │   ├── FilterSettingsActivityM.java
│       │   │               │   ├── HelpActivityM.java
│       │   │               │   ├── LifecycleWatcher.java
│       │   │               │   ├── LogcatSvcM.java
│       │   │               │   ├── MainActivityM.java
│       │   │               │   ├── MoveUpBehavior.java
│       │   │               │   ├── MyCoordinatorLayout.java
│       │   │               │   ├── MyDrawerLayout.java
│       │   │               │   ├── MyLinearLayout.java
│       │   │               │   ├── MyNavigationView.java
│       │   │               │   ├── MySearchView.java
│       │   │               │   ├── MyWebView.java
│       │   │               │   ├── NumPickerPref.java
│       │   │               │   ├── PackageActivityM.java
│       │   │               │   ├── ProgressLinearLayout.java
│       │   │               │   └── SettingsActivityM.java
│       │   │               ├── help/
│       │   │               │   ├── HelpActivity.java
│       │   │               │   └── HelpJsInterface.java
│       │   │               ├── main/
│       │   │               │   ├── AdbConnectDialog.java
│       │   │               │   ├── BackupRestoreDialog.java
│       │   │               │   ├── DaemonStartProg.java
│       │   │               │   ├── Feedback.java
│       │   │               │   ├── FeedbackDialogFrag.java
│       │   │               │   ├── MainActivity.java
│       │   │               │   ├── PackageAdapter.java
│       │   │               │   ├── PkgLongPressDialogFrag.java
│       │   │               │   └── PrivsCheckBoxFocus.java
│       │   │               ├── parser/
│       │   │               │   ├── AppOpsParser.java
│       │   │               │   ├── Package.java
│       │   │               │   ├── PackageParser.java
│       │   │               │   ├── PermGroupsMapping.java
│       │   │               │   ├── Permission.java
│       │   │               │   ├── SearchConstants.java
│       │   │               │   └── permsdb/
│       │   │               │       ├── PermissionDao.java
│       │   │               │       ├── PermissionDatabase.java
│       │   │               │       ├── PermissionEntity.java
│       │   │               │       └── PermsDb.java
│       │   │               ├── pkg/
│       │   │               │   ├── PackageActivity.java
│       │   │               │   ├── PermDetailDialog.java
│       │   │               │   ├── PermLongPressDialogFrag.java
│       │   │               │   └── PermissionAdapter.java
│       │   │               ├── prefs/
│       │   │               │   ├── AppUpdate.java
│       │   │               │   ├── ExcFiltersData.java
│       │   │               │   ├── MySettings.java
│       │   │               │   ├── fwk/
│       │   │               │   │   ├── CustomPrefDialogFrag.java
│       │   │               │   │   ├── EditTextPrefDialogFrag.java
│       │   │               │   │   ├── ListPrefDialogFrag.java
│       │   │               │   │   └── MultiSelectListPrefDialogFrag.java
│       │   │               │   └── settings/
│       │   │               │       ├── AdvSettingsActivity.java
│       │   │               │       ├── AdvSettingsFrag.java
│       │   │               │       ├── FilterSettingsActivity.java
│       │   │               │       ├── FilterSettingsFragment.java
│       │   │               │       ├── SearchSettingsFrag.java
│       │   │               │       ├── SettingsActivity.java
│       │   │               │       ├── SettingsFrag.java
│       │   │               │       ├── SettingsFragGeneral.java
│       │   │               │       └── SettingsFragTheme.java
│       │   │               ├── privs/
│       │   │               │   ├── AdbConnManager.java
│       │   │               │   ├── DaemonHandler.java
│       │   │               │   ├── DaemonIface.java
│       │   │               │   ├── DaemonStarter.java
│       │   │               │   └── NativeDaemon.java
│       │   │               ├── profile/
│       │   │               │   └── PermProfileBackupRestore.java
│       │   │               ├── svc/
│       │   │               │   ├── AdbConnectSvc.java
│       │   │               │   ├── DaemonRcvSvc.java
│       │   │               │   └── LogcatSvc.java
│       │   │               └── util/
│       │   │                   ├── ApiUtils.java
│       │   │                   ├── AppLifecycle.java
│       │   │                   ├── LocaleUtils.java
│       │   │                   ├── LogUtils.java
│       │   │                   ├── NotifUtils.java
│       │   │                   ├── SmallDimMarginSpan.java
│       │   │                   ├── StdErrLogServer.java
│       │   │                   ├── StringUtils.java
│       │   │                   ├── UiUtils.java
│       │   │                   ├── UserUtils.java
│       │   │                   ├── Utils.java
│       │   │                   └── bg/
│       │   │                       ├── LiveBgTask.java
│       │   │                       ├── LiveEvent.java
│       │   │                       ├── LiveMinDelayParamTask.java
│       │   │                       ├── LiveSchedParamTask.java
│       │   │                       ├── LiveSchedTask.java
│       │   │                       ├── LiveSingleParamTask.java
│       │   │                       ├── LiveTasksQueue.java
│       │   │                       ├── LiveTasksQueueTyped.java
│       │   │                       ├── LiveUiParamTask.java
│       │   │                       ├── LiveUiTask.java
│       │   │                       ├── LiveUiWaitTask.java
│       │   │                       └── UiRunner.java
│       │   └── res/
│       │       ├── anim/
│       │       │   └── shake.xml
│       │       ├── color/
│       │       │   ├── active_disabled.xml
│       │       │   └── slim_switch.xml
│       │       ├── drawable/
│       │       │   ├── accessibility.xml
│       │       │   ├── advanced_settings.xml
│       │       │   ├── arrow_right.xml
│       │       │   ├── backup_restore.xml
│       │       │   ├── check_circle.xml
│       │       │   ├── circle_progress_bar.xml
│       │       │   ├── color.xml
│       │       │   ├── crash_report_text_bg.xml
│       │       │   ├── cross_red.xml
│       │       │   ├── danger.xml
│       │       │   ├── dark_mode.xml
│       │       │   ├── database.xml
│       │       │   ├── donate.xml
│       │       │   ├── email.xml
│       │       │   ├── exit.xml
│       │       │   ├── filter.xml
│       │       │   ├── g_accounts.xml
│       │       │   ├── g_audio.xml
│       │       │   ├── g_background.xml
│       │       │   ├── g_biometrics.xml
│       │       │   ├── g_bluetooth.xml
│       │       │   ├── g_calendar.xml
│       │       │   ├── g_calllog.xml
│       │       │   ├── g_camera.xml
│       │       │   ├── g_clipboard.xml
│       │       │   ├── g_contacts.xml
│       │       │   ├── g_data.xml
│       │       │   ├── g_display.xml
│       │       │   ├── g_hardware.xml
│       │       │   ├── g_home.xml
│       │       │   ├── g_location.xml
│       │       │   ├── g_log.xml
│       │       │   ├── g_mic.xml
│       │       │   ├── g_network.xml
│       │       │   ├── g_notif.xml
│       │       │   ├── g_others.xml
│       │       │   ├── g_package.xml
│       │       │   ├── g_phone.xml
│       │       │   ├── g_power.xml
│       │       │   ├── g_sensors.xml
│       │       │   ├── g_settings.xml
│       │       │   ├── g_sms.xml
│       │       │   ├── g_storage.xml
│       │       │   ├── g_vibration.xml
│       │       │   ├── g_wifi.xml
│       │       │   ├── github_mark.xml
│       │       │   ├── help.xml
│       │       │   ├── hinge.xml
│       │       │   ├── info.xml
│       │       │   ├── issues.xml
│       │       │   ├── key.xml
│       │       │   ├── label.xml
│       │       │   ├── link.xml
│       │       │   ├── locale.xml
│       │       │   ├── log.xml
│       │       │   ├── main_act_big_prog_bg.xml
│       │       │   ├── notification_icon.xml
│       │       │   ├── paid.xml
│       │       │   ├── perm_watcher.xml
│       │       │   ├── permission.xml
│       │       │   ├── privacy_policy.xml
│       │       │   ├── report.xml
│       │       │   ├── root.xml
│       │       │   ├── schedule.xml
│       │       │   ├── search_settings.xml
│       │       │   ├── search_settings_bg.xml
│       │       │   ├── settings.xml
│       │       │   ├── share.xml
│       │       │   ├── shell.xml
│       │       │   ├── slim_switch_thumb.xml
│       │       │   ├── slim_switch_track.xml
│       │       │   ├── star.xml
│       │       │   ├── telegram.xml
│       │       │   ├── theme.xml
│       │       │   ├── tick.xml
│       │       │   ├── triangle.xml
│       │       │   ├── update.xml
│       │       │   ├── zoom_in.xml
│       │       │   └── zoom_out.xml
│       │       ├── layout/
│       │       │   ├── about_privileges_dialog.xml
│       │       │   ├── about_privileges_item.xml
│       │       │   ├── activity_about.xml
│       │       │   ├── activity_crash_report.xml
│       │       │   ├── activity_fragment_container.xml
│       │       │   ├── activity_help.xml
│       │       │   ├── activity_main.xml
│       │       │   ├── activity_main_moving_container.xml
│       │       │   ├── activity_package.xml
│       │       │   ├── adb_connect_dialog.xml
│       │       │   ├── backup_restore_dialog.xml
│       │       │   ├── dilog_title_with_help.xml
│       │       │   ├── feedback_dialog.xml
│       │       │   ├── perm_details_dialog.xml
│       │       │   ├── perm_long_press_dialog.xml
│       │       │   ├── pkg_long_press_dialog.xml
│       │       │   ├── progress_dialog.xml
│       │       │   ├── rate_donate_dialog.xml
│       │       │   ├── rv_item_perm.xml
│       │       │   ├── rv_item_pkg.xml
│       │       │   ├── status_bar_bg_cont.xml
│       │       │   ├── trans_credits_row.xml
│       │       │   └── translation_dialog.xml
│       │       ├── menu/
│       │       │   ├── about_menu.xml
│       │       │   ├── filter_settings.xml
│       │       │   ├── help_menu.xml
│       │       │   ├── main_drawer.xml
│       │       │   ├── main_search.xml
│       │       │   └── package_menu.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       ├── values/
│       │       │   ├── arrays.xml
│       │       │   ├── attrs.xml
│       │       │   ├── colors.xml
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   ├── strings_foss.xml
│       │       │   ├── styles.xml
│       │       │   └── theme.xml
│       │       ├── values-ar/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-de/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-el/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-es/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-night/
│       │       │   └── colors.xml
│       │       ├── values-ro/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-ru/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-tr/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-v29/
│       │       │   └── styles.xml
│       │       ├── values-zh-rCN/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       └── xml/
│       │           ├── adv_settings_prefs.xml
│       │           ├── filter_settings_preferences.xml
│       │           ├── settings_prefs.xml
│       │           ├── settings_prefs_general.xml
│       │           ├── settings_prefs_search.xml
│       │           └── settings_prefs_theming.xml
│       └── release/
│           └── AndroidManifest.xml
├── build.gradle.kts
├── buildSrc/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src/
│       └── main/
│           └── kotlin/
│               ├── android-base-conventions.gradle.kts
│               ├── android-lib-conventions.gradle.kts
│               ├── apk-conventions.gradle.kts
│               ├── dependency-updates-conventions.gradle.kts
│               ├── java-android-lib-conventions.gradle.kts
│               ├── java-base-conventions.gradle.kts
│               ├── java-kotlin-conventions.gradle.kts
│               ├── java-lib-conventions.gradle.kts
│               └── spotless-conventions.gradle.kts
├── fastlane/
│   └── metadata/
│       └── android/
│           ├── ar/
│           │   ├── short_description.txt
│           │   └── title.txt
│           ├── de/
│           │   └── short_description.txt
│           ├── el/
│           │   └── title.txt
│           ├── en-US/
│           │   ├── changelogs/
│           │   │   ├── 101.txt
│           │   │   ├── 103.txt
│           │   │   ├── 104.txt
│           │   │   ├── 105.txt
│           │   │   ├── 106.txt
│           │   │   ├── 107.txt
│           │   │   ├── 108.txt
│           │   │   ├── 109.txt
│           │   │   ├── 110.txt
│           │   │   ├── 111.txt
│           │   │   ├── 112.txt
│           │   │   ├── 113.txt
│           │   │   ├── 114.txt
│           │   │   ├── 116.txt
│           │   │   ├── 117.txt
│           │   │   ├── 118.txt
│           │   │   ├── 119.txt
│           │   │   ├── 120.txt
│           │   │   ├── 121.txt
│           │   │   ├── 122.txt
│           │   │   ├── 123.txt
│           │   │   ├── 124.txt
│           │   │   ├── 125.txt
│           │   │   ├── 126.txt
│           │   │   ├── 127.txt
│           │   │   ├── 128.txt
│           │   │   └── 129.txt
│           │   ├── full_description.txt
│           │   ├── short_description.txt
│           │   └── title.txt
│           ├── es/
│           │   ├── short_description.txt
│           │   └── title.txt
│           ├── ru/
│           │   ├── full_description.txt
│           │   ├── short_description.txt
│           │   └── title.txt
│           ├── tr/
│           │   └── title.txt
│           ├── ur/
│           │   └── title.txt
│           └── zh/
│               ├── full_description.txt
│               ├── short_description.txt
│               └── title.txt
├── gradle/
│   ├── libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── help/
│   ├── 404.html
│   ├── ar/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── assets/
│   │   └── javascripts/
│   │       └── lunr/
│   │           ├── tinyseg.js
│   │           └── wordcut.js
│   ├── batch-operations/
│   │   └── index.html
│   ├── css/
│   │   └── extra.css
│   ├── de/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── details/
│   │   └── index.html
│   ├── es/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── faqs/
│   │   └── index.html
│   ├── fr/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── index.html
│   ├── javascript/
│   │   └── extra.js
│   ├── permission-references/
│   │   └── index.html
│   ├── permission-view/
│   │   └── index.html
│   ├── permission-watcher/
│   │   └── index.html
│   ├── pt-BR/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── ru/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── scheduled-check/
│   │   └── index.html
│   ├── search/
│   │   ├── index.html
│   │   └── search_index.json
│   ├── sitemap.xml
│   ├── use-with-adb/
│   │   └── index.html
│   ├── versions/
│   │   └── index.html
│   ├── whatsrunning-integration/
│   │   └── index.html
│   └── zh/
│       ├── batch-operations/
│       │   └── index.html
│       ├── details/
│       │   └── index.html
│       ├── faqs/
│       │   └── index.html
│       ├── index.html
│       ├── permission-references/
│       │   └── index.html
│       ├── permission-view/
│       │   └── index.html
│       ├── permission-watcher/
│       │   └── index.html
│       ├── scheduled-check/
│       │   └── index.html
│       ├── search/
│       │   └── index.html
│       ├── use-with-adb/
│       │   └── index.html
│       ├── versions/
│       │   └── index.html
│       └── whatsrunning-integration/
│           └── index.html
├── hidden_apis/
│   ├── .gitignore
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           └── java/
│               ├── android/
│               │   ├── app/
│               │   │   ├── ActivityManagerNative.java
│               │   │   ├── AppOpsManager.java
│               │   │   └── IActivityManager.java
│               │   ├── content/
│               │   │   ├── Context.java
│               │   │   └── pm/
│               │   │       ├── IPackageManager.java
│               │   │       └── ParceledListSlice.java
│               │   ├── os/
│               │   │   ├── IDeviceIdleController.java
│               │   │   ├── Process.java
│               │   │   └── ServiceManager.java
│               │   └── permission/
│               │       └── IPermissionManager.java
│               └── com/
│                   └── android/
│                       └── internal/
│                           └── app/
│                               └── IAppOpsService.java
├── native/
│   ├── build_native.sh
│   ├── pmxd.c
│   └── pmxe.c
├── priv_daemon/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── daemon-proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── mirfatif/
│                       └── privdaemon/
│                           ├── Callbacks.java
│                           ├── DaemonLog.java
│                           ├── IPrivTasksImpl.java
│                           ├── Jni.java
│                           ├── Main.java
│                           ├── PrivDaemon.java
│                           ├── PrivsStatusReader.java
│                           └── Server.java
├── priv_library/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── aidl/
│           │   └── com/
│           │       └── mirfatif/
│           │           └── privtasks/
│           │               └── bind/
│           │                   ├── ILogCallback.aidl
│           │                   └── IPrivTasksCallback.aidl
│           └── java/
│               └── com/
│                   └── mirfatif/
│                       ├── err/
│                       │   ├── ContainerException.java
│                       │   └── HiddenAPIsException.java
│                       └── privtasks/
│                           ├── AppPrivTasks.java
│                           ├── Constants.java
│                           ├── HiddenSdkIntConstants.java
│                           ├── HiddenSdkStringConstants.java
│                           ├── PrivTasksError.java
│                           ├── bind/
│                           │   ├── AppOpsLists.java
│                           │   ├── DaemonState.java
│                           │   ├── MyPackageInfo.java
│                           │   ├── MyPackageOps.java
│                           │   ├── PermFixedFlags.java
│                           │   ├── PrivsStatus.java
│                           │   └── StrIntMap.java
│                           ├── hiddenapis/
│                           │   ├── HiddenAPIs.java
│                           │   ├── MidReleaseBrokenAPIsDelegate.kt
│                           │   └── SysSvcFactory.java
│                           ├── iface/
│                           │   └── IPrivTasks.java
│                           └── util/
│                               ├── CloseableReadWriteLock.java
│                               ├── LogUtil.java
│                               ├── MyLog.java
│                               ├── NonBlockingReader.java
│                               ├── Util.java
│                               └── bg/
│                                   ├── BgRunner.java
│                                   ├── MinDelayTaskExecutor.java
│                                   ├── NotifyWaiter.java
│                                   ├── RateLimitedTask.java
│                                   ├── RateLimitedTaskTyped.java
│                                   ├── RateLimiter.java
│                                   ├── RunnableWithParam.java
│                                   ├── RunnableWithResult.java
│                                   ├── SingleParamTask.java
│                                   ├── SingleSchedTaskExecutor.java
│                                   ├── SingleTaskExecutor.java
│                                   ├── SingleTaskExecutorAbstract.java
│                                   ├── SingleTaskExecutorTyped.java
│                                   └── ThreadUtils.java
├── privacy_policy.html
└── settings.gradle.kts

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
**/.gradle/
**/.idea/

**/build/

**/.kotlin/

/local.properties

/out/


================================================
FILE: .gitmodules
================================================
[submodule "native/libcap"]
	path = native/libcap
	url = https://android.googlesource.com/platform/external/libcap


================================================
FILE: 404.html
================================================
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>Redirecting…</title>

  <!-- Fallback meta refresh (for browsers without JS): go to help root -->
  <meta http-equiv="refresh" content="5;url=https://mirfatif.github.io/PermissionManagerX/help/" />

  <style>
    body {
      display: flex;
      min-height: 100vh;
      margin: 0;
      align-items: center;
      justify-content: center;
      color: #111827;
    }

    .card {
      background: white;
      padding: 1.25rem 1.5rem;
      border-radius: 12px;
      box-shadow: 0 6px 20px rgba(17, 24, 39, 0.08);
      max-width: 720px;
      text-align: left;
    }

    a {
      color: #0366d6;
      text-decoration: none;
    }
  </style>
</head>

<body>
  <main class="card" role="main">
    <h1>Redirecting…</h1>
    <p id="message">If your browser doesn't redirect automatically, <a href="https://mirfatif.github.io/PermissionManagerX/help/">click here</a>.</p>
  </main>

  <script>
    (function () {
      var origin = location.origin || (location.protocol + '//' + location.host);
      var parts = location.pathname.split('/');
      var helpIndex = parts.indexOf('help');

      var target;

      if (helpIndex !== -1 && parts[helpIndex + 1] === 'en') {
        // Remove the 'en' segment immediately after 'help'
        parts.splice(helpIndex + 1, 1);
        var newPath = parts.join('/') || '/';
        target = origin + newPath + (location.search || '') + (location.hash || '');
      } else if (helpIndex !== -1 && parts[helpIndex + 1] === 'cn') {
        // Replace the 'cn' segment immediately after 'help' with 'zh'
        parts.splice(helpIndex + 1, 1, 'zh');
        var newPath = parts.join('/') || '/';
        target = origin + newPath + (location.search || '') + (location.hash || '');
      } else {
        target = origin + '/PermissionManagerX/help/';
      }

      document.getElementById('message').textContent = 'Redirecting to: ' + target;
      location.replace(target);
    })();
  </script>
</body>

</html>

================================================
FILE: LICENSE
================================================
                    GNU AFFERO GENERAL PUBLIC LICENSE
                       Version 3, 19 November 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.

  A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate.  Many developers of free software are heartened and
encouraged by the resulting cooperation.  However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.

  The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community.  It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server.  Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.

  An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals.  This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU Affero General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Remote Network Interaction; Use with the GNU General Public License.

  Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software.  This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source.  For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code.  There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.



================================================
FILE: PRIVACY.html
================================================
<!DOCTYPE html>

<html lang="en">

<head>
    <title>PMX Privacy Policy</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <style>
        body {
            font-family: sans-serif;
            margin: 2px;
        }

        hr {
            width: 100%;
            text-align: center;
            margin-top: 3%;
            margin-bottom: 3%;
            height: 0px;
            border-left-width: 0;
            border-right-width: 0;
            border-top: 1px solid black;
            border-bottom: 1px solid white;
        }

        div.card {
            margin: 20px;
            padding: 15px;
            border: solid transparent;
            border-width: thin;
            border-radius: 10px;
            display: block;
            box-sizing: border-box;
            box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.2);
        }

        a {
            text-decoration: none;
        }

        a:hover {
            text-decoration: underline;
        }
    </style>

    <script>
        document.write("<style>");

        if (screen.availHeight < screen.availWidth) {
            var margin = (screen.availWidth - screen.availHeight) / 3;
            document.write("body { margin-left: " + margin + "px; margin-right: " + margin + "px; }");
        } else {
            document.write("div.card { margin-left: 5px; margin-right: 5px; }");
        }

        document.write("</style>");

        screen.orientation.addEventListener("change", function () {
            location.reload();
        });
    </script>
</head>

<body>
    <div class="card">
        <h1>Permission Manager X</h1>

        <hr>

        <h2>Privacy Policy</h2>
        <p>Irfan Latif built <a href="https://github.com/mirfatif/PermissionManagerX">Permission Manager X</a> as an open source app. However some features are paid-only and not open source. This app is intended for use as is.</p>
        <p>This page is used to inform the app users regarding my policies with the collection, use, and disclosure of Personal Information if anyone decides to use my app.</p>

        <p><strong>Information Collection and Use</strong></p>
        <p>I DO NOT collect and retain any personally identifiable information about you or your device, like user name, address, location, pictures etc.</p>
        <p>The paid version of the app available on <a href="https://play.google.com/store/apps/details?id=com.mirfatif.permissionmanagerx">Play Store</a> does use Google Play Services for License Verification, that may collect information used to identify you. Link to their privacy policy: <a href="https://www.google.com/policies/privacy/">Google Play Services</a>.</p>

        <p><strong>Log Data</strong></p>
        <p>I want to inform you that whenever you use my app, in case of an error, the app generates a crash log file. This Log Data may include information such as device name, operating system version, configuration of the app when utilizing the app, the time and date of your use of the app, and other statistics. This log file is retained on the device and you are prompted to share the data with us through email or Telegram service. If you do not share the data, it NEVER LEAVES your device. If you opt to send the log file to us, it's permanently deleted once the related issue is resolved.</p>

        <p><strong>Cookies</strong></p>
        <p>Permission Manager X does not use cookies.</p>

        <p><strong>Service Providers</strong></p>
        <p>Permission Manager X does not depend on any third party service provider for any purpose.</p>

        <p><strong>Links to Other Sites</strong></p>
        <p>Permission Manager X makes no internet connections except for app update check (which can be disabled in app settings) and to fetch help contents. Pro version also requires internet connection for license verification.</p>
        <p>This app contains links to other sites for your guidance. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by me. Therefore, I strongly advise you to review the Privacy Policy of these websites. I have no control over, and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.</p>

        <p><strong>Children's Privacy</strong></p>
        <p>Permission Manager X does not address anyone under the age of 13. I do not collect any personal identifiable information from children under 13.</p>

        <p><strong>Changes to This Privacy Policy</strong></p>
        <p>I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page. These changes are effective immediately, after they are posted on this page.</p>

        <p><strong>Contact Us</strong></p>
        <p>If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me at mirfatif.dev@gmail.com.</p>
    </div>
</body>

</html>

================================================
FILE: README.md
================================================
# PermissionManagerX
eXtended Permission Manager for Android - view and set Manifest Permissions and AppOps

<a href="https://f-droid.org/packages/com.mirfatif.permissionmanagerx"><img alt="Get it on F-Droid" src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="100"></a>
<a href="https://play.google.com/store/apps/details?id=com.mirfatif.permissionmanagerx"><img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" height="100"></a>  
<a href="https://apt.izzysoft.de/fdroid/index/apk/com.mirfatif.permissionmanagerx"><img alt="Get it on IzzyOnDroid" src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png" height="100"></a>
<a href="https://amzn.to/2Ij50j4"><img alt="Available at Amazon AppStore" src="https://user-images.githubusercontent.com/33040459/98554253-56c9d600-22c2-11eb-83ba-bd24fb1263ae.png" height="100"></a>  
<a href="https://mirfatif.github.io/mirfatif/getpro"><img alt="Get Pro Features" src="https://user-images.githubusercontent.com/33040459/137955720-51f667ab-ea09-4b1d-9626-0b857e5f1673.png" height="100"></a>

[![Github](https://img.shields.io/github/v/release/mirfatif/PermissionManagerX?label="Github")](https://github.com/mirfatif/PermissionManagerX/releases/latest) [![F-Droid](https://img.shields.io/f-droid/v/com.mirfatif.permissionmanagerx.svg?label="F-Droid")](https://f-droid.org/packages/com.mirfatif.permissionmanagerx) [![IzzyOnDroid](https://img.shields.io/endpoint?url=https://apt.izzysoft.de/fdroid/api/v1/shield/com.mirfatif.permissionmanagerx)](https://apt.izzysoft.de/fdroid/index/apk/com.mirfatif.permissionmanagerx) [![Telegram](https://img.shields.io/badge/Telegram-latest-blue)](https://t.me/mirfatifApps)

<sup>* Join Telegram support group to get instant updates and test beta releases.</sup>

## Features
Using e<b>X</b>tended <b>Permission Manager</b>, for each installed app, on single screen, you can:

* View, grant or revoke manifest permissions
* View AppOps permissions and choose one of multiple modes
* Set your desired reference value for every changeable permission

<b>Manifest permissions</b> are those normally called permissions e.g. Storage, Camera etc. <b>AppOps</b> (app operations) is a robust framework Android uses at back end for access control. With every Android release manifest permissions are becoming more dependent on AppOps. So it's fun to control both simultaneously and see how they relate to each other.

In short, AppOps provide a fine-grained control over many of the manifest permissions. Plus it provides additional controls like background execution, vibration, clipboard access etc. Just install the app to explore it yourself.

When you reinstall an app, or change your device, or upgrade your ROM, it's a time-taking process to review all installed apps for granted permissions and revoke the unnecessary ones (after all  <b><i>privacy matters</i></b>). PMX provides you the solution. Set <b>reference states</b> of permissions, which can be quickly backed up and restored, and colored bars at left make it quite easy to review packages and permissions at a glance.

Confused? We are here to explain. Please start with:

* <a href="https://mirfatif.github.io/PermissionManagerX/help/">What is PMX?</a>
* <a href="https://mirfatif.github.io/PermissionManagerX/help/faqs/#faq36">Why do I need to use PMX?</a>
* <a href="https://mirfatif.github.io/IAnswers/android_appop_manifest_permissions">What are manifest permissions and AppOps?</a>
* <a href="https://mirfatif.github.io/PermissionManagerX/help/permission-references">Permission References</a>

## Required Privileges / Permissions

* In order to let Permission Manager X serve you at its best, either the device must be <b>rooted</b> or you need to enable <b>ADB over network</b>.
* <b>android.permission.INTERNET</b> is required to use ADB over network. The only connections made outside the device are to check for app updates or to fetch help contents. Pro version also requires internet connection for license verification.

## Note:

* The app is tested on stock Android 7-16. Some highly customized ROMs may behave unexpectedly.

## Privacy Policy

[Privacy Policy](https://mirfatif.github.io/PermissionManagerX/privacy_policy.html)

## Paid Features

[Paid Features](https://mirfatif.github.io/PermissionManagerX/help/versions/#paid-features)

## Screenshots

<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg" width="250"> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg" width="250"> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg" width="250">
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg" width="250"> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg" width="250"> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/6.jpg" width="250">

## How to Build
`build.gradle` calls a shell script to build native binaries. So a Linux environment is expected with all standard tools.
* Download code: `git clone --depth=1 --recurse-submodules --shallow-submodules https://github.com/mirfatif/PermissionManagerX.git && cd PermissionManagerX`
* Set `sdk.dir` in `local.properties` to the directory containing Android SDK
* Run `./gradlew :app:assembleRelease`. Or use IntelliJ IDEA / Android Studio.

## Translations [![Crowdin](https://badges.crowdin.net/pmx/localized.svg)](https://crowdin.com/project/pmx)
[Crowdin](https://crowdin.com/project/pmx)

## Third-Party Libraries
Credits and thanks to the developers of:
* [Android Jetpack](https://github.com/androidx/androidx)
* [Android Hidden APIs](https://github.com/anggrayudi/android-hidden-api)
* [LSPass](https://github.com/LSPosed/AndroidHiddenApiBypass)
* [LibADB Android](https://github.com/MuntashirAkon/libadb-android)
* [Spotless GoogleJavaFormat](https://github.com/diffplug/spotless)
* [Material Components for Android](https://github.com/material-components/material-components-android)
* [Guava](https://github.com/google/guava)
* [BetterLinkMovementMethod](https://github.com/saket/Better-Link-Movement-Method)
* [LeakCanary](https://github.com/square/leakcanary)

## License [![License](https://img.shields.io/github/license/mirfatif/PermissionManagerX?label="License")](https://github.com/mirfatif/PermissionManagerX/blob/master/LICENSE)

You **CANNOT** use and distribute the app icon in anyway, except for **Permission Manager X** (`com.mirfatif.permissionmanagerx`) app.

    Permission Manager X is free software: you can redistribute it and/or modify
    it under the terms of the Affero GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    Affero GNU General Public License for more details.

    You should have received a copy of the Affero GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

## Need Help?

See [Guide and FAQs](https://mirfatif.github.io/PermissionManagerX/help/).

## Want To Reach Us?

<table>
    <td>&nbsp;<a href="https://t.me/PermissionManagerX"><img src="https://raw.githubusercontent.com/mirfatif/mirfatif/main/logos/telegram.png" height="25"/> Telegram</a>&nbsp;</td>
    <td><a href="https://forum.xda-developers.com/t/app-7-0-permission-manager-x-manage-appops-and-manifest-permissions.4187657"><img src="https://raw.githubusercontent.com/mirfatif/mirfatif/main/logos/xda.png" height="23" width="21"/> XDA Thread</a></td>
    <td>&nbsp;&nbsp;&nbsp;&nbsp;<a href="mailto:mirfatif.dev@gmail.com"><img src="https://raw.githubusercontent.com/mirfatif/mirfatif/main/logos/email.png" height="22" width="25"/> Email</a>&nbsp;&nbsp;&nbsp;&nbsp;</td>
</table>


================================================
FILE: app/.gitignore
================================================
/build/
/src/*/jniLibs/


================================================
FILE: app/build.gradle
================================================
import java.nio.file.Paths

apply plugin: 'apk-conventions'

final NDK_VER = '28.2.13676358'

android {
    namespace = 'com.mirfatif.permissionmanagerx'

    defaultConfig {
        applicationId namespace

        versionCode libs.versions.app.code.get().toInteger()
        versionName libs.versions.app.name.get()

        // Flavor-independent and BuildType-independent BuildConfig.APPLICATION_ID
        buildConfigField 'String', 'APP_ID', '"' + namespace + '"'

        versionNameSuffix '-foss'
    }

    buildTypes {
        debug {
            applicationIdSuffix '.debug'
            versionNameSuffix '-debug'
        }

        release.postprocessing.obfuscate = false
    }

    packagingOptions {
        jniLibs {
            // Due to android:extractNativeLibs set to 'true' in AndroidManifest.
            useLegacyPackaging = true
        }

        // Exclude large files.
        resources.excludes.add('org/bouncycastle/pqc/crypto/picnic/lowmcL1.bin.properties')
        resources.excludes.add('org/bouncycastle/pqc/crypto/picnic/lowmcL3.bin.properties')
        resources.excludes.add('org/bouncycastle/pqc/crypto/picnic/lowmcL5.bin.properties')
    }
}

configurations {
    configureEach {
        // To avoid duplicate class version conflict.
        exclude group: 'androidx.lifecycle', module: 'lifecycle-viewmodel-ktx'
    }
}

dependencies {
    implementation project(path: ':priv_library')
    runtimeOnly project(path: ':priv_daemon')

    implementation libs.libadb.android
    // To generate X509Certificate
    implementation libs.sun.security.android
    // For conscrypt
    implementation libs.hiddenapibypass

    implementation libs.androidx.appcompat
    implementation libs.androidx.recyclerview
    implementation libs.androidx.swiperefreshlayout
    implementation libs.androidx.preference
    implementation libs.androidx.browser
    implementation libs.androidx.room.runtime
    implementation libs.androidx.security.crypto
    implementation libs.androidx.webkit
    annotationProcessor libs.androidx.room.compiler

    // For SnackBar and NavigationView. Also includes CoordinatorLayout
    implementation libs.material

    // To handle hyperlink onClick in TextView
    implementation libs.better.link.movement.method

    // To use Iterables for splitting Collections
    implementation(libs.guava)

    // Let's behave responsibly
    debugImplementation libs.leakcanary.android
}

tasks.register('buildNative', Exec) {
    def props = new Properties()
    props.load(new FileInputStream(new File(rootDir, "local.properties")))
    def ndkDir = new File(props.get("sdk.dir").toString(), "ndk/" + NDK_VER)

    if (!ndkDir.exists()) {
        throw new GradleException('NDK ' + NDK_VER + ' not installed')
    }

    environment 'ANDROID_NDK', ndkDir.absolutePath
    workingDir rootDir.absolutePath + "/native"
    commandLine './build_native.sh'

    doLast {
        if (executionResult.get().exitValue != 0) {
            throw new GradleException('buildNative failed')
        }
    }
}

afterEvaluate {
    for (String build : new String[]{'Debug', 'Release'}) {
        tasks.named('merge' + build + 'JniLibFolders').configure {
            dependsOn('buildNative')
            mustRunAfter('buildNative')
        }
    }
}

clean.doLast {
    Paths.get(projectDir.absolutePath, 'src/main/jniLibs').deleteDir()
}

preBuild.doFirst {
    // Re-merge the assets and jniLibs source sets.
    for (String dir in new String[]{'assets', 'merged_jni_libs'}) {
        Paths.get(projectDir.absolutePath, 'build/intermediates/' + dir).deleteDir()
    }
}


================================================
FILE: app/proguard-rules.pro
================================================
# Preserve the line number information for debugging stack traces.
-keepattributes SourceFile,LineNumberTable

# Keep the line number information but hide the original source file name.
-renamesourcefileattribute SourceFile

# Move all obfuscated classes into the root package.
-repackageclasses
-allowaccessmodification

# Preference keys are accesses through reflection to reset filters and for backup / restore.
-keepclassmembers class com.mirfatif.permissionmanagerx.R$string {
  int pref_*_key;
}

# Throwable names must not be obfuscated to correctly print e.toString()
-keepnames class ** extends java.lang.Throwable

-dontwarn io.github.muntashirakon.adb.AdbProtocol$AuthType
-dontwarn jakarta.annotation.Nullable


================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools">

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission
    android:name="android.permission.QUERY_ALL_PACKAGES"
    tools:ignore="QueryAllPackagesPermission" />
  <uses-permission
    android:name="android.permission.GET_APP_OPS_STATS"
    tools:ignore="ProtectedPermissions" />
  <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />

  <application
    android:name=".fwk.AppM"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    tools:ignore="AllowBackup">

    <activity
      android:name=".fwk.MainActivityM"
      android:exported="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>

    <activity
      android:name=".fwk.PackageActivityM"
      android:parentActivityName=".fwk.MainActivityM" />

    <activity
      android:name=".fwk.SettingsActivityM"
      android:parentActivityName=".fwk.MainActivityM" />

    <activity
      android:name=".fwk.AdvSettingsActivityM"
      android:parentActivityName=".fwk.MainActivityM" />

    <activity
      android:name=".fwk.FilterSettingsActivityM"
      android:parentActivityName=".fwk.MainActivityM" />

    <activity
      android:name=".fwk.AboutActivityM"
      android:parentActivityName=".fwk.MainActivityM" />

    <activity
      android:name=".fwk.HelpActivityM"
      android:parentActivityName=".fwk.MainActivityM" />

    <activity
      android:name=".fwk.CrashReportActivityM"
      android:parentActivityName=".fwk.MainActivityM" />

    <service
      android:name=".fwk.LogcatSvcM"
      android:foregroundServiceType="specialUse">
      <property
        android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
        android:value="This service is explicitly started by the user. It may run up to maximum 5 minutes and collects logs in a text file while the user is interacting with the app which includes navigating between different screens and closing the app. User can tap the stop button on the notification anytime to stop the service." />
    </service>

    <service
      android:name=".fwk.DaemonRcvSvcM"
      android:exported="true"
      android:foregroundServiceType="shortService"
      tools:ignore="ExportedService" />

    <service
      android:name=".fwk.AdbConnectSvcM"
      android:exported="true"
      android:foregroundServiceType="specialUse"
      tools:ignore="ExportedService">
      <property
        android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
        android:value="This service is explicitly started by the user through commandline to notify the app that ADB has been enabled." />
    </service>

  </application>

</manifest>


================================================
FILE: app/src/main/java/com/mirfatif/err/AdbException.java
================================================
package com.mirfatif.err;

public class AdbException extends Exception {

  public AdbException(Throwable cause) {
    super(cause);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/about/AboutActivity.java
================================================
package com.mirfatif.permissionmanagerx.about;

import static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Debug;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.fragment.app.FragmentActivity;
import com.mirfatif.permissionmanagerx.BuildConfig;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.app.App;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.databinding.ActivityAboutBinding;
import com.mirfatif.permissionmanagerx.fwk.AboutActivityM;
import com.mirfatif.permissionmanagerx.help.HelpActivity;
import com.mirfatif.permissionmanagerx.main.FeedbackDialogFrag;
import com.mirfatif.permissionmanagerx.main.FeedbackDialogFrag.FeedbackType;
import com.mirfatif.permissionmanagerx.prefs.AppUpdate;
import com.mirfatif.permissionmanagerx.prefs.MySettings;
import com.mirfatif.permissionmanagerx.prefs.settings.SettingsActivity;
import com.mirfatif.permissionmanagerx.privs.DaemonHandler;
import com.mirfatif.permissionmanagerx.privs.DaemonIface;
import com.mirfatif.permissionmanagerx.svc.LogcatSvc;
import com.mirfatif.permissionmanagerx.util.ApiUtils;
import com.mirfatif.permissionmanagerx.util.LogUtils;
import com.mirfatif.permissionmanagerx.util.NotifUtils;
import com.mirfatif.permissionmanagerx.util.UiUtils;
import com.mirfatif.permissionmanagerx.util.bg.LiveTasksQueueTyped;
import com.mirfatif.privtasks.util.MyLog;
import com.mirfatif.privtasks.util.Util;
import com.mirfatif.privtasks.util.bg.SingleSchedTaskExecutor;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class AboutActivity {

  private static final String TAG = "AboutActivity";

  private final AboutActivityM mA;

  public AboutActivity(AboutActivityM activity) {
    mA = activity;
  }

  private ActivityAboutBinding mB;
  private ActivityResultLauncher<String> mNotifPermReqLauncher, mLoggingLauncher;

  public void onCreated() {
    mB = ActivityAboutBinding.inflate(mA.getLayoutInflater());
    mA.setContentView(mB);

    ActionBar actionBar = mA.getSupportActionBar();
    if (actionBar != null) {
      actionBar.setTitle(R.string.about_menu_item);
    }

    mB.version.setText(BuildConfig.VERSION_NAME);
    openWebUrl(mB.telegram, R.string.telegram_group_link);
    openWebUrl(mB.sourceCode, R.string.source_url);
    openWebUrl(mB.issues, R.string.issues_url);
    mB.rating.setOnClickListener(
        v -> FeedbackDialogFrag.show(FeedbackType.RATE, mA.getSupportFragmentManager()));
    mB.contact.setOnClickListener(v -> ApiUtils.sendMail(mA, null));
    setLogTitle(alreadyLogging() ? R.string.stop_logging : R.string.collect_logs);
    mB.logging.setOnClickListener(
        v -> {
          if (ApiUtils.hasNotifPerm()) {
            handleLogging(true);
          } else {
            NotifUtils.askForNotifPerm(mA, mNotifPermReqLauncher);
          }
        });

    if (LogUtils.isOfficialRelease()) {
      mB.sendCrashReport.setOnClickListener(v -> CrashReportActivity.start(mA));
    } else {
      mB.sendCrashReport.setEnabled(false);
    }

    openWebUrl(mB.privacyPolicy, R.string.privacy_policy_link);
    mB.checkUpdate.setOnClickListener(v -> checkForUpdates());
    mB.translate.setOnClickListener(
        v -> TransCreditsDialogFrag.show(mA.getSupportFragmentManager()));
    mB.shareApp.setOnClickListener(v -> sendShareIntent(mA));

    mB.paidFeatures.setOnClickListener(
        v -> HelpActivity.start(mA, getString(R.string.paid_features_href)));

    mNotifPermReqLauncher =
        mA.registerForActivityResult(
            new ActivityResultContracts.RequestPermission(), this::handleLogging);

    ActivityResultCallback<Uri> callback =
        logFile -> {
          if (logFile != null) {
            LogcatSvc.start(logFile);
            setLogTitle(R.string.stop_logging);
          }
        };

    mLoggingLauncher = mA.registerForActivityResult(new CreateDocument("text/plain"), callback);
  }

  private void openWebUrl(View view, int linkResId) {
    view.setOnClickListener(v -> ApiUtils.openWebUrl(mA, getString(linkResId)));
  }

  private void setLogTitle(int resId) {
    mB.loggingTitle.setText(resId);
  }

  private static boolean alreadyLogging() {
    return MySettings.INS.isDebug();
  }

  private void handleLogging(boolean notifPermGranted) {
    if (alreadyLogging()) {
      LogcatSvc.stopSvc();
      setLogTitle(R.string.collect_logs);
      // We need an anchor view at the bottom so that the nav bar
      // doesn't overlap the snack bar due to EdgeToEdge.
      UiUtils.showSnackBar(
          mA,
          mB.snackBarAnchor,
          mB.snackBarAnchor,
          App.getCxt().getString(R.string.logging_stopped),
          5);
      return;
    }

    if (notifPermGranted) {
      UiUtils.showToast(R.string.select_log_file);
      try {
        mLoggingLauncher.launch("PermissionManagerX_" + Util.getCurrDateTime(false, true) + ".log");
      } catch (ActivityNotFoundException ignored) {
        UiUtils.showToast(R.string.no_file_picker_installed);
      }
    }
  }

  private boolean mCheckForUpdateInProgress = false;

  private void checkForUpdates() {
    if (mCheckForUpdateInProgress) {
      return;
    }
    mCheckForUpdateInProgress = true;

    mB.checkUpdateSummary.setText(R.string.check_in_progress);

    new LiveTasksQueueTyped<>(mA, () -> AppUpdate.check(false))
        .onUiWith(this::handleAppUpdateResult)
        .start();
  }

  private void handleAppUpdateResult(AppUpdate.AppUpdateResult res) {
    if (res == null) {
      UiUtils.showToast(R.string.app_is_up_to_date);
    } else if (res.failed) {
      UiUtils.showToast(R.string.check_for_updates_failed);
    } else {
      showAppUpdateDialog(mA, res.version, true);
    }

    mB.checkUpdateSummary.setText(R.string.update_summary);
    mCheckForUpdateInProgress = false;
  }

  public static void showAppUpdateDialog(FragmentActivity act, String version, boolean showCancel) {
    Builder builder =
        new Builder(act)
            .setTitle(R.string.update)
            .setMessage(getString(R.string.new_version_available) + ": " + version)
            .setPositiveButton(
                R.string.download,
                (d, w) -> ApiUtils.openWebUrl(act, getString(R.string.source_url)));
    if (showCancel) {
      builder.setNegativeButton(R.string.cancel_button, null);
    }
    AlertDialogFragment.show(act, builder.create(), "APP_UPDATE");
  }

  public static void sendShareIntent(Activity activity) {
    Intent intent = new Intent(Intent.ACTION_SEND).setType("text/plain");
    intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name));
    String text = getString(R.string.share_text, getString(R.string.source_url));
    activity.startActivity(Intent.createChooser(intent.putExtra(Intent.EXTRA_TEXT, text), null));
  }

  public boolean onCreateOptionsMenu(Menu menu) {
    mA.getMenuInflater().inflate(R.menu.about_menu, menu);
    return true;
  }

  public boolean onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_perm_status).setEnabled(DaemonHandler.INS.isDaemonAlive());
    menu.findItem(R.id.action_dump_daemon_heap).setVisible(BuildConfig.DEBUG);
    return true;
  }

  public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.action_dump_daemon_heap) {
      item.setEnabled(false);
      mDumpHeap = true;
      return true;
    }

    if (item.getItemId() == R.id.action_perm_status) {
      if (DaemonHandler.INS.isDaemonAlive()) {
        AlertDialogFragment.show(mA, null, TAG_PERM_STATUS);
      } else {
        item.setEnabled(false);
      }
      return true;
    }
    return false;
  }

  private boolean mDumpHeap = false;

  public void onDestroy() {
    if (mDumpHeap) {
      UiUtils.showToast("Heap dump will be taken after 10 seconds");
      SingleSchedTaskExecutor.schedule(
          AboutActivity::dumpHeap, 10, TimeUnit.SECONDS, TAG + "-HeapDump");
    }
  }

  private static final String CLASS = SettingsActivity.class.getName();
  private static final String TAG_PERM_STATUS = CLASS + ".PERM_STATUS";

  public AlertDialog createDialog(String tag, AlertDialogFragment dialogFragment) {
    if (TAG_PERM_STATUS.equals(tag)) {
      return new PrivilegesDialog(mA).create(dialogFragment);
    }

    return null;
  }

  private static void dumpHeap() {
    UiUtils.showToast("Taking heap dump");

    boolean done = DaemonIface.INS.dumpHeap();

    System.gc();

    String directory = Objects.requireNonNull(App.getCxt().getExternalCacheDir()).getAbsolutePath();

    File dir = new File(directory);
    if (!dir.isDirectory()) {
      MyLog.e(TAG, "dumpHeap", directory + " is not a directory");
      done = false;
    }

    File file = new File(dir, "com.mirfatif.pmx.hprof");
    try {
      Debug.dumpHprofData(file.getAbsolutePath());
    } catch (IOException e) {
      MyLog.e(TAG, "dumpHeap", e);
      done = false;
    }

    UiUtils.showToast(done ? "Heap dump completed" : "Heap dump failed");
  }

  public static void start(Activity activity) {
    activity.startActivity(new Intent(App.getCxt(), AboutActivityM.class));
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/about/CrashReportActivity.kt
================================================
package com.mirfatif.permissionmanagerx.about

import android.content.Intent
import android.view.View
import androidx.annotation.MainThread
import androidx.annotation.WorkerThread
import androidx.appcompat.app.AlertDialog
import androidx.core.app.NotificationManagerCompat
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import com.mirfatif.permissionmanagerx.R
import com.mirfatif.permissionmanagerx.app.App
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment
import com.mirfatif.permissionmanagerx.databinding.ActivityCrashReportBinding
import com.mirfatif.permissionmanagerx.fwk.CrashReportActivityM
import com.mirfatif.permissionmanagerx.prefs.AppUpdate
import com.mirfatif.permissionmanagerx.util.ApiUtils
import com.mirfatif.permissionmanagerx.util.LogUtils
import com.mirfatif.permissionmanagerx.util.UiUtils
import com.mirfatif.privtasks.util.MyLog
import java.io.IOException
import java.lang.AutoCloseable
import java.net.HttpURLConnection
import java.net.URL
import java.nio.charset.StandardCharsets
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class CrashReportActivity(private val mA: CrashReportActivityM) {
  private lateinit var mB: ActivityCrashReportBinding

  fun onCreated() {
    mB = ActivityCrashReportBinding.inflate(mA.layoutInflater)
    mA.setContentView(mB)

    mA.supportActionBar?.setTitle(R.string.crash_report)

    mA.lifecycleScope.launch(Dispatchers.Main) { setFileContents(readFileContents()) }
  }

  private data class Result(val updateResult: AppUpdate.AppUpdateResult?, val contents: String)

  private suspend fun readFileContents(): Result? =
      withContext(Dispatchers.IO) {
        NotificationManagerCompat.from(App.getCxt())
            .cancel(ApiUtils.getInt(R.integer.channel_crash_report))

        val logFile = LogUtils.getCrashLogFile()
        if (!logFile.exists()) {
          UiUtils.showToast(R.string.crash_log_file_not_exists_toast)
          return@withContext null
        }

        val text: String

        try {
          text = logFile.readText()
        } catch (e: IOException) {
          MyLog.e(TAG, "getFileContents", e)
          UiUtils.showToast(R.string.crash_log_file_read_failed_toast)
          return@withContext null
        }

        if (text.split('\n').size <= LogUtils.CRASH_FILE_HEADER_LINES) {
          UiUtils.showToast(R.string.crash_log_file_not_exists_toast)
          null
        } else {
          withContext(Dispatchers.Main) { mB.progMsg.setText(R.string.checking_for_app_update) }
          Result(AppUpdate.check(false), text)
        }
      }

  @MainThread
  private fun setFileContents(result: Result?) {
    if (result == null) {
      mA.finishAfterTransition()
      return
    }

    mB.reportCont.visibility = View.VISIBLE
    mB.contentV.text = result.contents

    handleAppUpdate(result)
  }

  @MainThread
  private fun handleAppUpdate(res: Result) {
    mB.progCont.visibility = View.GONE

    if (res.updateResult == null) {
      mB.submitButton.isEnabled = true

      mB.submitButton.setOnClickListener {
        mB.submitButton.setText(R.string.submitting_report_button)
        mB.submitButton.isEnabled = false

        mA.lifecycleScope.launch(Dispatchers.Main) {
          handleSubmitResult(withContext(Dispatchers.IO) { submit(res.contents) })
        }
      }
    } else if (res.updateResult.failed) {
      val builder =
          AlertDialog.Builder(mA)
              .setTitle(R.string.update)
              .setMessage(R.string.check_for_updates_failed_long)
              .setPositiveButton(R.string.retry_button) { d, w ->
                mB.progCont.visibility = View.VISIBLE
                mA.lifecycleScope.launch(Dispatchers.IO) {
                  val updateResult = AppUpdate.check(false)
                  withContext(Dispatchers.Main) {
                    handleAppUpdate(Result(updateResult, res.contents))
                  }
                }
              }
      AlertDialogFragment.show(mA, builder.create(), "APP_UPDATE")
    } else {
      AboutActivity.showAppUpdateDialog(mA, res.updateResult.version, false)
    }
  }

  @Synchronized
  @WorkerThread
  private fun submit(fileContents: String): Boolean {
    try {
      ServerConnection().use { conn ->
        if (!conn.write(fileContents)) {
          return false
        }
      }
    } catch (e: IOException) {
      MyLog.e(TAG, "submit", e)
      return false
    }

    val logFile = LogUtils.getCrashLogFile()
    if (!logFile.delete()) {
      MyLog.e(TAG, "submit", "Failed to delete " + logFile.absolutePath)
    }

    LogUtils.createCrashLogFile()

    return true
  }

  private class ServerConnection : AutoCloseable {
    private val conn =
        URL("https://api.mirfatif.com/crash-report?app=PMX").openConnection() as HttpURLConnection

    init {
      conn.setConnectTimeout(60000)
      conn.setReadTimeout(60000)
      conn.setDoOutput(true)
      conn.setRequestMethod("PUT")
      conn.setRequestProperty("Content-Type", "text/plain; charset=UTF-8")
      conn.connect()
    }

    override fun close() {
      conn.disconnect()
    }

    fun write(fileContents: String): Boolean {
      conn.getOutputStream().use { it.write(fileContents.toByteArray(StandardCharsets.UTF_8)) }

      val code = conn.getResponseCode()
      if (code == HttpURLConnection.HTTP_CREATED || code == HttpURLConnection.HTTP_OK) {
        return true
      }

      MyLog.e(TAG, "write", "Response code: " + code + " (" + conn.getResponseMessage() + ")")
      return false
    }
  }

  private fun handleSubmitResult(done: Boolean) {
    if (done) {
      UiUtils.showToast(R.string.thank_you)
      mA.finishAfterTransition()
    } else {
      mB.submitButton.setText(R.string.submit_report_button)
      mB.submitButton.isEnabled = true
      UiUtils.showToast(R.string.submit_crash_report_failed_toast)
    }
  }

  companion object {
    private const val TAG = "CrashReportActivity"

    @JvmStatic
    fun start(act: FragmentActivity) {
      act.startActivity(Intent(App.getCxt(), CrashReportActivityM::class.java))
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/about/PrivilegesAdapter.java
================================================
package com.mirfatif.permissionmanagerx.about;

import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.about.PrivilegesAdapter.ItemViewHolder;
import com.mirfatif.permissionmanagerx.databinding.AboutPrivilegesItemBinding;
import com.mirfatif.privtasks.bind.PrivsStatus;
import java.util.ArrayList;
import java.util.List;

public class PrivilegesAdapter extends RecyclerView.Adapter<ItemViewHolder> {

  private final List<PrivsStatus.PermStatus> mPermStatusList = new ArrayList<>();

  void submitList(List<PrivsStatus.PermStatus> permStatusList) {
    synchronized (mPermStatusList) {
      mPermStatusList.clear();
      mPermStatusList.addAll(permStatusList);
      notifyDataSetChanged();
    }
  }

  public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    AboutPrivilegesItemBinding b = AboutPrivilegesItemBinding.inflate(inflater, parent, false);
    return new ItemViewHolder(b);
  }

  public void onBindViewHolder(ItemViewHolder holder, int position) {
    holder.bind(position);
  }

  public long getItemId(int position) {
    return position;
  }

  public int getItemCount() {
    return mPermStatusList.size();
  }

  class ItemViewHolder extends ViewHolder {

    private final AboutPrivilegesItemBinding mB;

    public ItemViewHolder(AboutPrivilegesItemBinding binding) {
      super(binding.getRoot());
      mB = binding;
    }

    void bind(int pos) {
      PrivsStatus.PermStatus item = mPermStatusList.get(pos);
      if (item != null) {
        mB.permV.setSelected(true);
        mB.permV.setText(item.name.replaceFirst("^android.permission.", ""));
        mB.statusV.setImageResource(item.granted ? R.drawable.tick : R.drawable.cross_red);
      }
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/about/PrivilegesDialog.java
================================================
package com.mirfatif.permissionmanagerx.about;

import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.databinding.AboutPrivilegesDialogBinding;
import com.mirfatif.permissionmanagerx.parser.PackageParser;
import com.mirfatif.permissionmanagerx.privs.DaemonHandler;
import com.mirfatif.permissionmanagerx.privs.DaemonIface;
import com.mirfatif.permissionmanagerx.util.UiUtils;
import com.mirfatif.permissionmanagerx.util.bg.LiveTasksQueueTyped;
import com.mirfatif.privtasks.bind.PrivsStatus;

public class PrivilegesDialog {

  private final FragmentActivity mA;

  PrivilegesDialog(FragmentActivity activity) {
    mA = activity;
  }

  AlertDialog create(AlertDialogFragment dialogFragment) {
    AboutPrivilegesDialogBinding b = AboutPrivilegesDialogBinding.inflate(mA.getLayoutInflater());
    PrivilegesAdapter adapter = new PrivilegesAdapter();

    new LiveTasksQueueTyped<>(dialogFragment, DaemonIface.INS::getPrivsStatus)
        .onUiWith(result -> updatePermStatusDialog(result, b, adapter, dialogFragment))
        .start();

    b.uidV.setText(String.valueOf(DaemonHandler.INS.getUid()));
    b.recyclerV.setLayoutManager(new LinearLayoutManager(mA));
    DividerItemDecoration divider = new DividerItemDecoration(mA, DividerItemDecoration.VERTICAL);
    divider.setDrawable(new Divider(mA.getColor(R.color.colorControlNormal)));
    b.recyclerV.addItemDecoration(divider);
    b.recyclerV.setAdapter(adapter);
    return new AlertDialog.Builder(mA)
        .setTitle(R.string.perm_status_menu_item)
        .setView(b.getRoot())
        .create();
  }

  private void updatePermStatusDialog(
      PrivsStatus status,
      AboutPrivilegesDialogBinding b,
      PrivilegesAdapter adapter,
      AlertDialogFragment dialogFragment) {
    if (status == null) {
      dialogFragment.dismissAllowingStateLoss();
      return;
    }

    adapter.submitList(status.permStatusList);
    b.opToDefModeV.setImageResource(getIcon(status.opToDefModeWorks));
    b.opToSwV.setImageResource(getIcon(status.opToSwitchWorks));
    b.opToNameV.setImageResource(getIcon(status.opToNameWorks));
    b.getOpsV.setImageResource(getIcon(status.getOpsWorks));
    b.consAppOpNumV.setImageResource(getIcon(status.opNumConsistent));
    b.consAppOpModeV.setImageResource(
        getIcon(PackageParser.INS.mOpModesConsistent && status.opModeConsistent));
  }

  private int getIcon(boolean ok) {
    return ok ? R.drawable.tick : R.drawable.cross_red;
  }

  private static class Divider extends ShapeDrawable {

    public Divider(int color) {
      super(new RectShape());
      super.setAlpha(100);
      super.getPaint().setColor(color);
      super.setIntrinsicHeight(UiUtils.dpToPx(1.2f));
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/about/TransCreditsDialogFrag.java
================================================
package com.mirfatif.permissionmanagerx.about;

import static com.mirfatif.permissionmanagerx.util.ApiUtils.openWebUrl;

import android.content.res.TypedArray;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.FragmentManager;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.app.App;
import com.mirfatif.permissionmanagerx.base.BottomSheetDialogFrag;
import com.mirfatif.permissionmanagerx.databinding.TransCreditsRowBinding;
import com.mirfatif.permissionmanagerx.databinding.TranslationDialogBinding;
import com.mirfatif.permissionmanagerx.util.StringUtils;
import me.saket.bettermovementmethod.BetterLinkMovementMethod;

public class TransCreditsDialogFrag extends BottomSheetDialogFrag {

  public static void show(FragmentManager fm) {
    TransCreditsDialogFrag frag = new TransCreditsDialogFrag();
    frag.show(fm, "TRANS_CREDITS");
  }

  public View onCreateView(
      LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    TranslationDialogBinding b = TranslationDialogBinding.inflate(mA.getLayoutInflater());

    TypedArray names = App.getRes().obtainTypedArray(R.array.locale_contributor_name_arrays);
    TypedArray links = App.getRes().obtainTypedArray(R.array.locale_contributor_link_arrays);
    String[] locales = App.getRes().getStringArray(R.array.locales);

    StringBuilder sb = new StringBuilder();
    TransCreditsRowBinding row;

    int nameArrayResId, linkArrayResId;
    String[] nameArray, linkArray;
    String link;

    BetterLinkMovementMethod moveMethod = BetterLinkMovementMethod.newInstance();
    moveMethod.setOnLinkClickListener((textView, url) -> openWebUrl(mA, url));

    for (int i = 0; i < names.length(); i++) {
      nameArrayResId = names.getResourceId(i, 0);
      linkArrayResId = links.getResourceId(i, 0);
      if (nameArrayResId == 0 || linkArrayResId == 0) {
        continue;
      }

      row = TransCreditsRowBinding.inflate(mA.getLayoutInflater());
      b.table.addView(row.getRoot());

      row.lang.setText(locales[i]);

      nameArray = App.getRes().getStringArray(nameArrayResId);
      linkArray = App.getRes().getStringArray(linkArrayResId);

      sb.setLength(0);

      for (int n = 0; n < nameArray.length; n++) {
        if (n > 0) {
          sb.append("<br />");
        }

        sb.append(nameArray[n]).append(" ");

        link = linkArray[n];
        if (link.startsWith("http://") || link.startsWith("https://")) {
          sb.append("<a href=\"").append(link).append("\">LINK</a>");
        } else if (!link.isEmpty()) {
          sb.append("(").append(link).append(")");
        }
      }

      if (sb.length() != 0) {
        row.credits.setText(StringUtils.htmlToString(sb.toString()));
      }
      row.credits.setMovementMethod(moveMethod);
    }

    names.recycle();
    links.recycle();

    b.addMyLang.setOnClickListener(
        v -> {
          openWebUrl(mA, getString(R.string.translation_link));
          dismissAllowingStateLoss();
        });
    return b.getRoot();
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/app/App.java
================================================
package com.mirfatif.permissionmanagerx.app;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.SystemClock;
import com.mirfatif.permissionmanagerx.fwk.AppM;
import com.mirfatif.permissionmanagerx.util.AppLifecycle;
import com.mirfatif.permissionmanagerx.util.LocaleUtils;
import com.mirfatif.permissionmanagerx.util.LogUtils;
import com.mirfatif.privtasks.util.MyLog;
import java.io.PrintWriter;
import java.io.StringWriter;

public class App {

  private static final String TAG = "App";

  private final AppM mA;

  public App(AppM app) {
    mA = app;
  }

  private static Context sContext;

  private Thread.UncaughtExceptionHandler defaultExceptionHandler;

  public void onCreate() {
    sContext = mA.getApplicationContext();
    mPm = App.getCxt().getPackageManager();

    setLocale();

    defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
    Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());

    AppLifecycle.init(mA);
  }

  public Configuration onConfigurationChanged(Configuration newConfig) {
    return LocaleUtils.setLocale(newConfig);
  }

  public static void setLocale() {
    LocaleUtils.setLocale(sContext);
  }

  public static Context getCxt() {
    while (sContext == null) {
      SystemClock.sleep(100);
    }
    return sContext;
  }

  public static Resources getRes() {
    return sContext.getResources();
  }

  private static PackageManager mPm;

  public static PackageManager getPm() {
    return mPm;
  }

  private class ExceptionHandler implements Thread.UncaughtExceptionHandler {

    public void uncaughtException(Thread t, Throwable e) {
      MyLog.e(TAG, "uncaughtException", t.getName() + ": " + e);

      StringWriter stringWriter = new StringWriter();
      PrintWriter writer = new PrintWriter(stringWriter, true);
      e.printStackTrace(writer);
      writer.close();
      LogUtils.showCrashNotification(stringWriter.toString(), false);

      defaultExceptionHandler.uncaughtException(t, e);
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/backup/BackupFileSelector.java
================================================
package com.mirfatif.permissionmanagerx.backup;

import android.content.ActivityNotFoundException;
import android.net.Uri;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.fragment.app.FragmentActivity;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.util.UiUtils;
import com.mirfatif.privtasks.util.Util;

public class BackupFileSelector {

  public static final String BACKUP_FILE_MIME = "text/xml";

  public static String backupFileName() {
    return "PermissionManagerX_" + Util.getCurrDateTime(false, false) + ".xml";
  }

  private final ActivityResultLauncher<String> mBackupLauncher;
  private final ActivityResultLauncher<String[]> mRestoreLauncher;

  public BackupFileSelector(
      FragmentActivity act, boolean forBackup, ActivityResultCallback<Uri> callback) {
    if (forBackup) {
      mBackupLauncher =
          act.registerForActivityResult(
              new ActivityResultContracts.CreateDocument(BACKUP_FILE_MIME), callback);

      mRestoreLauncher = null;
    } else {
      mBackupLauncher = null;
      mRestoreLauncher =
          act.registerForActivityResult(new ActivityResultContracts.OpenDocument(), callback);
    }
  }

  public void launch() {
    UiUtils.showToast(R.string.select_backup_file);

    try {
      if (mBackupLauncher != null) {
        mBackupLauncher.launch(backupFileName());
      } else {
        mRestoreLauncher.launch(new String[] {"text/xml"});
      }
    } catch (ActivityNotFoundException e) {
      UiUtils.showToast(R.string.no_file_picker_installed);
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/backup/BackupRestore.java
================================================
package com.mirfatif.permissionmanagerx.backup;

import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.util.Xml;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.app.App;
import com.mirfatif.permissionmanagerx.parser.AppOpsParser;
import com.mirfatif.permissionmanagerx.parser.PackageParser;
import com.mirfatif.permissionmanagerx.parser.permsdb.PermissionEntity;
import com.mirfatif.permissionmanagerx.parser.permsdb.PermsDb;
import com.mirfatif.permissionmanagerx.prefs.ExcFiltersData;
import com.mirfatif.permissionmanagerx.prefs.MySettings;
import com.mirfatif.permissionmanagerx.profile.PermProfileBackupRestore;
import com.mirfatif.permissionmanagerx.util.ApiUtils;
import com.mirfatif.privtasks.util.MyLog;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

public enum BackupRestore {
  INS;

  private static final String TAG = "BackupRestore";

  private static final String TAG_ROOT = "PermissionManagerX";

  private static final String TAG_PREFERENCES = "preferences";
  private static final String TAG_PREF = "pref";

  private static final String TAG_PERMISSIONS = "permissions";
  private static final String TAG_PERM = "perm";

  private static final String ATTR_KEY = "key";
  private static final String ATTR_VALUE = "value";
  private static final String ATTR_TYPE = "type";

  private static final String BOOLEAN = "boolean";
  private static final String FLOAT = "float";
  private static final String INT = "int";
  private static final String LONG = "long";
  private static final String SET = "Set";
  private static final String STRING = "String";

  private static final String SEPARATOR = ",";

  private static final String ATTR_PKG = "pkg";
  private static final String ATTR_PERM = "perm";
  private static final String ATTR_STATE = "state";
  private static final String ATTR_APP_OP = "app_op";
  private static final String ATTR_PER_UID = "per_uid";
  private static final String ATTR_USER_ID = "user_id";

  public Result backupNoThrow(Uri file, boolean backupPrefs, boolean skipUninstalledApps) {
    try {
      return backup(file, backupPrefs, skipUninstalledApps);
    } catch (FileNotFoundException e) {
      MyLog.e(TAG, "backupNoThrow", e);
      return null;
    }
  }

  private Result backup(Uri file, boolean backupPrefs, boolean skipUninstalledApps)
      throws FileNotFoundException {
    try (OutputStream os = App.getCxt().getContentResolver().openOutputStream(file, "w")) {
      return backup(os, backupPrefs, skipUninstalledApps);
    } catch (FileNotFoundException e) {
      throw e;
    } catch (IOException e) {
      MyLog.e(TAG, "backup", e);
      return null;
    }
  }

  public Result backup(
      OutputStream outputStream, boolean backupPrefs, boolean skipUninstalledApps) {
    XmlSerializer serializer = Xml.newSerializer();
    StringWriter stringWriter = new StringWriter();
    try {
      serializer.setOutput(stringWriter);
      serializer.startDocument("UTF-8", true);
      serializer.startTag(null, TAG_ROOT);
      serializer.startTag(null, TAG_PREFERENCES);
    } catch (IOException e) {
      MyLog.e(TAG, "backup", e);
      return null;
    }

    int prefCount = 0, invalidPrefs = 0;

    if (backupPrefs) {
      Map<String, ?> prefEntries = MySettings.getDefPrefs().getAll();

      for (Map.Entry<String, ?> entry : prefEntries.entrySet()) {
        String key = entry.getKey();

        if (isInvalidPrefKey(key)) {
          MyLog.i(TAG, "backup", "Skipping " + key);
          continue;
        }

        prefCount++;

        Object value = entry.getValue();
        String type;

        if (value instanceof Boolean) {
          type = BOOLEAN;
        } else if (value instanceof Float) {
          type = FLOAT;
        } else if (value instanceof Integer) {
          type = INT;
        } else if (value instanceof Long) {
          type = LONG;
        } else if (value instanceof Set) {
          type = SET;
          StringBuilder stringBuilder = new StringBuilder();
          for (Object object : (Set<?>) value) {
            if (stringBuilder.length() != 0) {
              stringBuilder.append(SEPARATOR);
            }
            stringBuilder.append(object.toString());
          }
          value = stringBuilder;
        } else if (value instanceof String) {
          type = STRING;
        } else {
          MyLog.e(TAG, "backup", "Unknown preference type: " + value.toString());
          invalidPrefs++;
          continue;
        }

        try {
          serializer.startTag(null, TAG_PREF);
          serializer.attribute(null, ATTR_KEY, key);
          serializer.attribute(null, ATTR_VALUE, value.toString());
          serializer.attribute(null, ATTR_TYPE, type);
          serializer.endTag(null, TAG_PREF);
        } catch (IOException e) {
          MyLog.e(TAG, "backup", e);
          return null;
        }
      }
    }

    try {
      serializer.endTag(null, TAG_PREFERENCES);
      serializer.startTag(null, TAG_PERMISSIONS);
    } catch (IOException e) {
      MyLog.e(TAG, "backup", e);
      return null;
    }

    List<PermissionEntity> permEntities = PermsDb.INS.getDb().getAll();

    int permCount = permEntities.size();
    int skippedApps = 0;

    if (skipUninstalledApps) {
      List<String> pkgList = getAllPkgList();
      int permEntitiesSize = permEntities.size();
      permEntities.removeIf(entity -> !pkgList.contains(entity.pkgName));
      skippedApps = permEntitiesSize - permEntities.size();
    }

    for (PermissionEntity entity : permEntities) {
      try {
        serializer.startTag(null, TAG_PERM);

        serializer.attribute(null, ATTR_PKG, entity.pkgName);
        serializer.attribute(null, ATTR_PERM, entity.permName);
        serializer.attribute(null, ATTR_STATE, entity.state);
        serializer.attribute(null, ATTR_APP_OP, String.valueOf(entity.isAppOps));
        serializer.attribute(null, ATTR_PER_UID, String.valueOf(entity.isPerUid));
        serializer.attribute(null, ATTR_USER_ID, String.valueOf(entity.userId));

        serializer.endTag(null, TAG_PERM);
      } catch (IOException e) {
        MyLog.e(TAG, "backup", e);
        return null;
      }
    }

    try {
      serializer.endTag(null, TAG_PERMISSIONS);
    } catch (IOException e) {
      MyLog.e(TAG, "backup", e);
      return null;
    }

    int profileCount;

    try {
      profileCount = PermProfileBackupRestore.backup(serializer);
    } catch (IOException e) {
      MyLog.e(TAG, "backup", e);
      return null;
    }

    try {
      serializer.endTag(null, TAG_ROOT);
      serializer.endDocument();
      serializer.flush();
    } catch (IOException e) {
      MyLog.e(TAG, "backup", e);
      return null;
    }

    Source input = new StreamSource(new StringReader(stringWriter.toString()));
    StreamResult output = new StreamResult(outputStream);
    try {
      Transformer transformer = TransformerFactory.newInstance().newTransformer();
      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
      transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
      transformer.transform(input, output);
    } catch (TransformerException e) {
      MyLog.e(TAG, "backup", e);
    }

    try {
      outputStream.flush();
      outputStream.close();
    } catch (IOException e) {
      MyLog.e(TAG, "backup", e);
    }

    MyLog.i(TAG, "backup", "Succeeded");

    return new Result(prefCount, permCount, profileCount, invalidPrefs, skippedApps);
  }

  public Result restore(Uri file, boolean skipUninstalledApps) {
    Result res;

    try (InputStream is = App.getCxt().getContentResolver().openInputStream(file)) {
      if (is == null) {
        MyLog.e(TAG, "restore", "Failed to get InputStream");
        return null;
      }
      res = restore(is, skipUninstalledApps);
    } catch (IOException | SecurityException e) {
      MyLog.e(TAG, "restore", e);
      return null;
    }

    if (res != null) {
      ExcFiltersData.INS.populateLists(true);
      PermsDb.INS.buildRefs();
      PackageParser.INS.updatePkgList();
    }

    return res;
  }

  public Result restore(InputStream is, boolean skipUninstalledApps) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    try {
      while ((len = is.read(buffer)) > -1) {
        byteArrayOutputStream.write(buffer, 0, len);
      }
      byteArrayOutputStream.flush();
    } catch (IOException e) {
      MyLog.e(TAG, "restore", e);
      return null;
    }

    InputStream inputStream1 = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
    InputStream inputStream2 = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
    InputStream inputStream3 = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

    int invalidPrefs = 0;

    String[] attrNames = new String[] {ATTR_KEY, ATTR_VALUE, ATTR_TYPE};
    List<String[]> entries = getKeyValueEntries(inputStream1, TAG_PREFERENCES, TAG_PREF, attrNames);

    if (entries == null) {
      return null;
    }

    int prefCount = entries.size();

    String key, value, type;

    SharedPreferences.Editor prefEdit = MySettings.getDefPrefs().edit();
    for (String[] entry : entries) {
      key = entry[0];
      value = entry[1];
      type = entry[2];

      if (isInvalidPrefKey(key)) {
        MyLog.e(TAG, "restore", "Invalid preference: " + key);
        invalidPrefs++;
        continue;
      }

      switch (type) {
        case BOOLEAN -> prefEdit.putBoolean(key, Boolean.parseBoolean(value));
        case FLOAT -> prefEdit.putFloat(key, Float.parseFloat(value));
        case INT -> prefEdit.putInt(key, Integer.parseInt(value));
        case LONG -> prefEdit.putLong(key, Long.parseLong(value));
        case SET -> {
          if (value.length() == 0) {
            prefEdit.putStringSet(key, new HashSet<>());
          } else {
            prefEdit.putStringSet(key, new HashSet<>(Arrays.asList(value.split(SEPARATOR))));
          }
        }
        case STRING -> prefEdit.putString(key, value);
        default -> {
          MyLog.e(TAG, "restore", "Unknown preference type: " + type);
          invalidPrefs++;
        }
      }
      prefEdit.apply();
    }

    attrNames =
        new String[] {
          ATTR_PKG,
          ATTR_PERM,
          ATTR_STATE,
          ATTR_APP_OP,
          ATTR_PER_UID,
          ATTR_USER_ID,
          ATTR_KEY,
          ATTR_VALUE,
          ATTR_TYPE
        };

    entries = getKeyValueEntries(inputStream2, TAG_PERMISSIONS, TAG_PERM, attrNames);
    if (entries == null) {
      return null;
    }

    int permCount = entries.size();

    List<PermissionEntity> entities = new ArrayList<>();

    String pkgName, permName, state;
    boolean isAppOp, isPerUid;

    for (String[] entry : entries) {
      pkgName = entry[0] != null ? entry[0] : entry[6];
      permName = entry[1] != null ? entry[1] : entry[8];
      state = entry[2] != null ? entry[2] : entry[7];
      isAppOp = entry[3] != null && Boolean.parseBoolean(entry[3]);
      isPerUid = entry[4] != null && Boolean.parseBoolean(entry[4]);

      entities.add(new PermissionEntity(pkgName, permName, state, isAppOp, isPerUid));
    }

    int skippedApps = 0;

    if (skipUninstalledApps) {
      List<String> pkgList = getAllPkgList();
      int permEntriesSize = entities.size();
      entities.removeIf(entity -> !pkgList.contains(entity.pkgName));
      skippedApps = permEntriesSize - entities.size();
    }

    PermsDb.INS.updateRefsDb(entities.toArray(new PermissionEntity[0]));

    if (!entries.isEmpty() && entries.get(0)[0] == null) {
      if (!AppOpsParser.INS.fixPermDb()) {
        MySettings.INS.setFixPermDb(true);
      }
    }

    int profileCount;

    try {
      profileCount = PermProfileBackupRestore.restore(inputStream3);
    } catch (Exception ignored) {
      return null;
    }

    MyLog.i(TAG, "restore", "Succeeded");

    return new Result(prefCount, permCount, profileCount, invalidPrefs, skippedApps);
  }

  public static List<String[]> getKeyValueEntries(
      InputStream inputStream, String mainTag, String entryTag, String[] attrNames) {
    XmlPullParser xmlParser = Xml.newPullParser();

    List<String[]> entries = new ArrayList<>();

    boolean rootTagFound = false;
    boolean mainTagFound = false;

    try {
      xmlParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
      xmlParser.setInput(inputStream, null);
      while (true) {
        int eventType = xmlParser.next();
        if (eventType == XmlPullParser.END_DOCUMENT) {
          break;
        }

        String tagName = xmlParser.getName();
        if (eventType == XmlPullParser.START_TAG && tagName.equals(TAG_ROOT)) {
          rootTagFound = true;
        }
        if (eventType == XmlPullParser.START_TAG && tagName.equals(mainTag)) {
          mainTagFound = true;
        }

        if (!rootTagFound || !mainTagFound) {
          continue;
        }

        if (eventType == XmlPullParser.END_TAG && tagName.equals(mainTag)) {
          break;
        }

        if (eventType == XmlPullParser.START_TAG && tagName.equals(entryTag)) {
          String[] values = new String[attrNames.length];
          for (int i = 0; i < attrNames.length; i++) {
            values[i] = xmlParser.getAttributeValue(null, attrNames[i]);
          }

          entries.add(values);
        }
      }
    } catch (IOException | XmlPullParserException e) {
      MyLog.e(TAG, "getKeyValueEntries", e);
      return null;
    }

    return entries;
  }

  private final List<String> mBackupAblePrefs = new ArrayList<>();

  private boolean isInvalidPrefKey(String prefKey) {
    synchronized (mBackupAblePrefs) {
      if (mBackupAblePrefs.isEmpty()) {
        int resId;
        String name;

        for (Field field : R.string.class.getDeclaredFields()) {
          name = field.getName();

          try {
            resId = R.string.class.getDeclaredField(name).getInt(null);
          } catch (NoSuchFieldException | IllegalAccessException e) {
            continue;
          }

          String str = App.getRes().getString(resId);

          if (str.startsWith("pref_") && !str.endsWith("_enc") && name.equals(str + "_key")) {
            mBackupAblePrefs.add(str);
          }
        }
      }
    }

    return !mBackupAblePrefs.contains(prefKey);
  }

  private List<String> getAllPkgList() {
    return ApiUtils.getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES).parallelStream()
        .map(pkgInfo -> pkgInfo.packageName)
        .collect(Collectors.toList());
  }

  public static class Result {

    public final int prefs, perms, profiles, invalidPrefs, skippedApps;

    private Result(int prefs, int perms, int profiles, int invalidPrefs, int skippedApps) {
      this.prefs = prefs;
      this.perms = perms;
      this.profiles = profiles;
      this.invalidPrefs = invalidPrefs;
      this.skippedApps = skippedApps;
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/AlertDialogFragment.java
================================================
package com.mirfatif.permissionmanagerx.base;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle.State;
import com.mirfatif.permissionmanagerx.util.UiUtils;
import com.mirfatif.privtasks.util.MyLog;

public class AlertDialogFragment extends AppCompatDialogFragment {

  private static final String TAG = "AlertDialogFragment";

  public static final String DIALOG_TAG = AlertDialogFragment.class.getName() + ".A";

  public AlertDialogFragment() {}

  private AlertDialog mAlertDialog;

  public AlertDialog getDialog() {
    return mAlertDialog;
  }

  private AlertDialogFragment(AlertDialog alertDialog) {
    mAlertDialog = alertDialog;
  }

  private BaseActivity mA;

  public void onAttach(Context context) {
    super.onAttach(context);
    mA = (BaseActivity) getActivity();
  }

  public Dialog onCreateDialog(Bundle savedInstanceState) {
    if (mAlertDialog == null) {
      mAlertDialog = mA.createDialog(requireArguments().getString(DIALOG_TAG), this);
      if (mAlertDialog == null) {
        dismissAllowingStateLoss();
        return new Builder(mA).create();
      }
    }
    UiUtils.onCreateDialog(mAlertDialog, mA);
    return mAlertDialog;
  }

  public void onSaveInstanceState(Bundle outState) {}

  private OnDismissListener mDismissListener;

  public AlertDialogFragment setOnDismissListener(OnDismissListener dismissListener) {
    mDismissListener = dismissListener;
    return this;
  }

  public void onDismiss(DialogInterface dialog) {
    super.onDismiss(dialog);
    if (mDismissListener != null) {
      mDismissListener.onDismiss(dialog);
    }
  }

  public static AlertDialogFragment create(AlertDialog alertDialog, String tag) {
    AlertDialogFragment frag = new AlertDialogFragment(alertDialog);
    Bundle args = new Bundle();
    args.putString(DIALOG_TAG, tag);
    frag.setArguments(args);

    return frag;
  }

  public static AlertDialogFragment show(
      FragmentActivity activity, AlertDialog alertDialog, String tag) {
    return create(alertDialog, tag).show(activity);
  }

  public AlertDialogFragment show(FragmentActivity activity) {
    synchronized (AlertDialogFragment.class) {
      String tag = requireArguments().getString(DIALOG_TAG);
      FragmentManager manager = activity.getSupportFragmentManager();

      Fragment fragment = manager.findFragmentByTag(tag);
      if (fragment != null) {
        manager.beginTransaction().remove(fragment).commitNowAllowingStateLoss();
      }

      try {
        if (activity.getLifecycle().getCurrentState().isAtLeast(State.INITIALIZED)
            && !activity.isChangingConfigurations()) {
          showNow(manager, tag);
        }
      } catch (IllegalStateException e) {
        MyLog.w(TAG, "show", e.toString());
      }

      return this;
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/BaseActivity.java
================================================
package com.mirfatif.permissionmanagerx.base;

import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.ViewGroup;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.viewbinding.ViewBinding;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.databinding.StatusBarBgContBinding;
import com.mirfatif.permissionmanagerx.prefs.MySettings;
import com.mirfatif.permissionmanagerx.util.LocaleUtils;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public abstract class BaseActivity extends AppCompatActivity {

  protected synchronized void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (!setNightTheme()) {
      onCreated(savedInstanceState);
    }
  }

  protected abstract void onCreated(Bundle savedInstanceState);

  public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == android.R.id.home) {
      getOnBackPressedDispatcher().onBackPressed();
      return true;
    }
    return super.onOptionsItemSelected(item);
  }

  protected void attachBaseContext(Context context) {
    super.attachBaseContext(LocaleUtils.setLocale(context));
  }

  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(LocaleUtils.setLocale(newConfig));
  }

  public void applyOverrideConfiguration(Configuration overrideConfiguration) {
    super.applyOverrideConfiguration(LocaleUtils.setLocale(overrideConfiguration));
  }

  public AlertDialog createDialog(String tag, AlertDialogFragment dialogFragment) {
    return null;
  }

  private boolean setNightTheme() {
    boolean wasNightMode = UiUtils.isNightMode(this);

    String mode = MySettings.INS.getDarkThemeMode();
    if (mode.equals(getString(R.string.dark_theme_mode_light_val))) {
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
    } else if (mode.equals(getString(R.string.dark_theme_mode_dark_val))) {
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
    } else {
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
    }

    return wasNightMode != UiUtils.isNightMode(this);
  }

  public void setContentView(ViewBinding binding) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
      setContentView(binding.getRoot());
      return;
    }

    var cont = StatusBarBgContBinding.inflate(getLayoutInflater());
    setContentView(cont.getRoot());
    cont.getRoot().addView(binding.getRoot(), cont.getRoot().getLayoutParams());

    WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView())
        .setAppearanceLightStatusBars(!UiUtils.isNightMode(this));

    ViewCompat.setOnApplyWindowInsetsListener(
        cont.getRoot(),
        (v, insets) -> {
          var type = WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout();
          var ins = insets.getInsets(type);

          var mlp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
          mlp.leftMargin = ins.left;
          mlp.bottomMargin = ins.bottom;
          mlp.rightMargin = ins.right;

          ActionBar actionBar = getSupportActionBar();
          if (actionBar != null) {
            actionBar.setBackgroundDrawable(null);
            var lp = cont.statusBarBg.getLayoutParams();
            lp.height = ins.top;
            cont.statusBarBg.setLayoutParams(lp);
          } else {
            mlp.topMargin = ins.top;
          }

          v.setLayoutParams(mlp);

          return WindowInsetsCompat.CONSUMED;
        });
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/BottomSheetDialogFrag.java
================================================
package com.mirfatif.permissionmanagerx.base;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import androidx.fragment.app.FragmentActivity;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

public class BottomSheetDialogFrag extends BottomSheetDialogFragment {

  public FragmentActivity mA;

  public void onAttach(Context context) {
    super.onAttach(context);
    mA = getActivity();
  }

  public Dialog onCreateDialog(Bundle savedInstanceState) {
    BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
    dialog.setDismissWithAnimation(true);
    dialog.setOnShowListener(
        d -> {
          View view = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
          if (view != null) {
            BottomSheetBehavior.from(view).setState(BottomSheetBehavior.STATE_EXPANDED);
          }
        });
    return dialog;
  }

  public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    ((View) view.getParent()).setBackground(new DialogBg(true, mA));
  }

  public int getTheme() {
    return com.google.android.material.R.style.Theme_Design_BottomSheetDialog;
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/DialogBg.java
================================================
package com.mirfatif.permissionmanagerx.base;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.InsetDrawable;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public class DialogBg extends InsetDrawable {

  private static final int DP16_TO_PX = UiUtils.dpToPx(16);

  public DialogBg(Activity activity, boolean bordered) {
    super(
        createDrawable(activity, false, bordered),
        DP16_TO_PX / 2,
        DP16_TO_PX,
        DP16_TO_PX / 2,
        DP16_TO_PX);
  }

  public DialogBg(boolean isBottom, Activity activity) {
    super(
        createDrawable(activity, isBottom, false),
        isBottom ? 0 : DP16_TO_PX / 2,
        isBottom ? 0 : DP16_TO_PX,
        isBottom ? 0 : DP16_TO_PX / 2,
        isBottom ? 0 : DP16_TO_PX);
  }

  private static Drawable createDrawable(Activity activity, boolean isBottom, boolean bordered) {
    GradientDrawable d = new GradientDrawable();
    d.setShape(GradientDrawable.RECTANGLE);
    d.setColor(UiUtils.getBgColor(activity));
    if (isBottom) {
      float[] radii = new float[8];
      radii[0] = radii[1] = radii[2] = radii[3] = DP16_TO_PX;
      d.setCornerRadii(radii);
    } else {
      d.setCornerRadius(DP16_TO_PX);
      if (bordered) {
        d.setStroke(DP16_TO_PX / 8, UiUtils.getColor(activity, R.attr.accentColor));
      } else {
        d.setStroke(DP16_TO_PX / 8, UiUtils.getColor(activity, R.attr.accentTrans10Color));
      }
    }
    return d;
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/MyListAdapter.java
================================================
package com.mirfatif.permissionmanagerx.base;

import androidx.lifecycle.LifecycleOwner;
import androidx.recyclerview.widget.DiffUtil.ItemCallback;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import com.mirfatif.permissionmanagerx.util.bg.LiveSingleParamTask;
import com.mirfatif.permissionmanagerx.util.bg.LiveUiParamTask;
import com.mirfatif.privtasks.util.bg.NotifyWaiter;
import com.mirfatif.privtasks.util.bg.RateLimiter;
import java.util.List;
import java.util.concurrent.TimeUnit;

public abstract class MyListAdapter<T, VH extends RecyclerView.ViewHolder>
    extends ListAdapter<T, VH> {

  protected MyListAdapter(ItemCallback<T> diffCallback, LifecycleOwner owner, String tag) {
    super(diffCallback);
    mBgListSubmitter =
        new LiveSingleParamTask<>(owner, this::submitListAndWait, tag + "-ListSubmitter");
    mUiListSubmitter = new LiveUiParamTask<>(owner, this::submitListOnUi);
  }

  protected T getItem(int position) {
    try {
      return super.getItem(position);
    } catch (IndexOutOfBoundsException ignored) {
      return null;
    }
  }

  private final LiveSingleParamTask<List<T>> mBgListSubmitter;

  public synchronized void submitList(List<T> list) {
    mBgListSubmitter.cancelAndSubmit(list, false);
  }

  private final LiveUiParamTask<List<T>> mUiListSubmitter;

  private final NotifyWaiter mCommitWaiter = new NotifyWaiter(2, TimeUnit.SECONDS);

  private final RateLimiter mListSubmitLimiter = new RateLimiter(1, TimeUnit.SECONDS);

  private void submitListAndWait(List<T> list) {
    mUiListSubmitter.post(list, true);
    mCommitWaiter.waitForNotifyNoThrow();
    mListSubmitLimiter.waitUntilCanNoThrow(true);
  }

  private final Runnable mWaitEnder = () -> mCommitWaiter.notify(true);

  private void submitListOnUi(List<T> list) {
    super.submitList(list, mWaitEnder);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AboutActivityM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.app.AlertDialog;
import com.mirfatif.permissionmanagerx.about.AboutActivity;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.base.BaseActivity;

public class AboutActivityM extends BaseActivity {

  private final AboutActivity mA = new AboutActivity(this);

  protected void onCreated(Bundle savedInstanceState) {
    mA.onCreated();
  }

  public boolean onCreateOptionsMenu(Menu menu) {
    return mA.onCreateOptionsMenu(menu);
  }

  public boolean onPrepareOptionsMenu(Menu menu) {
    return mA.onPrepareOptionsMenu(menu);
  }

  public boolean onOptionsItemSelected(MenuItem item) {
    return mA.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
  }

  protected void onDestroy() {
    mA.onDestroy();
    super.onDestroy();
  }

  public AlertDialog createDialog(String tag, AlertDialogFragment dialogFragment) {
    AlertDialog d = mA.createDialog(tag, dialogFragment);
    return d != null ? d : super.createDialog(tag, dialogFragment);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AdbConnectSvcM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.mirfatif.permissionmanagerx.svc.AdbConnectSvc;

public class AdbConnectSvcM extends Service {

  private final AdbConnectSvc mS = new AdbConnectSvc(this);

  public IBinder onBind(Intent intent) {
    return null;
  }

  public int onStartCommand(Intent intent, int flags, int startId) {
    return mS.onStartCommand(intent);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AdvSettingsActivityM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.os.Bundle;
import com.mirfatif.permissionmanagerx.base.BaseActivity;
import com.mirfatif.permissionmanagerx.prefs.settings.AdvSettingsActivity;

public class AdvSettingsActivityM extends BaseActivity {

  public final AdvSettingsActivity mA;

  public AdvSettingsActivityM() {
    mA = new AdvSettingsActivity(this);
  }

  protected void onCreated(Bundle savedInstanceState) {
    mA.onCreate(savedInstanceState);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AppM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.app.Application;
import android.content.res.Configuration;
import com.mirfatif.permissionmanagerx.app.App;

public class AppM extends Application {

  private final App mA = new App(this);

  public void onCreate() {
    super.onCreate();
    mA.onCreate();
  }

  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(mA.onConfigurationChanged(newConfig));
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/CrashReportActivityM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.os.Bundle;
import com.mirfatif.permissionmanagerx.about.CrashReportActivity;
import com.mirfatif.permissionmanagerx.base.BaseActivity;

public class CrashReportActivityM extends BaseActivity {

  private final CrashReportActivity mA = new CrashReportActivity(this);

  protected void onCreated(Bundle savedInstanceState) {
    mA.onCreated();
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/CustomButton.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.app.Activity;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.RippleDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.appcompat.widget.AppCompatButton;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public class CustomButton extends AppCompatButton {

  private static final int DP4_TO_PX = UiUtils.dpToPx(4);

  public CustomButton(Context context, AttributeSet attrs) {
    super(context, attrs);

    GradientDrawable normalBg = new GradientDrawable();
    normalBg.setShape(GradientDrawable.RECTANGLE);
    normalBg.setColor(UiUtils.getDimBgColor((Activity) context));
    normalBg.setCornerRadius(DP4_TO_PX * 3f / 2);
    if (VERSION.SDK_INT >= VERSION_CODES.Q) {
      normalBg.setPadding(2 * DP4_TO_PX, DP4_TO_PX, 2 * DP4_TO_PX, DP4_TO_PX);
    }

    int rippleColor = context.getColor(R.color.colorControlNormalA50);
    ColorStateList colorStateList =
        new ColorStateList(new int[][] {new int[] {}}, new int[] {rippleColor});
    mRipple = new RippleDrawable(colorStateList, null, normalBg);
    mRipple.setPadding(2 * DP4_TO_PX, DP4_TO_PX, 2 * DP4_TO_PX, DP4_TO_PX);

    StateListDrawable d = new StateListDrawable();
    d.addState(new int[] {android.R.attr.state_pressed}, new InsetDrawable(mRipple, DP4_TO_PX));
    d.addState(new int[] {}, new InsetDrawable(normalBg, DP4_TO_PX));
    setBackground(d);
  }

  private final RippleDrawable mRipple;

  public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN && mRipple != null) {
      mRipple.setHotspot(event.getX(), event.getY());
    }
    return super.onTouchEvent(event);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/DaemonRcvSvcM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.mirfatif.permissionmanagerx.svc.DaemonRcvSvc;

public class DaemonRcvSvcM extends Service {

  private final DaemonRcvSvc mS = new DaemonRcvSvc(this);

  public IBinder onBind(Intent intent) {
    return null;
  }

  public int onStartCommand(Intent intent, int flags, int startId) {
    return mS.onStartCommand(intent);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/DialogHelpIcon.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import androidx.activity.ComponentActivity;
import androidx.appcompat.widget.AppCompatImageView;
import com.mirfatif.permissionmanagerx.util.bg.LiveTasksQueue;

public class DialogHelpIcon extends AppCompatImageView {

  public DialogHelpIcon(Context context, AttributeSet attrs) {
    super(context, attrs);

    post(
        () ->
            new LiveTasksQueue((ComponentActivity) context, 3000)
                .onUi(() -> setColorFilter(Color.RED))
                .delay(250)
                .onUi(() -> setColorFilter(Color.TRANSPARENT))
                .delay(250)
                .onUi(this::clearColorFilter)
                .delay(250)
                .onUi(() -> setColorFilter(Color.RED))
                .delay(250)
                .onUi(() -> setColorFilter(Color.TRANSPARENT))
                .delay(250)
                .onUi(this::clearColorFilter)
                .start());
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/FilterSettingsActivityM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.app.AlertDialog;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.base.BaseActivity;
import com.mirfatif.permissionmanagerx.prefs.settings.FilterSettingsActivity;

public class FilterSettingsActivityM extends BaseActivity {

  public final FilterSettingsActivity mA = new FilterSettingsActivity(this);

  protected void onCreated(Bundle savedInstanceState) {
    mA.onCreated(savedInstanceState);
  }

  public boolean onCreateOptionsMenu(Menu menu) {
    return mA.onCreateOptionsMenu(menu);
  }

  public boolean onPrepareOptionsMenu(Menu menu) {
    return mA.onPrepareOptionsMenu(menu);
  }

  public boolean onOptionsItemSelected(MenuItem item) {
    return mA.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
  }

  public AlertDialog createDialog(String tag, AlertDialogFragment dialogFragment) {
    AlertDialog d = mA.createDialog(tag);
    return d != null ? d : super.createDialog(tag, dialogFragment);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/HelpActivityM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import com.mirfatif.permissionmanagerx.base.BaseActivity;
import com.mirfatif.permissionmanagerx.help.HelpActivity;

public class HelpActivityM extends BaseActivity {

  private final HelpActivity mA = new HelpActivity(this);

  protected void onCreated(Bundle savedInstanceState) {
    mA.onCreated();
  }

  public boolean onCreateOptionsMenu(Menu menu) {
    return mA.onCreateOptionsMenu(menu);
  }

  public boolean onPrepareOptionsMenu(Menu menu) {
    return mA.onPrepareOptionsMenu(menu);
  }

  public boolean onOptionsItemSelected(MenuItem item) {
    return mA.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/LifecycleWatcher.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.Lifecycle.Event;
import androidx.lifecycle.Lifecycle.State;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
import com.mirfatif.permissionmanagerx.util.bg.LiveUiWaitTask;
import com.mirfatif.privtasks.util.bg.ThreadUtils;

public class LifecycleWatcher {

  public static LifecycleWatcher addOnDestroyed(LifecycleOwner owner, LifecycleCallback callback) {
    return new LifecycleWatcher(owner, callback);
  }

  private final LifecycleEventObserver mObserver = new Observer();
  private final LifecycleCallback mCallback;

  private LifecycleWatcher(LifecycleOwner owner, LifecycleCallback callback) {
    mCallback = callback;
    if (ThreadUtils.isMainThread()) {
      addObserver(owner.getLifecycle());
    } else {
      LiveUiWaitTask.post(() -> addObserver(owner.getLifecycle())).waitForMe();
    }
  }

  private void addObserver(Lifecycle lifecycle) {
    lifecycle.addObserver(mObserver);
    if (lifecycle.getCurrentState() == State.DESTROYED) {
      onDestroyed(lifecycle);
    }
  }

  private void onDestroyed(Lifecycle lifecycle) {
    mCallback.onDestroyed();
    lifecycle.removeObserver(mObserver);
  }

  private class Observer implements LifecycleEventObserver {

    public void onStateChanged(LifecycleOwner source, Event event) {
      if (event == Event.ON_DESTROY) {
        onDestroyed(source.getLifecycle());
      }
    }
  }

  public interface LifecycleCallback {

    void onDestroyed();
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/LogcatSvcM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.mirfatif.permissionmanagerx.svc.LogcatSvc;

public class LogcatSvcM extends Service {

  private final LogcatSvc mS = new LogcatSvc(this);

  public IBinder onBind(Intent intent) {
    return null;
  }

  public int onStartCommand(Intent intent, int flags, int startId) {
    return mS.onStartCommand(intent);
  }

  public void onDestroy() {
    mS.onDestroy();
    super.onDestroy();
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MainActivityM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.app.AlertDialog;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.base.BaseActivity;
import com.mirfatif.permissionmanagerx.main.MainActivity;

public class MainActivityM extends BaseActivity {

  public final MainActivity mA = new MainActivity(this);

  protected void onCreated(Bundle savedInstanceState) {
    mA.onCreated();
  }

  protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    mA.onNewIntent(intent);
  }

  public boolean onCreateOptionsMenu(Menu menu) {
    return mA.onCreateOptionsMenu(menu);
  }

  public boolean onPrepareOptionsMenu(Menu menu) {
    return false;
  }

  public boolean onOptionsItemSelected(MenuItem item) {
    return mA.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
  }

  protected void onResume() {
    super.onResume();
    mA.onResume();
  }

  protected void onPause() {
    super.onPause();
    mA.onPause();
  }

  public void onAttachedToWindow() {
    super.onAttachedToWindow();
    mA.onAttachedToWindow();
  }

  public AlertDialog createDialog(String tag, AlertDialogFragment dialogFragment) {
    AlertDialog d = mA.createDialog(tag, dialogFragment);
    return d != null ? d : super.createDialog(tag, dialogFragment);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MoveUpBehavior.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.view.View;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

public class MoveUpBehavior extends CoordinatorLayout.Behavior<View> {

  private final Class<?> mDependency;
  private final View mChild;

  public MoveUpBehavior(Class<?> dependency, View child) {
    mDependency = dependency;
    mChild = child;
  }

  public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
    return mDependency.isInstance(dependency);
  }

  public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {

    float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());

    mChild.animate().cancel();

    mChild.setTranslationY(translationY);
    return true;
  }

  public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {
    super.onDependentViewRemoved(parent, child, dependency);

    mChild.animate().translationY(0).start();
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyCoordinatorLayout.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Context;
import android.util.AttributeSet;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public class MyCoordinatorLayout extends CoordinatorLayout {

  public MyCoordinatorLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    UiUtils.onCreateLayout(this);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyDrawerLayout.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Context;
import android.util.AttributeSet;
import androidx.drawerlayout.widget.DrawerLayout;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public class MyDrawerLayout extends DrawerLayout {

  public MyDrawerLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    UiUtils.onCreateLayout(this);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyLinearLayout.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public class MyLinearLayout extends LinearLayout {

  public MyLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    UiUtils.onCreateLayout(this);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyNavigationView.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Context;
import android.util.AttributeSet;
import com.google.android.material.navigation.NavigationView;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public class MyNavigationView extends NavigationView {

  public MyNavigationView(Context context, AttributeSet attrs) {
    super(context, attrs);
    UiUtils.onCreateLayout(this);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MySearchView.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Context;
import androidx.appcompat.widget.SearchView;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public class MySearchView extends SearchView {

  public MySearchView(Context context) {
    super(context);
    UiUtils.onCreateLayout(this);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyWebView.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Context;
import android.util.AttributeSet;
import android.webkit.WebView;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public class MyWebView extends WebView {

  public MyWebView(Context context, AttributeSet attrs) {
    super(context, attrs);
    UiUtils.onCreateLayout(this);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/NumPickerPref.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import androidx.preference.DialogPreference;

public class NumPickerPref extends DialogPreference {

  public NumPickerPref(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  protected Object onGetDefaultValue(TypedArray a, int index) {
    return a.getInt(index, 0);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/PackageActivityM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.app.AlertDialog;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.base.BaseActivity;
import com.mirfatif.permissionmanagerx.pkg.PackageActivity;

public class PackageActivityM extends BaseActivity {

  public final PackageActivity mA = new PackageActivity(this);

  protected void onCreated(Bundle savedInstanceState) {
    mA.onCreated();
  }

  public boolean onCreateOptionsMenu(Menu menu) {
    return mA.onCreateOptionsMenu(menu);
  }

  public boolean onPrepareOptionsMenu(Menu menu) {
    return mA.onPrepareOptionsMenu(menu);
  }

  public boolean onOptionsItemSelected(MenuItem item) {
    return mA.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
  }

  protected void onResume() {
    super.onResume();
    mA.onResume();
  }

  public AlertDialog createDialog(String tag, AlertDialogFragment dialogFragment) {
    AlertDialog d = mA.createDialog(tag);
    return d != null ? d : super.createDialog(tag, dialogFragment);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/ProgressLinearLayout.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.content.Context;
import android.util.AttributeSet;

public class ProgressLinearLayout extends MyLinearLayout {

  public ProgressLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  private Runnable mVisibilityTask;
  private long mLastCall;

  public synchronized void setVisibility(int visibility) {
    removeCallbacks(mVisibilityTask);
    mVisibilityTask =
        () -> {
          mLastCall = System.currentTimeMillis();
          super.setVisibility(visibility);
        };
    long sleepTime = 1000 + mLastCall - System.currentTimeMillis();
    if (sleepTime > 10) {
      postDelayed(mVisibilityTask, sleepTime);
    } else {
      mVisibilityTask.run();
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/SettingsActivityM.java
================================================
package com.mirfatif.permissionmanagerx.fwk;

import android.os.Bundle;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import com.mirfatif.permissionmanagerx.base.BaseActivity;
import com.mirfatif.permissionmanagerx.prefs.settings.SettingsActivity;

public class SettingsActivityM extends BaseActivity
    implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {

  public final SettingsActivity mA = new SettingsActivity(this);

  protected void onCreated(Bundle savedInstanceState) {
    mA.onCreated(savedInstanceState);
  }

  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mA.onSaveInstanceState(outState);
  }

  public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
    return mA.onPreferenceStartFragment(pref);
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/help/HelpActivity.java
================================================
package com.mirfatif.permissionmanagerx.help;

import static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import androidx.activity.OnBackPressedCallback;
import androidx.webkit.WebViewClientCompat;
import androidx.webkit.WebViewCompat;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.about.AboutActivity;
import com.mirfatif.permissionmanagerx.app.App;
import com.mirfatif.permissionmanagerx.databinding.ActivityHelpBinding;
import com.mirfatif.permissionmanagerx.fwk.HelpActivityM;
import com.mirfatif.permissionmanagerx.prefs.MySettings;
import com.mirfatif.permissionmanagerx.util.ApiUtils;
import com.mirfatif.permissionmanagerx.util.LocaleUtils;
import com.mirfatif.permissionmanagerx.util.UiUtils;
import com.mirfatif.permissionmanagerx.util.bg.LiveTasksQueue;
import java.util.ArrayList;
import java.util.List;

public class HelpActivity extends OnBackPressedCallback {

  private final HelpActivityM mA;

  public HelpActivity(HelpActivityM activity) {
    super(true);
    mA = activity;
  }

  private static final String EXTRA_URL = HelpActivity.class.getName() + ".A";

  private WebSettings mWebSettings;
  private ActivityHelpBinding mB;
  private String mUrl;

  public void onCreated() {
    mUrl = mA.getIntent().getStringExtra(EXTRA_URL);

    // We've been launched in unexpected way (after rotation???)
    if (mUrl == null) {
      mA.finishAfterTransition();
    }

    mB = ActivityHelpBinding.inflate(mA.getLayoutInflater());

    App.setLocale();
    LocaleUtils.setLocale(mA.getBaseContext());

    mA.setContentView(mB);

    if (mA.getSupportActionBar() != null) {
      mA.getSupportActionBar().setTitle(R.string.help_menu_item);
    }

    mWebSettings = mB.webV.getSettings();

    mFontSize = MySettings.INS.getHelpFontSize();
    setFontSize();

    mWebSettings.setSupportZoom(false);
    mWebSettings.setBlockNetworkLoads(false);
    mWebSettings.setBlockNetworkImage(false);
    mWebSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
    mB.webV.setWebViewClient(new MyWebViewClient());

    enableJs();
    mB.webV.addJavascriptInterface(new HelpJsInterface(mA), "Android");

    if (MySettings.INS.shouldClearWebViewCache()) {
      mB.webV.clearCache(true);
    }

    mB.webV.loadUrl(mUrl);

    mB.refreshLayout.setOnRefreshListener(
        () -> {
          mB.webV.clearCache(true);
          mB.webV.reload();
        });

    mA.getOnBackPressedDispatcher().addCallback(mA, this);
  }

  public void handleOnBackPressed() {
    if (mB != null && mB.webV.canGoBack()) {
      mB.webV.goBack();
    } else {
      mA.finishAfterTransition();
    }
  }

  private void enableJs() {
    mWebSettings.setJavaScriptEnabled(true);
  }

  private int mFontSize;

  private void setFontSize() {
    mWebSettings.setDefaultFontSize(mFontSize);
    mB.webV.reload();
    if (mFontSize > MAX_FONT_SIZE - 2 || mFontSize < MIN_FONT_SIZE + 2) {
      mA.invalidateOptionsMenu();
    }
    MySettings.INS.setHelpFontSize(mFontSize);
  }

  public boolean onCreateOptionsMenu(Menu menu) {
    mA.getMenuInflater().inflate(R.menu.help_menu, menu);
    return true;
  }

  private static final int MAX_FONT_SIZE = 24;
  private static final int MIN_FONT_SIZE = 10;

  public boolean onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_zoom_in).setEnabled(mFontSize < MAX_FONT_SIZE);
    menu.findItem(R.id.action_zoom_out).setEnabled(mFontSize > MIN_FONT_SIZE);
    return true;
  }

  public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.action_open_browser) {
      ApiUtils.openWebUrl(mA, mUrl);
      mA.finishAfterTransition();
      return true;
    }
    if (item.getItemId() == R.id.action_zoom_in) {
      mFontSize++;
      setFontSize();
      return true;
    }
    if (item.getItemId() == R.id.action_zoom_out) {
      mFontSize--;
      setFontSize();
      return true;
    }
    if (item.getItemId() == android.R.id.home) {
      mA.finishAfterTransition();
      return true;
    }
    return false;
  }

  private static final String HELP_URL = getString(R.string.github_help_url);

  private boolean mFirstRun = true;

  private class MyWebViewClient extends WebViewClientCompat {

    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
      String url = request.getUrl().toString();
      if (url.equals(getString(R.string.contact_us_url))) {
        AboutActivity.start(mA);
        return true;
      }
      if (!url.startsWith(HELP_URL)) {
        ApiUtils.openWebUrl(mA, url);
        return true;
      }
      return super.shouldOverrideUrlLoading(view, request);
    }

    public void onPageFinished(WebView view, String url) {
      mB.refreshLayout.setRefreshing(false);

      if (mFirstRun && url.contains("#")) {
        String[] splitUrl = url.split("#");
        String id = splitUrl[splitUrl.length - 1];
        if (!TextUtils.isEmpty(id)) {
          String jsf = "function(){document.getElementById('" + id + "').scrollIntoView();}";
          new LiveTasksQueue(mA, 500)
              .onUi(() -> mB.webV.loadUrl("javascript:(" + jsf + ")()"))
              .start();
        }
      }
      mFirstRun = false;
    }
  }

  private static final List<String> WEB_VIEW_PKGS = new ArrayList<>();

  static {
    WEB_VIEW_PKGS.add("com.android.webview");
    WEB_VIEW_PKGS.add("com.google.android.webview");
    WEB_VIEW_PKGS.add("com.android.chrome");
  }

  public static void start(Activity activity, String href) {
    String url = HELP_URL + "/" + getString(R.string.help_dir_name) + "/";
    if (href != null) {
      url += "#" + href;
    }

    PackageInfo pkgInfo = WebViewCompat.getCurrentWebViewPackage(activity);
    if (pkgInfo == null) {
      UiUtils.showToast(R.string.no_web_view);
      ApiUtils.openWebUrl(activity, url);
      return;
    }

    if (WEB_VIEW_PKGS.contains(pkgInfo.packageName)) {
      try {
        int ver = Integer.parseInt(pkgInfo.versionName.split("\\.")[0]);
        if (ver < 73) {
          UiUtils.showToast(R.string.outdated_web_view);
          ApiUtils.openWebUrl(activity, url);
          return;
        }
      } catch (NumberFormatException ignored) {
      }
    }

    activity.startActivity(new Intent(activity, HelpActivityM.class).putExtra(EXTRA_URL, url));
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/help/HelpJsInterface.java
================================================
package com.mirfatif.permissionmanagerx.help;

import android.app.Activity;
import android.graphics.Color;
import android.webkit.JavascriptInterface;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.util.UiUtils;

public class HelpJsInterface {

  private final String mBgColor, mTextColor, mThemeColor;
  private final boolean mNightMode;

  HelpJsInterface(Activity act) {
    mBgColor = UiUtils.colorIntToRGB(UiUtils.getColor(act, android.R.attr.colorBackground), false);
    mTextColor = UiUtils.colorIntToRGB(UiUtils.isNightMode(act) ? Color.WHITE : Color.BLACK, false);
    mThemeColor = UiUtils.colorIntToRGB(UiUtils.getColor(act, R.attr.accentColor), false);
    mNightMode = UiUtils.isNightMode(act);
  }

  @JavascriptInterface
  public String getBgColor() {
    return mBgColor;
  }

  @JavascriptInterface
  public String getTextColor() {
    return mTextColor;
  }

  @JavascriptInterface
  public String getThemeColor() {
    return mThemeColor;
  }

  @JavascriptInterface
  public boolean isDarkTheme() {
    return mNightMode;
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/AdbConnectDialog.java
================================================
package com.mirfatif.permissionmanagerx.main;

import static com.mirfatif.permissionmanagerx.main.MainActivity.TAG_ADB_CONNECTION;
import static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;
import static java.lang.System.currentTimeMillis;

import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.SystemClock;
import android.system.Os;
import android.system.OsConstants;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.MutableLiveData;
import com.google.android.material.textfield.TextInputLayout;
import com.mirfatif.err.AdbException;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.app.App;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.databinding.AdbConnectDialogBinding;
import com.mirfatif.permissionmanagerx.databinding.DilogTitleWithHelpBinding;
import com.mirfatif.permissionmanagerx.fwk.LifecycleWatcher;
import com.mirfatif.permissionmanagerx.help.HelpActivity;
import com.mirfatif.permissionmanagerx.prefs.MySettings;
import com.mirfatif.permissionmanagerx.privs.AdbConnManager;
import com.mirfatif.permissionmanagerx.privs.DaemonStarter;
import com.mirfatif.permissionmanagerx.privs.NativeDaemon;
import com.mirfatif.permissionmanagerx.util.StringUtils;
import com.mirfatif.permissionmanagerx.util.UiUtils;
import com.mirfatif.permissionmanagerx.util.bg.LiveTasksQueueTyped;
import com.mirfatif.privtasks.util.MyLog;
import com.mirfatif.privtasks.util.NonBlockingReader;
import io.github.muntashirakon.adb.AdbPairingRequiredException;
import io.github.muntashirakon.adb.AdbStream;
import io.github.muntashirakon.adb.android.AdbMdns;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.lsposed.hiddenapibypass.HiddenApiBypass;

public class AdbConnectDialog {

  private static final String TAG = "AdbConnectDialog";

  private final MainActivity mA;
  private final AdbConnectDialogBinding mB;
  private final AlertDialogFragment mDialogFrag;

  public AdbConnectDialog(MainActivity activity, AlertDialogFragment dialogFragment) {
    mA = activity;
    mB = AdbConnectDialogBinding.inflate(mA.mA.getLayoutInflater());
    mB.connectIpV.setText(MySettings.INS.getAdbHost());
    mB.connectPortV.setText(String.valueOf(MySettings.INS.getAdbPort()));

    mDialogFrag = dialogFragment;
    LifecycleWatcher.addOnDestroyed(dialogFragment, this::stopMdnsPairingListener);

    connectToAdb(true);
  }

  private void onFirstTryFailed() {
    if (VERSION.SDK_INT >= VERSION_CODES.R) {
      mB.pairHelpV.setText(StringUtils.htmlToString(R.string.adb_pair_help_msg));

      mB.pairingIpV.setText(MySettings.INS.getAdbHost());
      mB.pairButton.setOnClickListener(v -> doPairing());

      mB.pairingCodeV.addTextChangedListener(new EditTextWatcher(mB.pairingCodeCont));
      mB.pairingIpV.addTextChangedListener(new EditTextWatcher(mB.pairingIpCont));
      mB.pairingPortV.addTextChangedListener(new EditTextWatcher(mB.pairingPortCont));

      mB.pairHeaderCont.setVisibility(View.VISIBLE);
      mB.divider.setVisibility(View.VISIBLE);
      mB.connectHeaderCont.setVisibility(View.VISIBLE);
      mB.pairArrow.setOnClickListener(v -> onArrowClicked(v, false));
      mB.connectArrow.setOnClickListener(v -> onArrowClicked(v, false));

      setAutoPairingHostPort();
    }

    mB.connectHelpV.setVisibility(View.VISIBLE);
    setConnectHelpText(false);

    mB.connectButton.setOnClickListener(v -> connectToAdb(false));

    mB.connectIpV.addTextChangedListener(new EditTextWatcher(mB.connectIpCont));
    mB.connectPortV.addTextChangedListener(new EditTextWatcher(mB.connectPortCont));
  }

  private final MutableLiveData<HostPort> mMdnsPairingEvent = new MutableLiveData<>();

  private static class HostPort {

    public final String host;
    public final int port;

    public HostPort(String host, int port) {
      this.host = host;
      this.port = port;
    }
  }

  private AdbMdns mMdnsPairingListener;

  private void setAutoPairingHostPort() {
    synchronized (mMdnsPairingEvent) {
      mMdnsPairingListener =
          new AdbMdns(
              App.getCxt(),
              AdbMdns.SERVICE_TYPE_TLS_PAIRING,
              (hostAddress, port) -> {
                String host = hostAddress == null ? null : hostAddress.getHostAddress();
                if (host != null && port > 0) {
                  mMdnsPairingEvent.postValue(new HostPort(host, port));
                }
              });
      mMdnsPairingListener.start();
    }

    mMdnsPairingEvent.observe(
        mDialogFrag,
        daemon -> {
          mB.pairingIpV.setText(daemon.host);
          mB.pairingPortV.setText(String.valueOf(daemon.port));
        });
  }

  private void stopMdnsPairingListener() {
    synchronized (mMdnsPairingEvent) {
      if (mMdnsPairingListener != null) {
        mMdnsPairingListener.stop();
        mMdnsPairingListener = null;
      }
    }
  }

  private void setConnectHelpText(boolean afterPairing) {
    int resId;
    if (VERSION.SDK_INT <= VERSION_CODES.Q) {
      resId = R.string.adb_connect_help_msg;
    } else if (afterPairing) {
      resId = R.string.adb_connect_help_after_pair_msg;
    } else {
      resId = R.string.adb_connect_help_11_msg;
    }
    mB.connectHelpV.setText(StringUtils.htmlToString(resId));
  }

  private void onArrowClicked(View arrow, boolean hideOnly) {
    View hideArrow = null, hideCont = null, showArrow, showCont;

    if (arrow == mB.pairArrow) {
      if (mB.pairCont.getVisibility() == View.GONE) {
        if (hideOnly) {
          return;
        }
        showArrow = arrow;
        showCont = mB.pairCont;
      } else {
        hideArrow = arrow;
        hideCont = mB.pairCont;
        showArrow = mB.connectArrow;
        showCont = mB.connectCont;
      }
    } else {
      if (mB.connectCont.getVisibility() == View.GONE) {
        if (hideOnly) {
          return;
        }
        showArrow = arrow;
        showCont = mB.connectCont;
      } else {
        hideArrow = arrow;
        hideCont = mB.connectCont;
        showArrow = mB.pairArrow;
        showCont = mB.pairCont;
      }
    }

    if (hideArrow != null) {
      hideArrow.setRotation(0);
      hideCont.setVisibility(View.GONE);
    }

    showArrow.setRotation(90);
    showCont.setVisibility(View.VISIBLE);
  }

  private long mShowTs;

  public AlertDialog createDialog() {
    int helpHrefRes;
    if (VERSION.SDK_INT <= VERSION_CODES.Q) {
      helpHrefRes = R.string.adb_connect_help_href_10;
    } else {
      helpHrefRes = R.string.adb_connect_help_href_11;
    }

    DilogTitleWithHelpBinding b = DilogTitleWithHelpBinding.inflate(mA.mA.getLayoutInflater());
    b.titleV.setText(R.string.adb_title);
    b.helpV.setOnClickListener(v -> HelpActivity.start(mA.mA, getString(helpHrefRes)));

    AlertDialog d = new Builder(mA.mA).setCustomTitle(b.getRoot()).setView(mB.getRoot()).create();
    d.setOnShowListener(dialog -> mShowTs = currentTimeMillis());
    return d;
  }

  private void doPairing() {
    CharSequence s = mB.pairingCodeV.getText();
    if (TextUtils.isEmpty(s)) {
      mB.pairingCodeCont.setError(getString(R.string.required_field_error));
      s = null;
    } else if ((s = s.toString().trim()).length() != 6) {
      s = null;
    }
    String code = s == null ? null : s.toString();

    String host = getHost(mB.pairingIpV.getText(), mB.pairingIpCont);
    int port = getPort(mB.pairingPortV.getText(), mB.pairingPortCont);

    if (code != null && host != null && port != 0) {
      mB.pairButton.setEnabled(false);
      mB.pairButton.setText(R.string.pairing_button);
      mB.pairingProg.setVisibility(View.VISIBLE);

      new LiveTasksQueueTyped<>(mDialogFrag, () -> doPairing(host, port, code))
          .onUiWith(this::onPairingComplete)
          .inBgWithFor(this::autoConnectAfterAutoPairing)
          .onUiWith(this::dismissDialog)
          .start();
    }
  }

  private static boolean mHiddenApiExempted = false;

  private boolean doPairing(String host, int port, String code) {
    if (!mHiddenApiExempted && VERSION.SDK_INT >= VERSION_CODES.P) {
      if (!HiddenApiBypass.addHiddenApiExemptions("Lcom/android/org/conscrypt/Conscrypt")) {
        MyLog.e(
            TAG, "doPairing", "Failed to access hidden class com.android.org.conscrypt.Conscrypt");
        return false;
      }
      mHiddenApiExempted = true;
    }

    try (AdbConnManager connMgr = new AdbConnManager()) {
      if (connMgr.pair(host, port, code)) {
        return true;
      } else {
        MyLog.e(TAG, "doPairing", "Adb pairing failed");
      }
    } catch (Exception e) {
      MyLog.e(TAG, "doPairing", e);
    }
    return false;
  }

  private void onPairingComplete(boolean result) {
    setConnectHelpText(result);

    if (result) {
      onArrowClicked(mB.pairArrow, true);
      mB.connectPortV.setText(null);
    } else {
      mB.pairButton.setEnabled(true);
      mB.pairButton.setText(R.string.pair_button);
      mB.pairingProg.setVisibility(View.INVISIBLE);
      UiUtils.showToast(R.string.adb_pairing_failed_toast);
    }
  }

  private boolean autoConnectAfterAutoPairing(boolean paired) {
    if (paired) {
      return connToAdbAndRestartDaemon(null, -1, false);
    }
    return false;
  }

  private void connectToAdb(boolean isFirstTry) {
    String host = getHost(mB.connectIpV.getText(), mB.connectIpCont);
    int port = getPort(mB.connectPortV.getText(), mB.connectPortCont);

    mB.connectButton.setEnabled(false);
    mB.connectButton.setText(R.string.connecting_button);
    mB.connectProg.setVisibility(View.VISIBLE);

    mA.setAdbCheckBox(false, false);

    new LiveTasksQueueTyped<>(mDialogFrag, () -> connToAdbAndRestartDaemon(host, port, !isFirstTry))
        .onUiWith(result -> onAdbConnect(result, isFirstTry))
        .start();
  }

  private boolean connToAdbAndRestartDaemon(String host, int port, boolean buttonPressed) {
    boolean retryAdbConnect = false;
    boolean onlyAutoConnect = host == null || port <= 0;

    if (!onlyAutoConnect) {
      if (buttonPressed
          && VERSION.SDK_INT >= VERSION_CODES.R
          && port != MySettings.INS.getAdbPort()) {
        try (AdbConnManager connMgr = new AdbConnManager()) {
          connMgr.setTimeout(10, TimeUnit.SECONDS);
          if (connMgr.connect(port)) {
            retryAdbConnect = callTcpIp(connMgr, port);
          } else {
            MyLog.e(TAG, "connToAdbAndRestartDaemon", "Adb connect for tcpip failed");
          }
        } catch (AdbException
            | InterruptedException
            | IOException
            | AdbPairingRequiredException e) {
          MyLog.e(TAG, "connToAdbAndRestartDaemon", e);
        }
      }

      MySettings.INS.setAdbHost(host);
      MySettings.INS.saveAdbPort(port);
    }

    boolean res;
    if (!buttonPressed || onlyAutoConnect) {
      res = NativeDaemon.getAdb(false, false, buttonPressed, host, port);
      SystemClock.sleep(mShowTs == 0 ? 1000 : Math.max(mShowTs + 1000 - currentTimeMillis(), 0));
    } else {
      res = NativeDaemon.forceGetAdb(retryAdbConnect);
    }

    if (res) {
      DaemonStarter.INS.switchToRootOrAdbDaemon(false);
    }

    return res;
  }

  private boolean callTcpIp(AdbConnManager connMgr, int port) {
    try (AdbStream adbStream = connMgr.openStream("tcpip:" + port)) {
      waitForTcpIpResponse(adbStream);
      return true;
    } catch (IOException | InterruptedException e) {
      MyLog.e(TAG, "callTcpIp", e);
      return false;
    }
  }

  private void waitForTcpIpResponse(AdbStream adbStream) {
    NonBlockingReader reader = new NonBlockingReader(adbStream.openInputStream());
    try {
      String line = reader.readLine(2000);
      if (line != null) {
        MyLog.i(TAG, "waitForTcpIpResponse", line);
      }
    } catch (IOException | InterruptedException e) {
      MyLog.e(TAG, "waitForTcpIpResponse", e);
    }
  }

  private void onAdbConnect(boolean result, boolean isFirstTry) {
    boolean dismissed = false;

    if (result) {
      dismissed = dismissDialog(true);
    } else if (isFirstTry) {
      onFirstTryFailed();
    } else {
      UiUtils.showToast(R.string.adb_connect_failed_toast);
    }

    if (!dismissed) {
      mB.connectButton.setEnabled(true);
      mB.connectButton.setText(R.string.connect_button);
      mB.connectProg.setVisibility(View.INVISIBLE);
    }
  }

  private boolean dismissDialog(boolean result) {
    boolean dismissed = false;
    if (result) {
      FragmentManager fm = mA.mA.getSupportFragmentManager();
      Fragment frag = fm.findFragmentByTag(TAG_ADB_CONNECTION);
      if (frag != null) {
        fm.beginTransaction().remove(frag).commitNowAllowingStateLoss();
        dismissed = true;
      }
      mA.showSnackBar(getString(R.string.connected_to_adb_toast), 5);
    }
    mA.setAdbCheckBox(result, true);
    return dismissed;
  }

  public static final int MIN_PORT = 1;
  public static final int MAX_PORT = 65535;

  private static int getPort(CharSequence portStr, TextInputLayout container) {
    if (!TextUtils.isEmpty(portStr)) {
      int port;
      try {
        port = Integer.parseInt(portStr.toString().trim());
      } catch (NumberFormatException ignored) {
        port = -1;
      }
      if (port <= MAX_PORT && port >= MIN_PORT) {
        return port;
      }
      container.setError(getString(R.string.invalid_field_error));
    } else {
      container.setError(getString(R.string.required_field_error));
    }
    return 0;
  }

  private static String getHost(CharSequence ipStr, TextInputLayout container) {
    if (!TextUtils.isEmpty(ipStr)) {
      String host = ipStr.toString().trim();
      if (Os.inet_pton(OsConstants.AF_INET, host) != null) {
        return host;
      }
      container.setError(getString(R.string.invalid_field_error));
    } else {
      container.setError(getString(R.string.required_field_error));
    }
    return null;
  }

  private static class EditTextWatcher implements TextWatcher {

    private final TextInputLayout mCont;

    private EditTextWatcher(TextInputLayout container) {
      mCont = container;
    }

    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    public void onTextChanged(CharSequence s, int start, int before, int count) {
      mCont.setErrorEnabled(false);
    }

    public void afterTextChanged(Editable s) {}
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/BackupRestoreDialog.java
================================================
package com.mirfatif.permissionmanagerx.main;

import static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;

import android.net.Uri;
import android.view.View;
import android.widget.CheckBox;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AlertDialog.Builder;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.backup.BackupFileSelector;
import com.mirfatif.permissionmanagerx.backup.BackupRestore;
import com.mirfatif.permissionmanagerx.backup.BackupRestore.Result;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.databinding.BackupRestoreDialogBinding;
import com.mirfatif.permissionmanagerx.databinding.ProgressDialogBinding;
import com.mirfatif.permissionmanagerx.util.ApiUtils;
import com.mirfatif.permissionmanagerx.util.StringUtils;
import com.mirfatif.permissionmanagerx.util.bg.LiveTasksQueueTyped;
import com.mirfatif.privtasks.util.MyLog;
import java.util.Objects;

public class BackupRestoreDialog {

  private static final String TAG = "BackupRestoreDialog";

  private final MainActivity mA;

  public BackupRestoreDialog(MainActivity activity) {
    mA = activity;
  }

  private BackupFileSelector mBackupLauncher;
  private BackupFileSelector mRestoreLauncher;

  public void onCreated() {
    mBackupLauncher = new BackupFileSelector(mA.mA, true, uri -> doBackupRestore(true, uri));
    mRestoreLauncher = new BackupFileSelector(mA.mA, false, uri -> doBackupRestore(false, uri));
  }

  private boolean mSkipUninstalledApps = false;

  public AlertDialog createDialog() {
    BackupRestoreDialogBinding b = BackupRestoreDialogBinding.inflate(mA.mA.getLayoutInflater());

    CheckBox cb = b.skipUninstalledPackages;
    cb.setChecked(mSkipUninstalledApps);
    cb.setOnClickListener(v -> mSkipUninstalledApps = cb.isChecked());

    return new Builder(mA.mA)
        .setPositiveButton(R.string.backup, (d, w) -> mBackupLauncher.launch())
        .setNegativeButton(R.string.restore, (d, w) -> mRestoreLauncher.launch())
        .setTitle(getString(R.string.backup) + " / " + getString(R.string.restore))
        .setView(b.getRoot())
        .create();
  }

  private void doBackupRestore(boolean isBackup, Uri uri) {
    if (uri == null) {
      return;
    }

    ProgressDialogBinding b = ProgressDialogBinding.inflate(mA.mA.getLayoutInflater());
    b.progText.setText(isBackup ? R.string.backup_in_progress : R.string.restore_in_progress);

    AlertDialog dialog =
        new Builder(mA.mA)
            .setTitle(isBackup ? R.string.backup : R.string.restore)
            .setPositiveButton(android.R.string.ok, null)
            .setView(b.getRoot())
            .create();

    AlertDialogFragment dialogFrag = AlertDialogFragment.create(dialog, "BACKUP_RESTORE");
    dialogFrag.setCancelable(false);

    dialog.setOnShowListener(
        d -> {
          dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);

          new LiveTasksQueueTyped<>(
                  mA.mA,
                  () -> {
                    if (isBackup) {
                      return BackupRestore.INS.backupNoThrow(uri, true, mSkipUninstalledApps);
                    } else {
                      return BackupRestore.INS.restore(uri, mSkipUninstalledApps);
                    }
                  })
              .onUiWith(result -> handleResult(isBackup, result, b, dialogFrag))
              .start();
        });

    dialogFrag.show(mA.mA);
  }

  private void handleResult(
      boolean isBackup, Result res, ProgressDialogBinding b, AlertDialogFragment dialog) {
    b.prog.setVisibility(View.GONE);
    Objects.requireNonNull(dialog.getDialog())
        .getButton(AlertDialog.BUTTON_POSITIVE)
        .setEnabled(true);
    dialog.setCancelable(true);

    if (res == null) {
      MyLog.e(TAG, "handleResult", (isBackup ? "Backup" : "Restore") + " failed");
      b.progText.setText(R.string.backup_restore_failed);
    } else {
      String message =
          ApiUtils.getQtyString(R.plurals.backup_restore_processed_prefs, res.prefs, res.prefs);

      if (res.profiles >= 0) {
        message =
            ApiUtils.getQtyString(
                R.plurals.backup_restore_processed_profiles, res.profiles, message, res.profiles);
      }

      message =
          ApiUtils.getQtyString(
              R.plurals.backup_restore_processed_refs, res.perms, message, res.perms);

      if (res.invalidPrefs > 0) {
        message =
            ApiUtils.getQtyString(
                R.plurals.backup_restore_invalid_prefs,
                res.invalidPrefs,
                message,
                res.invalidPrefs);
      }

      if (res.skippedApps > 0) {
        message =
            ApiUtils.getQtyString(
                R.plurals.backup_restore_uninstalled_apps,
                res.skippedApps,
                message,
                res.skippedApps);
      }

      b.progText.setText(StringUtils.breakParas(message));
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/DaemonStartProg.java
================================================
package com.mirfatif.permissionmanagerx.main;

import static com.mirfatif.permissionmanagerx.main.MainActivity.ACTION_SHOW_DRAWER;
import static com.mirfatif.permissionmanagerx.main.MainActivity.TAG_GRANT_ROOT_OR_ADB;
import static com.mirfatif.permissionmanagerx.main.MainActivity.TAG_PRIVS_REQ_FOR_DAEMON;
import static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;

import androidx.appcompat.app.AlertDialog;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.parser.PackageParser;
import com.mirfatif.permissionmanagerx.prefs.MySettings;
import com.mirfatif.permissionmanagerx.privs.DaemonStarter;
import com.mirfatif.permissionmanagerx.util.Utils;
import com.mirfatif.permissionmanagerx.util.bg.LiveSchedTask;
import java.util.concurrent.TimeUnit;

public class DaemonStartProg {

  private static final String TAG = "DaemonStartProg";

  private final MainActivity mA;

  DaemonStartProg(MainActivity activity) {
    mA = activity;
  }

  void onCreated(String intentAction) {
    DaemonStarter.INS.getLiveProg().observe(mA.mA, this::setDaemonStartProg);
    DaemonStarter.INS.getLiveStartResult().observe(mA.mA, this::handleStartDaemonResult);

    if (MySettings.INS.getShowUnsupportedSdkWarning()) {
      AlertDialog dialog =
          new AlertDialog.Builder(mA.mA)
              .setTitle(R.string.unsupported_sdk_warning_title)
              .setMessage(
                  getString(R.string.unsupported_sdk_warning_message, Utils.getAndroidVersionInt()))
              .setPositiveButton(
                  R.string.unsupported_sdk_warning_button,
                  (d, w) -> MySettings.INS.onUnsupportedSdkWarningShown())
              .create();

      AlertDialogFragment frag = AlertDialogFragment.create(dialog, "UNSUPPORTED_SDK_WARNING");
      frag.setOnDismissListener(d -> startDaemon(intentAction));

      LiveSchedTask.schedule(
          mA.mA,
          () -> frag.show(mA.mA),
          500,
          TimeUnit.MILLISECONDS,
          true,
          TAG + "-SdkWarningDialog");
    } else {
      startDaemon(intentAction);
    }
  }

  private void startDaemon(String intentAction) {
    DaemonStarter.INS.startPrivDaemon(false, true, true, !ACTION_SHOW_DRAWER.equals(intentAction));
  }

  private void setDaemonStartProg(String prog) {
    if (prog != null) {
      mA.mB.bigProgText.setText(prog);
      mA.setBigProgVisible(true);
    } else {
      mA.setBigProgVisible(false);
    }
  }

  private void handleStartDaemonResult(DaemonStarter.DaemonStartResult res) {
    if (res.daemonStarted == DaemonStarter.DaemonStartStatus.NO_PRIVS) {

      if (res.showNoPrivsDialog) {
        if (!res.isFirstRun) {
          AlertDialogFragment.show(mA.mA, null, TAG_GRANT_ROOT_OR_ADB);
        } else if (MySettings.INS.shouldRemindMissingPrivileges()) {
          LiveSchedTask.schedule(
              mA.mA,
              () -> AlertDialogFragment.show(mA.mA, null, TAG_PRIVS_REQ_FOR_DAEMON),
              1,
              TimeUnit.SECONDS,
              true,
              TAG + "-NoPrivsDialog");
        }
      }
    }

    if (res.isFirstRun) {
      mA.setLiveDataObservers();
    } else if (res.wasAlive || res.daemonStarted == DaemonStarter.DaemonStartStatus.STARTED) {
      PackageParser.INS.updatePkgList();
    } else {
      mA.setBigProgVisible(false);
    }

    if (res.daemonStarted == DaemonStarter.DaemonStartStatus.FAILED) {
      mA.showSnackBar(getString(R.string.daemon_failed_toast), 10);
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/Feedback.java
================================================
package com.mirfatif.permissionmanagerx.main;

import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import androidx.coordinatorlayout.widget.CoordinatorLayout.LayoutParams;
import com.google.android.material.behavior.SwipeDismissBehavior;
import com.google.android.material.behavior.SwipeDismissBehavior.OnDismissListener;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.main.FeedbackDialogFrag.FeedbackType;
import com.mirfatif.permissionmanagerx.prefs.MySettings;

class Feedback {

  private final MainActivity mA;

  Feedback(MainActivity activity) {
    mA = activity;
  }

  private boolean mFeedbackSwiped = false;

  void askForFeedback() {
    if (mA.mB == null) {
      return;
    }

    if (!mFeedbackSwiped && MySettings.INS.shouldAskForFeedback()) {
      mA.mB.movCont.feedbackCont.setVisibility(View.VISIBLE);
      MySettings.INS.setAskForFeedbackTs(false);
    }

    if (mA.mB.movCont.feedbackCont.getVisibility() != View.VISIBLE) {
      return;
    }

    mA.mB.movCont.likingAppYesButton.setOnClickListener(v -> showDialog(true));
    mA.mB.movCont.likingAppNoButton.setOnClickListener(v -> showDialog(false));

    SwipeDismissBehavior<View> dismissBehavior = new SwipeDismissBehavior<>();
    dismissBehavior.setListener(new FeedbackDismissListener());
    ((LayoutParams) mA.mB.movCont.feedbackCont.getLayoutParams()).setBehavior(dismissBehavior);

    Animation anim = AnimationUtils.loadAnimation(mA.mA, R.anim.shake);
    mA.mB.movCont.feedbackCont.postDelayed(
        () -> mA.mB.movCont.feedbackCont.startAnimation(anim), 1000);
  }

  private void showDialog(boolean isYes) {
    int type = isYes ? FeedbackType.POSITIVE : FeedbackType.NEGATIVE;
    FeedbackDialogFrag.show(type, mA.mA.getSupportFragmentManager());
    mA.mB.movCont.feedbackCont.setVisibility(View.GONE);
  }

  private class FeedbackDismissListener implements OnDismissListener {

    public void onDismiss(View view) {
      mA.mB.movCont.feedbackCont.setVisibility(View.GONE);
      mFeedbackSwiped = true;
    }

    public void onDragStateChanged(int state) {}
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/FeedbackDialogFrag.java
================================================
package com.mirfatif.permissionmanagerx.main;

import static com.mirfatif.permissionmanagerx.util.ApiUtils.openWebUrl;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import androidx.fragment.app.FragmentManager;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.about.AboutActivity;
import com.mirfatif.permissionmanagerx.base.BottomSheetDialogFrag;
import com.mirfatif.permissionmanagerx.databinding.FeedbackDialogBinding;
import com.mirfatif.permissionmanagerx.databinding.RateDonateDialogBinding;
import com.mirfatif.permissionmanagerx.help.HelpActivity;
import com.mirfatif.permissionmanagerx.prefs.MySettings;
import com.mirfatif.permissionmanagerx.util.ApiUtils;
import com.mirfatif.permissionmanagerx.util.UiUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class FeedbackDialogFrag extends BottomSheetDialogFrag {

  private static final String FEEDBACK_TYPE = "FEEDBACK_TYPE";

  @Retention(RetentionPolicy.SOURCE)
  public @interface FeedbackType {
    int POSITIVE = 0;
    int NEGATIVE = 1;
    int RATE = 2;
    int RATE_DONATE = 3;
    int CONTACT = 4;
  }

  public static void show(int type, FragmentManager fm) {
    FeedbackDialogFrag frag = new FeedbackDialogFrag();
    Bundle args = new Bundle();
    args.putInt(FEEDBACK_TYPE, type);
    frag.setArguments(args);
    frag.show(fm, "FEEDBACK_RATING");
  }

  public View onCreateView(
      LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    int type = requireArguments().getInt(FEEDBACK_TYPE);
    if (type == FeedbackType.POSITIVE) {
      return getFeedbackView(true);
    }
    if (type == FeedbackType.NEGATIVE) {
      return getFeedbackView(false);
    }
    return getButtonsView(type);
  }

  private View getFeedbackView(boolean isYes) {
    FeedbackDialogBinding b = FeedbackDialogBinding.inflate(mA.getLayoutInflater());
    int msgResId, buttonResId;

    if (isYes) {
      msgResId = R.string.purchase_and_rate_the_app;
      buttonResId = R.string.how_do_i;
    } else {
      msgResId = R.string.ask_to_provide_feedback;
      buttonResId = R.string.contact;
    }

    b.msgV.setText(msgResId);
    b.posButton.setText(buttonResId);

    b.neutralButton.setOnClickListener(
        v -> {
          MySettings.INS.setAskForFeedbackTs(true);
          dismissAllowingStateLoss();
        });

    b.negButton.setOnClickListener(v -> dismissAllowingStateLoss());

    b.posButton.setOnClickListener(
        v -> {
          int type = isYes ? FeedbackType.RATE_DONATE : FeedbackType.CONTACT;
          FeedbackDialogFrag.show(type, mA.getSupportFragmentManager());
          dismissAllowingStateLoss();
        });

    return b.getRoot();
  }

  private View getButtonsView(int type) {
    int b1 = 0, b2, b3 = 0;
    ButtonListener l1 = null, l2, l3 = null;

    RateDonateDialogBinding b = RateDonateDialogBinding.inflate(mA.getLayoutInflater());

    if (type == FeedbackType.CONTACT) {
      b1 = R.string.contact_on_telegram;
      l1 = new ButtonListener(() -> openWebUrl(mA, ApiUtils.getString(R.string.telegram_mirfatif)));
      b2 = R.string.contact_on_email;
      l2 = new ButtonListener(() -> ApiUtils.sendMail(mA, null));

    } else {
      b2 = R.string.rating_options;

      if (type == FeedbackType.RATE) {
        b1 = R.string.rate_on_ps;
        l1 = new ButtonListener(() -> openWebUrl(mA, getString(R.string.play_store_url)));

        b2 = R.string.other_rating_options;

      } else if (type == FeedbackType.RATE_DONATE) {
        b1 = R.string.purchase_donate;
        l1 =
            new ButtonListener(() -> ApiUtils.openWebUrl(mA, getString(R.string.purchase_pro_url)));
      }

      l2 =
          new ButtonListener(
              () -> HelpActivity.start(mA, getString(R.string.rate_review_help_href)));

      if (type == FeedbackType.RATE_DONATE) {
        b3 = R.string.share_with_others;
        l3 = new ButtonListener(() -> AboutActivity.sendShareIntent(mA));
      }
    }

    if (l1 != null) {
      b.button1.setText(b1);
      b.button1.setOnClickListener(l1);
    } else {
      b.button1.setVisibility(View.GONE);
    }

    b.button2.setText(b2);
    b.button2.setOnClickListener(l2);

    if (l3 != null) {
      b.button3.setText(b3);
      b.button3.setOnClickListener(l3);
    } else {
      b.button3.setVisibility(View.GONE);
    }

    return b.getRoot();
  }

  private class ButtonListener implements OnClickListener {

    private final Runnable mTask;

    private ButtonListener(Runnable task) {
      mTask = task;
    }

    public void onClick(View v) {
      mTask.run();
      UiUtils.showToast(R.string.thank_you);
      dismissAllowingStateLoss();
    }
  }
}


================================================
FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/MainActivity.java
================================================
package com.mirfatif.permissionmanagerx.main;

import static com.mirfatif.permissionmanagerx.util.ApiUtils.getQtyString;
import static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;

import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import androidx.activity.OnBackPressedCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.SearchView.OnQueryTextListener;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.view.GravityCompat;
import androidx.core.view.MenuCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.material.snackbar.Snackbar;
import com.mirfatif.permissionmanagerx.R;
import com.mirfatif.permissionmanagerx.about.AboutActivity;
import com.mirfatif.permissionmanagerx.app.App;
import com.mirfatif.permissionmanagerx.base.AlertDialogFragment;
import com.mirfatif.permissionmanagerx.databinding.ActivityMainBinding;
import com.mirfatif.permissionmanagerx.databinding.DilogTitleWithHelpBinding;
import com.mirfatif.permissionmanagerx.fwk.AdvSettingsActivityM;
import com.mirfatif.permissionmanagerx.fwk.FilterSettingsActivityM;
import com.mirfatif.permissionmanagerx.fwk.LifecycleWatcher;
import com.mirfatif.permissionmanagerx.fwk.MainActivityM;
import com.mirfatif.permissionmanagerx.fwk.MoveUpBehavior;
import com.mirfatif.permissionmanagerx.fwk.SettingsActivityM;
import com.mirfatif.permissionmanagerx.help.HelpActivity;
import com.mirfatif.permissionmanagerx.main.PackageAdapter.PkgAdapterCallback;
import com.mirfatif.permissionmanagerx.parser.AppOpsParser;
import com.mirfatif.permissionmanagerx.parser.Package;
import com.mirfatif.permissionmanagerx.parser.PackageParser;
import com.mirfatif.permissionmanagerx.pkg.PackageActivity;
import com.mirfatif.permissionmanagerx.prefs.AppUpdate;
import com.mirfatif.permissionmanagerx.prefs.MySettings;
import com.mirfatif.permissionmanagerx.prefs.settings.SearchSettingsFrag;
import com.mirfatif.permissionmanagerx.privs.DaemonHandler;
import com.mirfatif.permissionmanagerx.privs.DaemonStarter;
import com.mirfatif.permissionmanagerx.privs.NativeDaemon;
import com.mirfatif.permissionmanagerx.util.ApiUtils;
import com.mirfatif.permissionmanagerx.util.LocaleUtils;
import com.mirfatif.permissionmanagerx.util.NotifUtils;
import com.mirfatif.permissionmanagerx.util.UiUtils;
import com.mirfatif.permissionmanagerx.util.UserUtils;
import com.mirfatif.permissionmanagerx.util.bg.LiveMinDelayParamTask;
import com.mirfatif.permissionmanagerx.util.bg.LiveSchedParamTask;
import com.mirfatif.permissionmanagerx.util.bg.LiveSchedTask;
import com.mirfatif.permissionmanagerx.util.bg.LiveTasksQueue;
import com.mirfatif.permissionmanagerx.util.bg.LiveTasksQueueTyped;
import com.mirfatif.privtasks.util.bg.BgRunner;
import com.mirfatif.privtasks.util.bg.NotifyWaiter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class MainActivity extends OnBackPressedCallback {

  private static final String TAG = "MainActivity";

  public final MainActivityM mA;

  public MainActivity(MainActivityM activity) {
    super(true);
    mA = activity;

    mPkgCountNotifier =
        new LiveSchedParamTask<>(
            mA, this::showPkgCount, 500, TimeUnit.MILLISECONDS, true, TAG + "-PkgCountNotifier");

    mBigProgHider =
        new LiveMinDelayParamTask<>(
            mA,
            visibility -> mB.bigProgCont.setVisibility(visibility),
            1,
            TimeUnit.SECONDS,
            true,
            TAG + "-BigProgHider");

    mWindowWaiter = new NotifyWaiter(() -> mA.getWindow() == null);
  }

  private static final String CLASS = MainActivity.class.getName();
  public static final String ACTION_SHOW_DRAWER = CLASS + ".action.SHOW_DRAWER";

  public final DaemonStartProg mDaemonStartProg = new DaemonStartProg(this);
  private final Feedback mFeedback = new Feedback(this);
  private final BackupRestoreDialog mBackupRestoreDialog = new BackupRestoreDialog(this);
  private final PrivsCheckBoxFocus mCheckBoxFocus = new PrivsCheckBoxFocus(this);

  private ActivityResultLauncher<String> mNotifPermReqLauncher;

  ActivityMainBinding mB;

  private LinearLayoutManager mLayoutManager;
  public SearchView mSearchView;
  private PackageAdapter mPkgAdapter;

  ActionBarDrawerToggle mDrawerToggle;

  private final Class<?> mSnackBarLayoutCls = Snackbar.SnackbarLayout.class;

  public void onCreated() {
    if (isSecondaryUser()) {
      return;
    }

    mB = ActivityMainBinding.inflate(mA.getLayoutInflater());
    mB.movCont.setData(new Data());
    mA.setContentView(mB);

    ((CoordinatorLayout.LayoutParams) mB.moveUpCont.getLayoutParams())
        .setBehavior(new MoveUpBehavior(mSnackBarLayoutCls, mB.movCont.getRoot()));

    mB.bigProgCont.setOnClickListener(null);

    ActionBar actionBar = mA.getSupportActionBar();
    if (actionBar != null) {
      actionBar.setDisplayHomeAsUpEnabled(true);
    }

    mDrawerToggle =
        new ActionBarDrawerToggle(mA, mB.getRoot(), R.string.open_drawer, R.string.close_drawer);
    mB.getRoot().addDrawerListener(mDrawerToggle);
    mDrawerToggle.syncState();

    handleIntentActions(mA.getIntent());

    mB.navV.setNavigationItemSelectedListener(this::handleNavigationItemSelected);
    setNavigationMenu();

    MySettings.INS.mPrefsWatcher.observe(mA, this::onPrefChanged);

    mB.refreshLayout.setOnRefreshListener(
        () -> {
          if (MySettings.INS.isSearching()) {
            handleSearchQuery();
          } else {
            PackageParser.INS.updatePkgList();
          }
        });

    mPkgAdapter = new PackageAdapter(mA, new PkgAdapterCallbackImpl());

    mB.recyclerView.setAdapter(mPkgAdapter);

    mLayoutManager = new LinearLayoutManager(mA, LinearLayoutManager.VERTICAL, false);
    mB.recyclerView.setLayoutManager(mLayoutManager);

    mB.recyclerView.addItemDecoration(new DividerItemDecoration(mA, LinearLayoutManager.VERTICAL));

    mB.recyclerView.setOnScrollChangeListener(
        (v, scrollX, scrollY, oldScrollX, oldScrollY) -> setRepeatUpdates());

    if (mSearchView != null) {
      collapseSearchView();
    } else {
      MySettings.INS.setQueryText(null);
    }

    mB.searchSettingsContainer.setOnClickListener(v -> hideSearchSettings());

    String action = mA.getIntent().getAction();

    if (Intent.ACTION_MAIN.equals(action)) {
      BgRunner.execute(MySettings.INS::plusAppLaunchCount);
    }

    mNotifPermReqLauncher =
        mA.registerForActivityResult(
            new ActivityResultContracts.RequestPermission(), granted -> {});

    mDaemonStartProg.onCreated(action);
    mBackupRestoreDialog.onCreated();

    if (ApiUtils.hasNotifPerm()) {
      BgRunner.execute(() -> AppUpdate.check(true));
    }

    mA.getOnBackPressedDispatcher().addCallback(mA, this);
  }

  public void onNewIntent(Intent intent) {
    handleIntentActions(intent);
  }

  public boolean onCreateOptionsMenu(Menu menu) {
    if (UserUtils.getUserId() != 0) {
      return false;
    }

    mA.getMenuInflater().inflate(R.menu.main_search, menu);
    MenuCompat.setGroupDividerEnabled(menu, true);

    MenuItem searchMenuItem = menu.findItem(R.id.action_search);
    mSearchView = (SearchView) searchMenuItem.getActionView();
    setUpSearchView();

    return true;
  }

  public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == android.R.id.home) {
      if (!mSearchView.isIconified()) {
        if (mB.searchSettingsContainer.getVisibility() == View.VISIBLE) {
          hideSearchSettings();
        } else {
          mB.searchSettingsContainer.setVisibility(View.VISIBLE);
          mA.getSupportFragmentManager()
              .beginTransaction()
              .replace(R.id.search_settings_frag, new SearchSettingsFrag())
              .commit();
        }
        return true;
      }
    }

    return mDrawerToggle.onOptionsItemSelected(item);
  }

  public void handleOnBackPressed() {
    mCheckBoxFocus.endFocus();

    if (mB != null && mB.getRoot().isDrawerOpen(GravityCompat.START)) {
      mB.getRoot().closeDrawer(GravityCompat.START, true);
      return;
    }

    if (mSearchView != null && !TextUtils.isEmpty(mSearchView.getQuery())) {
      collapseSearchView();
      return;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
      mExited = true;
    }

    mA.finishAfterTransition();
  }

  private boolean mExited = false;

  public void onResume() {
    mFeedback.askForFeedback();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && mExited) {
      PackageParser.INS.updatePkgList();
    }
    mExited = false;
  }

  public void onPause() {
    mCheckBoxFocus.endFocus();
  }

  public void onAttachedToWindow() {
    mWindowWaiter.notify(true);
  }

  public static final String TAG_PRIVS_REQ_FOR_DAEMON = CLASS + ".PRIVS_REQ_FOR_DAEMON";
  public static final String TAG_GRANT_ROOT_OR_ADB = CLASS + ".GRANT_ROOT_OR_ADB";
  public static final String TAG_ADB_CONNECTION = CLASS + ".TAG_ADB_CONNECTION";
  private static final String TAG_BACKUP_RESTORE = CLASS + ".TAG_BACKUP_RESTORE";

  public AlertDialog createDialog(String tag, AlertDialogFragment dialogFragment) {
    if (TAG_PRIVS_REQ_FOR_DAEMON.equals(tag) || TAG_GRANT_ROOT_OR_ADB.equals(tag)) {
      DilogTitleWithHelpBinding b = DilogTitleWithHelpBinding.inflate(mA.getLayoutInflater());
      b.titleV.setText(R.string.privileges_title);
      b.helpV.setOnClickListener(v -> HelpActivity.start(mA, "faq1"));

      Builder builder =
          new Builder(mA)
              .setPositiveButton(android.R.string.ok, (d, w) -> openDrawerForPrivileges())
              .setCustomTitle(b.getRoot())
              .setMessage(getString(R.string.grant_root_or_adb));
      if (TAG_GRANT_ROOT_OR_ADB.equals(tag)) {
        builder.setNegativeButton(android.R.string.cancel, null);
      } else {
        builder.setNeutralButton(
            R.string.do_not_remind, (d, which) -> MySettings.INS.setPrivReminderOff());
      }
      return UiUtils.removeButtonPadding(builder.create());
    }

    if (TAG_ADB_CONNECTION.equals(tag)) {
      return new AdbConnectDialog(this, dialogFragment).createDialog();
    }

    if (TAG_BACKUP_RESTORE.equals(tag)) {
      return mBackupRestoreDialog.createDialog();
    }

    return null;
  }

  private boolean isSecondaryUser() {
    if (UserUtils.getUserId() == 0) {
      return false;
    }

    Builder builder =
        new Builder(mA)
            .setPositiveButton(android.R.string.ok, null)
            .setTitle(R.string.primary_account)
            .setMessage(R.string.primary_profile_only);
    AlertDialogFragment.show(mA, builder.create(), "PRIMARY_PROFILE")
        .setOnDismissListener(d -> mA.finishAfterTransition());

    return true;
  }

  private class PkgAdapterCallbackImpl implements PkgAdapterCallback {

    public void onClick(Package pkg) {
      PackageActivity.start(mA, pkg, null);
    }

    public void onLongClick(Package pkg) {
      new PkgLongPressDialogFrag(pkg).show(mA.getSupportFragmentManager(), "PKG_OPTIONS");
    }
  }

  private boolean mObserversSet = false;

  public synchronized void setLiveDataObservers() {
    if (mObserversSet) {
      return;
    }

    PackageParser.INS.getProgMax().observe(mA, this::setMaxProg);
    PackageParser.INS.getProgNow().observe(mA, this::setNowProg);
    PackageParser.INS.getListCompleted().observe(mA, this::onListCompleted);
    PackageParser.INS.getPkgListLive().observe(mA, this::pkgListReceived);
    PackageParser.INS.getChangedPkg().observe(mA, this::pkgChanged);

    mObserversSet = true;

    PackageParser.INS.updatePkgListIfChanged();
  }

  private void setMaxProg(int progMax) {
    if (progMax < 0) {
      TextView progTv;

      if (mB.bigProgCont.getVisibility() == View.VISIBLE) {
        progTv = mB.bigProgText;
      } else {
        progTv = mB.movCont.progNowV;
        mB.movCont.progBar.setIndeterminate(true);
        mB.movCont.progMaxV.setText("");
        setProgVisible(true);
      }

      progTv.setText(PackageParser.INS.getProgMsg(progMax));
      return;
    }

    mB.movCont.progBar.setIndeterminate(false);
    mB.movCont.progBar.setProgress(0);
    mB.movCont.progNowV.setText(LocaleUtils.toLocalizedNum(0));
    mB.movCont.progBar.setMax(progMax);
    mB.movCont.progMaxV.setText(LocaleUtils.toLocalizedNum(progMax));

    setBigProgVisible(false);
    setProgVisible(true);
  }

  private void setNowProg(int progNow) {
    mB.movCont.progBar.setProgress(progNow, true);
    mB.movCont.progNowV.setText(LocaleUtils.toLocalizedNum(progNow));
  }

  private boolean mFirstListCompleted = true;
  private final LiveSchedParamTask<Integer> mPkgCountNotifier;

  private void onListCompleted(int pkgCount) {
    setProgVisible(false);

    if (((mB.refreshLayout.isRefreshing() || MySettings.INS.isSearching()) && pkgCount >= 0)
        || pkgCount == 0) {
      mPkgCountNotifier.cancelAndSchedule(pkgCount);
    }

    mB.refreshLayout.setRefreshing(false);

    if (mFirstListCompleted) {
      mFirstListCompleted = false;

      LiveSchedTask.schedule(
          mA, this::askForFeedback, 5, TimeUnit.SECONDS, true, TAG + "-FeedbackPrompt");

      showAppOpsPrivsToast();

      if (DaemonHandler.INS.isDaemonAlive()
          && !ApiUtils.hasNotifPerm()
          && MySettings.INS.shouldAskForNotifPerm()) {
        NotifUtils.askForNotifPerm(mA, mNotifPermReqLauncher);
      }
    }
  }

  private void pkgListReceived(List<Package> packages) {
    mPkgAdapter.submitList(new ArrayList<>(packages));
    setRepeatUpdates();
  }

  private void pkgChanged(Package pkg) {
    int position = mPkgAdapter.getCurrentList().indexOf(pkg);
    if (position != -1) {
      mPkgAdapter.notifyItemChanged(position);
    }
  }

  private void setRepeatUpdates() {
    boolean rep = mPkgAdapter.getItemCount() < mLayoutManager.findLastVisibleItemPosition() + 5;
    PackageParser.INS.setRepeatUpdates(rep);
  }

  private void onPrefChanged(Integer pref) {
    switch (pref) {
      case MySettings.PREF_DRAWER_CHANGED -> setBoxesChecked();
      case MySettings.PREF_UI_CHANGED -> mA.recreate();
    }
  }

  private void showPkgCount(int pkgCount) {
    showSnackBar(getQtyString(R.plurals.apps_count, pkgCount, pkgCount), 5);
  }

  public void showSnackBar(String text, int sec) {
    createSnackBar(text, sec).show();
  }

  public Snackbar createSnackBar(String text, int sec) {
    return UiUtils.createSnackBar(mA, mB.movCont.progBarCont, null, text, sec);
  }

  private void handleIntentActions(Intent intent) {
    String action = intent.getAction();
    if (action != null) {
      if (action.equals(ACTION_SHOW_DRAWER)) {
        openDrawerForPrivileges();
      }
    }
  }

  private final LiveMinDelayParamTask<Integer> mBigProgHider;

  public void setBigProgVisible(boolean visible) {
    if (visible) {
      mBigProgHider.cancelAndRunNow(View.VISIBLE);
    } else {
      mBigProgHider.cancelAndRunOrSchedule(View.GONE);
    }
  }

  public void setProgVisible(boolean visible) {
    mB.movCont.progBarCont.setVisibility(visible ? View.VISIBLE : View.GONE);
  }

  private boolean mNoAppOpsToasted = false;

  private void showAppOpsPrivsToast() {
    FragmentManager fm = mA.getSupportFragmentManager();
    if (!mNoAppOpsToasted
        && !MySettings.INS.excludeAppOpsPerms()
        && !AppOpsParser.INS.canReadAppOps()
        && !MySettings.INS.isRootEnabled()
        && !MySettings.INS.isAdbEnabled()
        && fm.findFragmentByTag(TAG_GRANT_ROOT_OR_ADB) == null
        && fm.findFragmentByTag(TAG_PRIVS_REQ_FOR_DAEMON) == null) {
      UiUtils.showToast(R.string.no_app_ops_without_daemon_toast);
      mNoAppOpsToasted = true;
    }
  }

  private void askForFeedback() {
    MySettings.INS.setMayAskForFeedback(true);
    LifecycleWatcher.addOnDestroyed(mA, () -> MySettings.INS.setMayAskForFeedback(false));
    mFeedback.askForFeedback();
  }

  private void setUpSearchView() {
    mSearchView.setOnQueryTextListener(
        new OnQueryTextListener() {
          public boolean onQueryTextSubmit(String query) {
            handleSearchQuery();
            return true;
          }

          public boolean onQueryTextChange(String newText) {
            handleSearchQuery();
            return true;
          }
        });

    mSearchView.setOnQueryTextFocusChangeListener(
        (v, hasFocus) -> {
          ActionBar actionBar = mA.getSupportActionBar();
          if (actionBar != null) {
            Drawable icon = AppCompatResources.getDrawable(mA, R.drawable.search_settings);
            if (icon != null) {
              actionBar.setHomeAsUpIndicator(icon);
            }
          }

          mB.getRoot().closeDrawer(GravityCompat.START, true);
          if (!hasFocus && TextUtils.isEmpty(mSearchView.getQuery())) {
            collapseSearchView();
          }
        });

    mSearchView.setQueryHint(getString(R.string.search_menu_item));
    mSearchView.setMaxWidth(Integer.MAX_VALUE);
  }

  private void collapseSearchView() {
    mSearchView.onActionViewCollapsed();
    mSearchView.setQuery(null, false);
    handleSearchQuery();

    ActionBar actionBar = mA.getSupportActionBar();
    ActionBarDrawerToggle drawerToggle;
    if (actionBar != null && (drawerToggle = mDrawerToggle) != null) {
      actionBar.setHomeAsUpIndicator(drawerToggle.getDrawerArrowDrawable());
    }
  }

  private void hideSearchSettings() {
    int delay = 0;
    FragmentManager fm = mA.getSupportFragmentManager();
    Fragment frag = fm.findFragmentById(R.id.search_settings_frag);
    if (frag != null) {
      fm.beginTransaction().remove(frag).commit();
      delay = 50;
    }
    mB.searchSettingsContainer.postDelayed(
        () -> mB.searchSettingsContainer.setVisibility(View.GONE), delay);
  }

  private void handleSearchQuery() {
    handleSearchQuery(true);
  }

  public void handleSearchQuery(boolean hideSettings) {
    if (hideSettings) {
      hideSearchSettings();
    }

    CharSequence queryText = mSearchView.getQuery();
    boolean wasSearching = MySettings.INS.isSearching();

    MySettings.INS.setQueryText(queryText == null ? null : queryText.toString());

    if (!MySettings.INS.isSearching() && !wasSearching) {
      return;
    }

    mPkgCountNotifier.cancel();

    mB.refreshLayout.setRefreshing(
        !MySettings.INS.isDeepSearchEnabled() || !MySettings.INS.isSearching());

    PackageParser.INS.setRepeatUpdates(true);

    PackageParser.INS.handleSearchQuery();
  }

  private void setNavigationMenu() {
    mB.navV.invalidate();
    setBoxesChecked();
    setCheckBoxListeners();
    mB.navV.getMenu().findItem(R.id.action_donate).setVisible(true);
  }

  private void setBoxesChecked() {
    if (mB != null) {
      setRootCheckBox(MySettings.INS.isRootEnabled(), true);
      setAdbCheckBox(MySettings.INS.isAdbEnabled(), true);
    }
  }

  private void setCheckBoxListeners() {
    if (mB == null) {
      return;
    }
    Menu menu = mB.navV.getMenu();
    for (int id : new int[] {R.id.action_root, R.id.action_adb}) {
      MenuItem menuItem = menu.findItem(id);
      Objects.requireNonNull(menuItem.getActionView())
          .setOnClickListener(v -> handleNavigationItemChecked(menuItem));
    }
  }

  private boolean handleNavigationItemSelected(MenuItem item) {
    View view = item.getActionView();
    if (view instanceof CheckBox checkBox) {
      checkBox.setCh
Download .txt
gitextract_19owviso/

├── .gitignore
├── .gitmodules
├── 404.html
├── LICENSE
├── PRIVACY.html
├── README.md
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── mirfatif/
│       │   │           ├── err/
│       │   │           │   └── AdbException.java
│       │   │           └── permissionmanagerx/
│       │   │               ├── about/
│       │   │               │   ├── AboutActivity.java
│       │   │               │   ├── CrashReportActivity.kt
│       │   │               │   ├── PrivilegesAdapter.java
│       │   │               │   ├── PrivilegesDialog.java
│       │   │               │   └── TransCreditsDialogFrag.java
│       │   │               ├── app/
│       │   │               │   └── App.java
│       │   │               ├── backup/
│       │   │               │   ├── BackupFileSelector.java
│       │   │               │   └── BackupRestore.java
│       │   │               ├── base/
│       │   │               │   ├── AlertDialogFragment.java
│       │   │               │   ├── BaseActivity.java
│       │   │               │   ├── BottomSheetDialogFrag.java
│       │   │               │   ├── DialogBg.java
│       │   │               │   └── MyListAdapter.java
│       │   │               ├── fwk/
│       │   │               │   ├── AboutActivityM.java
│       │   │               │   ├── AdbConnectSvcM.java
│       │   │               │   ├── AdvSettingsActivityM.java
│       │   │               │   ├── AppM.java
│       │   │               │   ├── CrashReportActivityM.java
│       │   │               │   ├── CustomButton.java
│       │   │               │   ├── DaemonRcvSvcM.java
│       │   │               │   ├── DialogHelpIcon.java
│       │   │               │   ├── FilterSettingsActivityM.java
│       │   │               │   ├── HelpActivityM.java
│       │   │               │   ├── LifecycleWatcher.java
│       │   │               │   ├── LogcatSvcM.java
│       │   │               │   ├── MainActivityM.java
│       │   │               │   ├── MoveUpBehavior.java
│       │   │               │   ├── MyCoordinatorLayout.java
│       │   │               │   ├── MyDrawerLayout.java
│       │   │               │   ├── MyLinearLayout.java
│       │   │               │   ├── MyNavigationView.java
│       │   │               │   ├── MySearchView.java
│       │   │               │   ├── MyWebView.java
│       │   │               │   ├── NumPickerPref.java
│       │   │               │   ├── PackageActivityM.java
│       │   │               │   ├── ProgressLinearLayout.java
│       │   │               │   └── SettingsActivityM.java
│       │   │               ├── help/
│       │   │               │   ├── HelpActivity.java
│       │   │               │   └── HelpJsInterface.java
│       │   │               ├── main/
│       │   │               │   ├── AdbConnectDialog.java
│       │   │               │   ├── BackupRestoreDialog.java
│       │   │               │   ├── DaemonStartProg.java
│       │   │               │   ├── Feedback.java
│       │   │               │   ├── FeedbackDialogFrag.java
│       │   │               │   ├── MainActivity.java
│       │   │               │   ├── PackageAdapter.java
│       │   │               │   ├── PkgLongPressDialogFrag.java
│       │   │               │   └── PrivsCheckBoxFocus.java
│       │   │               ├── parser/
│       │   │               │   ├── AppOpsParser.java
│       │   │               │   ├── Package.java
│       │   │               │   ├── PackageParser.java
│       │   │               │   ├── PermGroupsMapping.java
│       │   │               │   ├── Permission.java
│       │   │               │   ├── SearchConstants.java
│       │   │               │   └── permsdb/
│       │   │               │       ├── PermissionDao.java
│       │   │               │       ├── PermissionDatabase.java
│       │   │               │       ├── PermissionEntity.java
│       │   │               │       └── PermsDb.java
│       │   │               ├── pkg/
│       │   │               │   ├── PackageActivity.java
│       │   │               │   ├── PermDetailDialog.java
│       │   │               │   ├── PermLongPressDialogFrag.java
│       │   │               │   └── PermissionAdapter.java
│       │   │               ├── prefs/
│       │   │               │   ├── AppUpdate.java
│       │   │               │   ├── ExcFiltersData.java
│       │   │               │   ├── MySettings.java
│       │   │               │   ├── fwk/
│       │   │               │   │   ├── CustomPrefDialogFrag.java
│       │   │               │   │   ├── EditTextPrefDialogFrag.java
│       │   │               │   │   ├── ListPrefDialogFrag.java
│       │   │               │   │   └── MultiSelectListPrefDialogFrag.java
│       │   │               │   └── settings/
│       │   │               │       ├── AdvSettingsActivity.java
│       │   │               │       ├── AdvSettingsFrag.java
│       │   │               │       ├── FilterSettingsActivity.java
│       │   │               │       ├── FilterSettingsFragment.java
│       │   │               │       ├── SearchSettingsFrag.java
│       │   │               │       ├── SettingsActivity.java
│       │   │               │       ├── SettingsFrag.java
│       │   │               │       ├── SettingsFragGeneral.java
│       │   │               │       └── SettingsFragTheme.java
│       │   │               ├── privs/
│       │   │               │   ├── AdbConnManager.java
│       │   │               │   ├── DaemonHandler.java
│       │   │               │   ├── DaemonIface.java
│       │   │               │   ├── DaemonStarter.java
│       │   │               │   └── NativeDaemon.java
│       │   │               ├── profile/
│       │   │               │   └── PermProfileBackupRestore.java
│       │   │               ├── svc/
│       │   │               │   ├── AdbConnectSvc.java
│       │   │               │   ├── DaemonRcvSvc.java
│       │   │               │   └── LogcatSvc.java
│       │   │               └── util/
│       │   │                   ├── ApiUtils.java
│       │   │                   ├── AppLifecycle.java
│       │   │                   ├── LocaleUtils.java
│       │   │                   ├── LogUtils.java
│       │   │                   ├── NotifUtils.java
│       │   │                   ├── SmallDimMarginSpan.java
│       │   │                   ├── StdErrLogServer.java
│       │   │                   ├── StringUtils.java
│       │   │                   ├── UiUtils.java
│       │   │                   ├── UserUtils.java
│       │   │                   ├── Utils.java
│       │   │                   └── bg/
│       │   │                       ├── LiveBgTask.java
│       │   │                       ├── LiveEvent.java
│       │   │                       ├── LiveMinDelayParamTask.java
│       │   │                       ├── LiveSchedParamTask.java
│       │   │                       ├── LiveSchedTask.java
│       │   │                       ├── LiveSingleParamTask.java
│       │   │                       ├── LiveTasksQueue.java
│       │   │                       ├── LiveTasksQueueTyped.java
│       │   │                       ├── LiveUiParamTask.java
│       │   │                       ├── LiveUiTask.java
│       │   │                       ├── LiveUiWaitTask.java
│       │   │                       └── UiRunner.java
│       │   └── res/
│       │       ├── anim/
│       │       │   └── shake.xml
│       │       ├── color/
│       │       │   ├── active_disabled.xml
│       │       │   └── slim_switch.xml
│       │       ├── drawable/
│       │       │   ├── accessibility.xml
│       │       │   ├── advanced_settings.xml
│       │       │   ├── arrow_right.xml
│       │       │   ├── backup_restore.xml
│       │       │   ├── check_circle.xml
│       │       │   ├── circle_progress_bar.xml
│       │       │   ├── color.xml
│       │       │   ├── crash_report_text_bg.xml
│       │       │   ├── cross_red.xml
│       │       │   ├── danger.xml
│       │       │   ├── dark_mode.xml
│       │       │   ├── database.xml
│       │       │   ├── donate.xml
│       │       │   ├── email.xml
│       │       │   ├── exit.xml
│       │       │   ├── filter.xml
│       │       │   ├── g_accounts.xml
│       │       │   ├── g_audio.xml
│       │       │   ├── g_background.xml
│       │       │   ├── g_biometrics.xml
│       │       │   ├── g_bluetooth.xml
│       │       │   ├── g_calendar.xml
│       │       │   ├── g_calllog.xml
│       │       │   ├── g_camera.xml
│       │       │   ├── g_clipboard.xml
│       │       │   ├── g_contacts.xml
│       │       │   ├── g_data.xml
│       │       │   ├── g_display.xml
│       │       │   ├── g_hardware.xml
│       │       │   ├── g_home.xml
│       │       │   ├── g_location.xml
│       │       │   ├── g_log.xml
│       │       │   ├── g_mic.xml
│       │       │   ├── g_network.xml
│       │       │   ├── g_notif.xml
│       │       │   ├── g_others.xml
│       │       │   ├── g_package.xml
│       │       │   ├── g_phone.xml
│       │       │   ├── g_power.xml
│       │       │   ├── g_sensors.xml
│       │       │   ├── g_settings.xml
│       │       │   ├── g_sms.xml
│       │       │   ├── g_storage.xml
│       │       │   ├── g_vibration.xml
│       │       │   ├── g_wifi.xml
│       │       │   ├── github_mark.xml
│       │       │   ├── help.xml
│       │       │   ├── hinge.xml
│       │       │   ├── info.xml
│       │       │   ├── issues.xml
│       │       │   ├── key.xml
│       │       │   ├── label.xml
│       │       │   ├── link.xml
│       │       │   ├── locale.xml
│       │       │   ├── log.xml
│       │       │   ├── main_act_big_prog_bg.xml
│       │       │   ├── notification_icon.xml
│       │       │   ├── paid.xml
│       │       │   ├── perm_watcher.xml
│       │       │   ├── permission.xml
│       │       │   ├── privacy_policy.xml
│       │       │   ├── report.xml
│       │       │   ├── root.xml
│       │       │   ├── schedule.xml
│       │       │   ├── search_settings.xml
│       │       │   ├── search_settings_bg.xml
│       │       │   ├── settings.xml
│       │       │   ├── share.xml
│       │       │   ├── shell.xml
│       │       │   ├── slim_switch_thumb.xml
│       │       │   ├── slim_switch_track.xml
│       │       │   ├── star.xml
│       │       │   ├── telegram.xml
│       │       │   ├── theme.xml
│       │       │   ├── tick.xml
│       │       │   ├── triangle.xml
│       │       │   ├── update.xml
│       │       │   ├── zoom_in.xml
│       │       │   └── zoom_out.xml
│       │       ├── layout/
│       │       │   ├── about_privileges_dialog.xml
│       │       │   ├── about_privileges_item.xml
│       │       │   ├── activity_about.xml
│       │       │   ├── activity_crash_report.xml
│       │       │   ├── activity_fragment_container.xml
│       │       │   ├── activity_help.xml
│       │       │   ├── activity_main.xml
│       │       │   ├── activity_main_moving_container.xml
│       │       │   ├── activity_package.xml
│       │       │   ├── adb_connect_dialog.xml
│       │       │   ├── backup_restore_dialog.xml
│       │       │   ├── dilog_title_with_help.xml
│       │       │   ├── feedback_dialog.xml
│       │       │   ├── perm_details_dialog.xml
│       │       │   ├── perm_long_press_dialog.xml
│       │       │   ├── pkg_long_press_dialog.xml
│       │       │   ├── progress_dialog.xml
│       │       │   ├── rate_donate_dialog.xml
│       │       │   ├── rv_item_perm.xml
│       │       │   ├── rv_item_pkg.xml
│       │       │   ├── status_bar_bg_cont.xml
│       │       │   ├── trans_credits_row.xml
│       │       │   └── translation_dialog.xml
│       │       ├── menu/
│       │       │   ├── about_menu.xml
│       │       │   ├── filter_settings.xml
│       │       │   ├── help_menu.xml
│       │       │   ├── main_drawer.xml
│       │       │   ├── main_search.xml
│       │       │   └── package_menu.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       ├── values/
│       │       │   ├── arrays.xml
│       │       │   ├── attrs.xml
│       │       │   ├── colors.xml
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   ├── strings_foss.xml
│       │       │   ├── styles.xml
│       │       │   └── theme.xml
│       │       ├── values-ar/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-de/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-el/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-es/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-night/
│       │       │   └── colors.xml
│       │       ├── values-ro/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-ru/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-tr/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       ├── values-v29/
│       │       │   └── styles.xml
│       │       ├── values-zh-rCN/
│       │       │   ├── pref_keys_foss.xml
│       │       │   ├── search_strings_foss.xml
│       │       │   └── strings_foss.xml
│       │       └── xml/
│       │           ├── adv_settings_prefs.xml
│       │           ├── filter_settings_preferences.xml
│       │           ├── settings_prefs.xml
│       │           ├── settings_prefs_general.xml
│       │           ├── settings_prefs_search.xml
│       │           └── settings_prefs_theming.xml
│       └── release/
│           └── AndroidManifest.xml
├── build.gradle.kts
├── buildSrc/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src/
│       └── main/
│           └── kotlin/
│               ├── android-base-conventions.gradle.kts
│               ├── android-lib-conventions.gradle.kts
│               ├── apk-conventions.gradle.kts
│               ├── dependency-updates-conventions.gradle.kts
│               ├── java-android-lib-conventions.gradle.kts
│               ├── java-base-conventions.gradle.kts
│               ├── java-kotlin-conventions.gradle.kts
│               ├── java-lib-conventions.gradle.kts
│               └── spotless-conventions.gradle.kts
├── fastlane/
│   └── metadata/
│       └── android/
│           ├── ar/
│           │   ├── short_description.txt
│           │   └── title.txt
│           ├── de/
│           │   └── short_description.txt
│           ├── el/
│           │   └── title.txt
│           ├── en-US/
│           │   ├── changelogs/
│           │   │   ├── 101.txt
│           │   │   ├── 103.txt
│           │   │   ├── 104.txt
│           │   │   ├── 105.txt
│           │   │   ├── 106.txt
│           │   │   ├── 107.txt
│           │   │   ├── 108.txt
│           │   │   ├── 109.txt
│           │   │   ├── 110.txt
│           │   │   ├── 111.txt
│           │   │   ├── 112.txt
│           │   │   ├── 113.txt
│           │   │   ├── 114.txt
│           │   │   ├── 116.txt
│           │   │   ├── 117.txt
│           │   │   ├── 118.txt
│           │   │   ├── 119.txt
│           │   │   ├── 120.txt
│           │   │   ├── 121.txt
│           │   │   ├── 122.txt
│           │   │   ├── 123.txt
│           │   │   ├── 124.txt
│           │   │   ├── 125.txt
│           │   │   ├── 126.txt
│           │   │   ├── 127.txt
│           │   │   ├── 128.txt
│           │   │   └── 129.txt
│           │   ├── full_description.txt
│           │   ├── short_description.txt
│           │   └── title.txt
│           ├── es/
│           │   ├── short_description.txt
│           │   └── title.txt
│           ├── ru/
│           │   ├── full_description.txt
│           │   ├── short_description.txt
│           │   └── title.txt
│           ├── tr/
│           │   └── title.txt
│           ├── ur/
│           │   └── title.txt
│           └── zh/
│               ├── full_description.txt
│               ├── short_description.txt
│               └── title.txt
├── gradle/
│   ├── libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── help/
│   ├── 404.html
│   ├── ar/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── assets/
│   │   └── javascripts/
│   │       └── lunr/
│   │           ├── tinyseg.js
│   │           └── wordcut.js
│   ├── batch-operations/
│   │   └── index.html
│   ├── css/
│   │   └── extra.css
│   ├── de/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── details/
│   │   └── index.html
│   ├── es/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── faqs/
│   │   └── index.html
│   ├── fr/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── index.html
│   ├── javascript/
│   │   └── extra.js
│   ├── permission-references/
│   │   └── index.html
│   ├── permission-view/
│   │   └── index.html
│   ├── permission-watcher/
│   │   └── index.html
│   ├── pt-BR/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── ru/
│   │   ├── batch-operations/
│   │   │   └── index.html
│   │   ├── details/
│   │   │   └── index.html
│   │   ├── faqs/
│   │   │   └── index.html
│   │   ├── index.html
│   │   ├── permission-references/
│   │   │   └── index.html
│   │   ├── permission-view/
│   │   │   └── index.html
│   │   ├── permission-watcher/
│   │   │   └── index.html
│   │   ├── scheduled-check/
│   │   │   └── index.html
│   │   ├── search/
│   │   │   └── index.html
│   │   ├── use-with-adb/
│   │   │   └── index.html
│   │   ├── versions/
│   │   │   └── index.html
│   │   └── whatsrunning-integration/
│   │       └── index.html
│   ├── scheduled-check/
│   │   └── index.html
│   ├── search/
│   │   ├── index.html
│   │   └── search_index.json
│   ├── sitemap.xml
│   ├── use-with-adb/
│   │   └── index.html
│   ├── versions/
│   │   └── index.html
│   ├── whatsrunning-integration/
│   │   └── index.html
│   └── zh/
│       ├── batch-operations/
│       │   └── index.html
│       ├── details/
│       │   └── index.html
│       ├── faqs/
│       │   └── index.html
│       ├── index.html
│       ├── permission-references/
│       │   └── index.html
│       ├── permission-view/
│       │   └── index.html
│       ├── permission-watcher/
│       │   └── index.html
│       ├── scheduled-check/
│       │   └── index.html
│       ├── search/
│       │   └── index.html
│       ├── use-with-adb/
│       │   └── index.html
│       ├── versions/
│       │   └── index.html
│       └── whatsrunning-integration/
│           └── index.html
├── hidden_apis/
│   ├── .gitignore
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           └── java/
│               ├── android/
│               │   ├── app/
│               │   │   ├── ActivityManagerNative.java
│               │   │   ├── AppOpsManager.java
│               │   │   └── IActivityManager.java
│               │   ├── content/
│               │   │   ├── Context.java
│               │   │   └── pm/
│               │   │       ├── IPackageManager.java
│               │   │       └── ParceledListSlice.java
│               │   ├── os/
│               │   │   ├── IDeviceIdleController.java
│               │   │   ├── Process.java
│               │   │   └── ServiceManager.java
│               │   └── permission/
│               │       └── IPermissionManager.java
│               └── com/
│                   └── android/
│                       └── internal/
│                           └── app/
│                               └── IAppOpsService.java
├── native/
│   ├── build_native.sh
│   ├── pmxd.c
│   └── pmxe.c
├── priv_daemon/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── daemon-proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── mirfatif/
│                       └── privdaemon/
│                           ├── Callbacks.java
│                           ├── DaemonLog.java
│                           ├── IPrivTasksImpl.java
│                           ├── Jni.java
│                           ├── Main.java
│                           ├── PrivDaemon.java
│                           ├── PrivsStatusReader.java
│                           └── Server.java
├── priv_library/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── aidl/
│           │   └── com/
│           │       └── mirfatif/
│           │           └── privtasks/
│           │               └── bind/
│           │                   ├── ILogCallback.aidl
│           │                   └── IPrivTasksCallback.aidl
│           └── java/
│               └── com/
│                   └── mirfatif/
│                       ├── err/
│                       │   ├── ContainerException.java
│                       │   └── HiddenAPIsException.java
│                       └── privtasks/
│                           ├── AppPrivTasks.java
│                           ├── Constants.java
│                           ├── HiddenSdkIntConstants.java
│                           ├── HiddenSdkStringConstants.java
│                           ├── PrivTasksError.java
│                           ├── bind/
│                           │   ├── AppOpsLists.java
│                           │   ├── DaemonState.java
│                           │   ├── MyPackageInfo.java
│                           │   ├── MyPackageOps.java
│                           │   ├── PermFixedFlags.java
│                           │   ├── PrivsStatus.java
│                           │   └── StrIntMap.java
│                           ├── hiddenapis/
│                           │   ├── HiddenAPIs.java
│                           │   ├── MidReleaseBrokenAPIsDelegate.kt
│                           │   └── SysSvcFactory.java
│                           ├── iface/
│                           │   └── IPrivTasks.java
│                           └── util/
│                               ├── CloseableReadWriteLock.java
│                               ├── LogUtil.java
│                               ├── MyLog.java
│                               ├── NonBlockingReader.java
│                               ├── Util.java
│                               └── bg/
│                                   ├── BgRunner.java
│                                   ├── MinDelayTaskExecutor.java
│                                   ├── NotifyWaiter.java
│                                   ├── RateLimitedTask.java
│                                   ├── RateLimitedTaskTyped.java
│                                   ├── RateLimiter.java
│                                   ├── RunnableWithParam.java
│                                   ├── RunnableWithResult.java
│                                   ├── SingleParamTask.java
│                                   ├── SingleSchedTaskExecutor.java
│                                   ├── SingleTaskExecutor.java
│                                   ├── SingleTaskExecutorAbstract.java
│                                   ├── SingleTaskExecutorTyped.java
│                                   └── ThreadUtils.java
├── privacy_policy.html
└── settings.gradle.kts
Download .txt
SYMBOL INDEX (1844 symbols across 169 files)

FILE: app/src/main/java/com/mirfatif/err/AdbException.java
  class AdbException (line 3) | public class AdbException extends Exception {
    method AdbException (line 5) | public AdbException(Throwable cause) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/about/AboutActivity.java
  class AboutActivity (line 49) | public class AboutActivity {
    method AboutActivity (line 55) | public AboutActivity(AboutActivityM activity) {
    method onCreated (line 62) | public void onCreated() {
    method openWebUrl (line 118) | private void openWebUrl(View view, int linkResId) {
    method setLogTitle (line 122) | private void setLogTitle(int resId) {
    method alreadyLogging (line 126) | private static boolean alreadyLogging() {
    method handleLogging (line 130) | private void handleLogging(boolean notifPermGranted) {
    method checkForUpdates (line 157) | private void checkForUpdates() {
    method handleAppUpdateResult (line 170) | private void handleAppUpdateResult(AppUpdate.AppUpdateResult res) {
    method showAppUpdateDialog (line 183) | public static void showAppUpdateDialog(FragmentActivity act, String ve...
    method sendShareIntent (line 197) | public static void sendShareIntent(Activity activity) {
    method onCreateOptionsMenu (line 204) | public boolean onCreateOptionsMenu(Menu menu) {
    method onPrepareOptionsMenu (line 209) | public boolean onPrepareOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 215) | public boolean onOptionsItemSelected(MenuItem item) {
    method onDestroy (line 235) | public void onDestroy() {
    method createDialog (line 246) | public AlertDialog createDialog(String tag, AlertDialogFragment dialog...
    method dumpHeap (line 254) | private static void dumpHeap() {
    method start (line 280) | public static void start(Activity activity) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/about/PrivilegesAdapter.java
  class PrivilegesAdapter (line 14) | public class PrivilegesAdapter extends RecyclerView.Adapter<ItemViewHold...
    method submitList (line 18) | void submitList(List<PrivsStatus.PermStatus> permStatusList) {
    method onCreateViewHolder (line 26) | public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewTyp...
    method onBindViewHolder (line 32) | public void onBindViewHolder(ItemViewHolder holder, int position) {
    method getItemId (line 36) | public long getItemId(int position) {
    method getItemCount (line 40) | public int getItemCount() {
    class ItemViewHolder (line 44) | class ItemViewHolder extends ViewHolder {
      method ItemViewHolder (line 48) | public ItemViewHolder(AboutPrivilegesItemBinding binding) {
      method bind (line 53) | void bind(int pos) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/about/PrivilegesDialog.java
  class PrivilegesDialog (line 19) | public class PrivilegesDialog {
    method PrivilegesDialog (line 23) | PrivilegesDialog(FragmentActivity activity) {
    method create (line 27) | AlertDialog create(AlertDialogFragment dialogFragment) {
    method updatePermStatusDialog (line 47) | private void updatePermStatusDialog(
    method getIcon (line 67) | private int getIcon(boolean ok) {
    class Divider (line 71) | private static class Divider extends ShapeDrawable {
      method Divider (line 73) | public Divider(int color) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/about/TransCreditsDialogFrag.java
  class TransCreditsDialogFrag (line 19) | public class TransCreditsDialogFrag extends BottomSheetDialogFrag {
    method show (line 21) | public static void show(FragmentManager fm) {
    method onCreateView (line 26) | public View onCreateView(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/app/App.java
  class App (line 16) | public class App {
    method App (line 22) | public App(AppM app) {
    method onCreate (line 30) | public void onCreate() {
    method onConfigurationChanged (line 42) | public Configuration onConfigurationChanged(Configuration newConfig) {
    method setLocale (line 46) | public static void setLocale() {
    method getCxt (line 50) | public static Context getCxt() {
    method getRes (line 57) | public static Resources getRes() {
    method getPm (line 63) | public static PackageManager getPm() {
    class ExceptionHandler (line 67) | private class ExceptionHandler implements Thread.UncaughtExceptionHand...
      method uncaughtException (line 69) | public void uncaughtException(Thread t, Throwable e) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/backup/BackupFileSelector.java
  class BackupFileSelector (line 13) | public class BackupFileSelector {
    method backupFileName (line 17) | public static String backupFileName() {
    method BackupFileSelector (line 24) | public BackupFileSelector(
    method launch (line 39) | public void launch() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/backup/BackupRestore.java
  type BackupRestore (line 45) | public enum BackupRestore {
    method backupNoThrow (line 78) | public Result backupNoThrow(Uri file, boolean backupPrefs, boolean ski...
    method backup (line 87) | private Result backup(Uri file, boolean backupPrefs, boolean skipUnins...
    method backup (line 99) | public Result backup(
    method restore (line 256) | public Result restore(Uri file, boolean skipUninstalledApps) {
    method restore (line 279) | public Result restore(InputStream is, boolean skipUninstalledApps) {
    method getKeyValueEntries (line 408) | public static List<String[]> getKeyValueEntries(
    method isInvalidPrefKey (line 461) | private boolean isInvalidPrefKey(String prefKey) {
    method getAllPkgList (line 488) | private List<String> getAllPkgList() {
    class Result (line 494) | public static class Result {
      method Result (line 498) | private Result(int prefs, int perms, int profiles, int invalidPrefs,...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/AlertDialogFragment.java
  class AlertDialogFragment (line 18) | public class AlertDialogFragment extends AppCompatDialogFragment {
    method AlertDialogFragment (line 24) | public AlertDialogFragment() {}
    method getDialog (line 28) | public AlertDialog getDialog() {
    method AlertDialogFragment (line 32) | private AlertDialogFragment(AlertDialog alertDialog) {
    method onAttach (line 38) | public void onAttach(Context context) {
    method onCreateDialog (line 43) | public Dialog onCreateDialog(Bundle savedInstanceState) {
    method onSaveInstanceState (line 55) | public void onSaveInstanceState(Bundle outState) {}
    method setOnDismissListener (line 59) | public AlertDialogFragment setOnDismissListener(OnDismissListener dism...
    method onDismiss (line 64) | public void onDismiss(DialogInterface dialog) {
    method create (line 71) | public static AlertDialogFragment create(AlertDialog alertDialog, Stri...
    method show (line 80) | public static AlertDialogFragment show(
    method show (line 85) | public AlertDialogFragment show(FragmentActivity activity) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/BaseActivity.java
  class BaseActivity (line 23) | public abstract class BaseActivity extends AppCompatActivity {
    method onCreate (line 25) | protected synchronized void onCreate(Bundle savedInstanceState) {
    method onCreated (line 33) | protected abstract void onCreated(Bundle savedInstanceState);
    method onOptionsItemSelected (line 35) | public boolean onOptionsItemSelected(MenuItem item) {
    method attachBaseContext (line 43) | protected void attachBaseContext(Context context) {
    method onConfigurationChanged (line 47) | public void onConfigurationChanged(Configuration newConfig) {
    method applyOverrideConfiguration (line 51) | public void applyOverrideConfiguration(Configuration overrideConfigura...
    method createDialog (line 55) | public AlertDialog createDialog(String tag, AlertDialogFragment dialog...
    method setNightTheme (line 59) | private boolean setNightTheme() {
    method setContentView (line 74) | public void setContentView(ViewBinding binding) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/BottomSheetDialogFrag.java
  class BottomSheetDialogFrag (line 12) | public class BottomSheetDialogFrag extends BottomSheetDialogFragment {
    method onAttach (line 16) | public void onAttach(Context context) {
    method onCreateDialog (line 21) | public Dialog onCreateDialog(Bundle savedInstanceState) {
    method onViewCreated (line 34) | public void onViewCreated(View view, Bundle savedInstanceState) {
    method getTheme (line 40) | public int getTheme() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/DialogBg.java
  class DialogBg (line 10) | public class DialogBg extends InsetDrawable {
    method DialogBg (line 14) | public DialogBg(Activity activity, boolean bordered) {
    method DialogBg (line 23) | public DialogBg(boolean isBottom, Activity activity) {
    method createDrawable (line 32) | private static Drawable createDrawable(Activity activity, boolean isBo...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/base/MyListAdapter.java
  class MyListAdapter (line 14) | public abstract class MyListAdapter<T, VH extends RecyclerView.ViewHolder>
    method MyListAdapter (line 17) | protected MyListAdapter(ItemCallback<T> diffCallback, LifecycleOwner o...
    method getItem (line 24) | protected T getItem(int position) {
    method submitList (line 34) | public synchronized void submitList(List<T> list) {
    method submitListAndWait (line 44) | private void submitListAndWait(List<T> list) {
    method submitListOnUi (line 52) | private void submitListOnUi(List<T> list) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AboutActivityM.java
  class AboutActivityM (line 11) | public class AboutActivityM extends BaseActivity {
    method onCreated (line 15) | protected void onCreated(Bundle savedInstanceState) {
    method onCreateOptionsMenu (line 19) | public boolean onCreateOptionsMenu(Menu menu) {
    method onPrepareOptionsMenu (line 23) | public boolean onPrepareOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 27) | public boolean onOptionsItemSelected(MenuItem item) {
    method onDestroy (line 31) | protected void onDestroy() {
    method createDialog (line 36) | public AlertDialog createDialog(String tag, AlertDialogFragment dialog...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AdbConnectSvcM.java
  class AdbConnectSvcM (line 8) | public class AdbConnectSvcM extends Service {
    method onBind (line 12) | public IBinder onBind(Intent intent) {
    method onStartCommand (line 16) | public int onStartCommand(Intent intent, int flags, int startId) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AdvSettingsActivityM.java
  class AdvSettingsActivityM (line 7) | public class AdvSettingsActivityM extends BaseActivity {
    method AdvSettingsActivityM (line 11) | public AdvSettingsActivityM() {
    method onCreated (line 15) | protected void onCreated(Bundle savedInstanceState) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AppM.java
  class AppM (line 7) | public class AppM extends Application {
    method onCreate (line 11) | public void onCreate() {
    method onConfigurationChanged (line 16) | public void onConfigurationChanged(Configuration newConfig) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/CrashReportActivityM.java
  class CrashReportActivityM (line 7) | public class CrashReportActivityM extends BaseActivity {
    method onCreated (line 11) | protected void onCreated(Bundle savedInstanceState) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/CustomButton.java
  class CustomButton (line 18) | public class CustomButton extends AppCompatButton {
    method CustomButton (line 22) | public CustomButton(Context context, AttributeSet attrs) {
    method onTouchEvent (line 47) | public boolean onTouchEvent(MotionEvent event) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/DaemonRcvSvcM.java
  class DaemonRcvSvcM (line 8) | public class DaemonRcvSvcM extends Service {
    method onBind (line 12) | public IBinder onBind(Intent intent) {
    method onStartCommand (line 16) | public int onStartCommand(Intent intent, int flags, int startId) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/DialogHelpIcon.java
  class DialogHelpIcon (line 10) | public class DialogHelpIcon extends AppCompatImageView {
    method DialogHelpIcon (line 12) | public DialogHelpIcon(Context context, AttributeSet attrs) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/FilterSettingsActivityM.java
  class FilterSettingsActivityM (line 11) | public class FilterSettingsActivityM extends BaseActivity {
    method onCreated (line 15) | protected void onCreated(Bundle savedInstanceState) {
    method onCreateOptionsMenu (line 19) | public boolean onCreateOptionsMenu(Menu menu) {
    method onPrepareOptionsMenu (line 23) | public boolean onPrepareOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 27) | public boolean onOptionsItemSelected(MenuItem item) {
    method createDialog (line 31) | public AlertDialog createDialog(String tag, AlertDialogFragment dialog...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/HelpActivityM.java
  class HelpActivityM (line 9) | public class HelpActivityM extends BaseActivity {
    method onCreated (line 13) | protected void onCreated(Bundle savedInstanceState) {
    method onCreateOptionsMenu (line 17) | public boolean onCreateOptionsMenu(Menu menu) {
    method onPrepareOptionsMenu (line 21) | public boolean onPrepareOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 25) | public boolean onOptionsItemSelected(MenuItem item) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/LifecycleWatcher.java
  class LifecycleWatcher (line 11) | public class LifecycleWatcher {
    method addOnDestroyed (line 13) | public static LifecycleWatcher addOnDestroyed(LifecycleOwner owner, Li...
    method LifecycleWatcher (line 20) | private LifecycleWatcher(LifecycleOwner owner, LifecycleCallback callb...
    method addObserver (line 29) | private void addObserver(Lifecycle lifecycle) {
    method onDestroyed (line 36) | private void onDestroyed(Lifecycle lifecycle) {
    class Observer (line 41) | private class Observer implements LifecycleEventObserver {
      method onStateChanged (line 43) | public void onStateChanged(LifecycleOwner source, Event event) {
    type LifecycleCallback (line 50) | public interface LifecycleCallback {
      method onDestroyed (line 52) | void onDestroyed();

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/LogcatSvcM.java
  class LogcatSvcM (line 8) | public class LogcatSvcM extends Service {
    method onBind (line 12) | public IBinder onBind(Intent intent) {
    method onStartCommand (line 16) | public int onStartCommand(Intent intent, int flags, int startId) {
    method onDestroy (line 20) | public void onDestroy() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MainActivityM.java
  class MainActivityM (line 12) | public class MainActivityM extends BaseActivity {
    method onCreated (line 16) | protected void onCreated(Bundle savedInstanceState) {
    method onNewIntent (line 20) | protected void onNewIntent(Intent intent) {
    method onCreateOptionsMenu (line 25) | public boolean onCreateOptionsMenu(Menu menu) {
    method onPrepareOptionsMenu (line 29) | public boolean onPrepareOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 33) | public boolean onOptionsItemSelected(MenuItem item) {
    method onResume (line 37) | protected void onResume() {
    method onPause (line 42) | protected void onPause() {
    method onAttachedToWindow (line 47) | public void onAttachedToWindow() {
    method createDialog (line 52) | public AlertDialog createDialog(String tag, AlertDialogFragment dialog...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MoveUpBehavior.java
  class MoveUpBehavior (line 6) | public class MoveUpBehavior extends CoordinatorLayout.Behavior<View> {
    method MoveUpBehavior (line 11) | public MoveUpBehavior(Class<?> dependency, View child) {
    method layoutDependsOn (line 16) | public boolean layoutDependsOn(CoordinatorLayout parent, View child, V...
    method onDependentViewChanged (line 20) | public boolean onDependentViewChanged(CoordinatorLayout parent, View c...
    method onDependentViewRemoved (line 30) | public void onDependentViewRemoved(CoordinatorLayout parent, View chil...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyCoordinatorLayout.java
  class MyCoordinatorLayout (line 8) | public class MyCoordinatorLayout extends CoordinatorLayout {
    method MyCoordinatorLayout (line 10) | public MyCoordinatorLayout(Context context, AttributeSet attrs) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyDrawerLayout.java
  class MyDrawerLayout (line 8) | public class MyDrawerLayout extends DrawerLayout {
    method MyDrawerLayout (line 10) | public MyDrawerLayout(Context context, AttributeSet attrs) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyLinearLayout.java
  class MyLinearLayout (line 8) | public class MyLinearLayout extends LinearLayout {
    method MyLinearLayout (line 10) | public MyLinearLayout(Context context, AttributeSet attrs) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyNavigationView.java
  class MyNavigationView (line 8) | public class MyNavigationView extends NavigationView {
    method MyNavigationView (line 10) | public MyNavigationView(Context context, AttributeSet attrs) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MySearchView.java
  class MySearchView (line 7) | public class MySearchView extends SearchView {
    method MySearchView (line 9) | public MySearchView(Context context) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyWebView.java
  class MyWebView (line 8) | public class MyWebView extends WebView {
    method MyWebView (line 10) | public MyWebView(Context context, AttributeSet attrs) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/NumPickerPref.java
  class NumPickerPref (line 8) | public class NumPickerPref extends DialogPreference {
    method NumPickerPref (line 10) | public NumPickerPref(Context context, AttributeSet attrs) {
    method onGetDefaultValue (line 14) | protected Object onGetDefaultValue(TypedArray a, int index) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/PackageActivityM.java
  class PackageActivityM (line 11) | public class PackageActivityM extends BaseActivity {
    method onCreated (line 15) | protected void onCreated(Bundle savedInstanceState) {
    method onCreateOptionsMenu (line 19) | public boolean onCreateOptionsMenu(Menu menu) {
    method onPrepareOptionsMenu (line 23) | public boolean onPrepareOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 27) | public boolean onOptionsItemSelected(MenuItem item) {
    method onResume (line 31) | protected void onResume() {
    method createDialog (line 36) | public AlertDialog createDialog(String tag, AlertDialogFragment dialog...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/ProgressLinearLayout.java
  class ProgressLinearLayout (line 6) | public class ProgressLinearLayout extends MyLinearLayout {
    method ProgressLinearLayout (line 8) | public ProgressLinearLayout(Context context, AttributeSet attrs) {
    method setVisibility (line 15) | public synchronized void setVisibility(int visibility) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/fwk/SettingsActivityM.java
  class SettingsActivityM (line 9) | public class SettingsActivityM extends BaseActivity
    method onCreated (line 14) | protected void onCreated(Bundle savedInstanceState) {
    method onSaveInstanceState (line 18) | protected void onSaveInstanceState(Bundle outState) {
    method onPreferenceStartFragment (line 23) | public boolean onPreferenceStartFragment(PreferenceFragmentCompat call...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/help/HelpActivity.java
  class HelpActivity (line 30) | public class HelpActivity extends OnBackPressedCallback {
    method HelpActivity (line 34) | public HelpActivity(HelpActivityM activity) {
    method onCreated (line 45) | public void onCreated() {
    method handleOnBackPressed (line 93) | public void handleOnBackPressed() {
    method enableJs (line 101) | private void enableJs() {
    method setFontSize (line 107) | private void setFontSize() {
    method onCreateOptionsMenu (line 116) | public boolean onCreateOptionsMenu(Menu menu) {
    method onPrepareOptionsMenu (line 124) | public boolean onPrepareOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 130) | public boolean onOptionsItemSelected(MenuItem item) {
    class MyWebViewClient (line 157) | private class MyWebViewClient extends WebViewClientCompat {
      method shouldOverrideUrlLoading (line 159) | public boolean shouldOverrideUrlLoading(WebView view, WebResourceReq...
      method onPageFinished (line 172) | public void onPageFinished(WebView view, String url) {
    method start (line 197) | public static void start(Activity activity, String href) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/help/HelpJsInterface.java
  class HelpJsInterface (line 9) | public class HelpJsInterface {
    method HelpJsInterface (line 14) | HelpJsInterface(Activity act) {
    method getBgColor (line 21) | @JavascriptInterface
    method getTextColor (line 26) | @JavascriptInterface
    method getThemeColor (line 31) | @JavascriptInterface
    method isDarkTheme (line 36) | @JavascriptInterface

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/AdbConnectDialog.java
  class AdbConnectDialog (line 46) | public class AdbConnectDialog {
    method AdbConnectDialog (line 54) | public AdbConnectDialog(MainActivity activity, AlertDialogFragment dia...
    method onFirstTryFailed (line 66) | private void onFirstTryFailed() {
    class HostPort (line 97) | private static class HostPort {
      method HostPort (line 102) | public HostPort(String host, int port) {
    method setAutoPairingHostPort (line 110) | private void setAutoPairingHostPort() {
    method stopMdnsPairingListener (line 133) | private void stopMdnsPairingListener() {
    method setConnectHelpText (line 142) | private void setConnectHelpText(boolean afterPairing) {
    method onArrowClicked (line 154) | private void onArrowClicked(View arrow, boolean hideOnly) {
    method createDialog (line 196) | public AlertDialog createDialog() {
    method doPairing (line 213) | private void doPairing() {
    method doPairing (line 241) | private boolean doPairing(String host, int port, String code) {
    method onPairingComplete (line 263) | private void onPairingComplete(boolean result) {
    method autoConnectAfterAutoPairing (line 277) | private boolean autoConnectAfterAutoPairing(boolean paired) {
    method connectToAdb (line 284) | private void connectToAdb(boolean isFirstTry) {
    method connToAdbAndRestartDaemon (line 299) | private boolean connToAdbAndRestartDaemon(String host, int port, boole...
    method callTcpIp (line 341) | private boolean callTcpIp(AdbConnManager connMgr, int port) {
    method waitForTcpIpResponse (line 351) | private void waitForTcpIpResponse(AdbStream adbStream) {
    method onAdbConnect (line 363) | private void onAdbConnect(boolean result, boolean isFirstTry) {
    method dismissDialog (line 381) | private boolean dismissDialog(boolean result) {
    method getPort (line 399) | private static int getPort(CharSequence portStr, TextInputLayout conta...
    method getHost (line 417) | private static String getHost(CharSequence ipStr, TextInputLayout cont...
    class EditTextWatcher (line 430) | private static class EditTextWatcher implements TextWatcher {
      method EditTextWatcher (line 434) | private EditTextWatcher(TextInputLayout container) {
      method beforeTextChanged (line 438) | public void beforeTextChanged(CharSequence s, int start, int count, ...
      method onTextChanged (line 440) | public void onTextChanged(CharSequence s, int start, int before, int...
      method afterTextChanged (line 444) | public void afterTextChanged(Editable s) {}

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/BackupRestoreDialog.java
  class BackupRestoreDialog (line 23) | public class BackupRestoreDialog {
    method BackupRestoreDialog (line 29) | public BackupRestoreDialog(MainActivity activity) {
    method onCreated (line 36) | public void onCreated() {
    method createDialog (line 43) | public AlertDialog createDialog() {
    method doBackupRestore (line 58) | private void doBackupRestore(boolean isBackup, Uri uri) {
    method handleResult (line 96) | private void handleResult(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/DaemonStartProg.java
  class DaemonStartProg (line 18) | public class DaemonStartProg {
    method DaemonStartProg (line 24) | DaemonStartProg(MainActivity activity) {
    method onCreated (line 28) | void onCreated(String intentAction) {
    method startDaemon (line 58) | private void startDaemon(String intentAction) {
    method setDaemonStartProg (line 62) | private void setDaemonStartProg(String prog) {
    method handleStartDaemonResult (line 71) | private void handleStartDaemonResult(DaemonStarter.DaemonStartResult r...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/Feedback.java
  class Feedback (line 13) | class Feedback {
    method Feedback (line 17) | Feedback(MainActivity activity) {
    method askForFeedback (line 23) | void askForFeedback() {
    method showDialog (line 49) | private void showDialog(boolean isYes) {
    class FeedbackDismissListener (line 55) | private class FeedbackDismissListener implements OnDismissListener {
      method onDismiss (line 57) | public void onDismiss(View view) {
      method onDragStateChanged (line 62) | public void onDragStateChanged(int state) {}

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/FeedbackDialogFrag.java
  class FeedbackDialogFrag (line 23) | public class FeedbackDialogFrag extends BottomSheetDialogFrag {
    method show (line 36) | public static void show(int type, FragmentManager fm) {
    method onCreateView (line 44) | public View onCreateView(
    method getFeedbackView (line 57) | private View getFeedbackView(boolean isYes) {
    method getButtonsView (line 90) | private View getButtonsView(int type) {
    class ButtonListener (line 147) | private class ButtonListener implements OnClickListener {
      method ButtonListener (line 151) | private ButtonListener(Runnable task) {
      method onClick (line 155) | public void onClick(View v) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/MainActivity.java
  class MainActivity (line 74) | public class MainActivity extends OnBackPressedCallback {
    method MainActivity (line 80) | public MainActivity(MainActivityM activity) {
    method onCreated (line 120) | public void onCreated() {
    method onNewIntent (line 200) | public void onNewIntent(Intent intent) {
    method onCreateOptionsMenu (line 204) | public boolean onCreateOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 219) | public boolean onOptionsItemSelected(MenuItem item) {
    method handleOnBackPressed (line 238) | public void handleOnBackPressed() {
    method onResume (line 260) | public void onResume() {
    method onPause (line 268) | public void onPause() {
    method onAttachedToWindow (line 272) | public void onAttachedToWindow() {
    method createDialog (line 281) | public AlertDialog createDialog(String tag, AlertDialogFragment dialog...
    method isSecondaryUser (line 312) | private boolean isSecondaryUser() {
    class PkgAdapterCallbackImpl (line 328) | private class PkgAdapterCallbackImpl implements PkgAdapterCallback {
      method onClick (line 330) | public void onClick(Package pkg) {
      method onLongClick (line 334) | public void onLongClick(Package pkg) {
    method setLiveDataObservers (line 341) | public synchronized void setLiveDataObservers() {
    method setMaxProg (line 357) | private void setMaxProg(int progMax) {
    method setNowProg (line 384) | private void setNowProg(int progNow) {
    method onListCompleted (line 392) | private void onListCompleted(int pkgCount) {
    method pkgListReceived (line 418) | private void pkgListReceived(List<Package> packages) {
    method pkgChanged (line 423) | private void pkgChanged(Package pkg) {
    method setRepeatUpdates (line 430) | private void setRepeatUpdates() {
    method onPrefChanged (line 435) | private void onPrefChanged(Integer pref) {
    method showPkgCount (line 442) | private void showPkgCount(int pkgCount) {
    method showSnackBar (line 446) | public void showSnackBar(String text, int sec) {
    method createSnackBar (line 450) | public Snackbar createSnackBar(String text, int sec) {
    method handleIntentActions (line 454) | private void handleIntentActions(Intent intent) {
    method setBigProgVisible (line 465) | public void setBigProgVisible(boolean visible) {
    method setProgVisible (line 473) | public void setProgVisible(boolean visible) {
    method showAppOpsPrivsToast (line 479) | private void showAppOpsPrivsToast() {
    method askForFeedback (line 493) | private void askForFeedback() {
    method setUpSearchView (line 499) | private void setUpSearchView() {
    method collapseSearchView (line 533) | private void collapseSearchView() {
    method hideSearchSettings (line 545) | private void hideSearchSettings() {
    method handleSearchQuery (line 557) | private void handleSearchQuery() {
    method handleSearchQuery (line 561) | public void handleSearchQuery(boolean hideSettings) {
    method setNavigationMenu (line 585) | private void setNavigationMenu() {
    method setBoxesChecked (line 592) | private void setBoxesChecked() {
    method setCheckBoxListeners (line 599) | private void setCheckBoxListeners() {
    method handleNavigationItemSelected (line 611) | private boolean handleNavigationItemSelected(MenuItem item) {
    method handleNavigationItemChecked (line 619) | private boolean handleNavigationItemChecked(MenuItem item) {
    method handleRootCheckBox (line 671) | private void handleRootCheckBox(boolean enable) {
    method setRootCheckBox (line 688) | private void setRootCheckBox(boolean checked, boolean enabled) {
    method handleRootResult (line 694) | private void handleRootResult(boolean granted) {
    method handleAdbCheckBox (line 703) | private void handleAdbCheckBox(boolean enable) {
    method setAdbCheckBox (line 718) | public void setAdbCheckBox(boolean checked, boolean enabled) {
    method openDrawerForPrivileges (line 726) | private void openDrawerForPrivileges() {
    class Data (line 738) | public class Data {
      method Data (line 742) | private Data() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/PackageAdapter.java
  class PackageAdapter (line 31) | public class PackageAdapter extends MyListAdapter<Package, ItemViewHolde...
    method PackageAdapter (line 40) | public PackageAdapter(LifecycleOwner owner, PkgAdapterCallback callbac...
    method getPkg (line 46) | private Package getPkg(int pos) {
    method onCreateViewHolder (line 50) | public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewTyp...
    method onBindViewHolder (line 56) | public void onBindViewHolder(ItemViewHolder holder, int position) {
    class ItemViewHolder (line 60) | class ItemViewHolder extends RecyclerView.ViewHolder
      method ItemViewHolder (line 67) | public ItemViewHolder(RvItemPkgBinding binding) {
      method bind (line 74) | public void bind(int pos) {
      method onClick (line 133) | public void onClick(View v) {
      method onLongClick (line 141) | public boolean onLongClick(View v) {
      method setIcon (line 150) | private void setIcon(Package pkg) {
    method getHighlightSpan (line 164) | private TextAppearanceSpan getHighlightSpan(int currentColor) {
    class DiffUtilItemCallBack (line 172) | private static class DiffUtilItemCallBack extends DiffUtil.ItemCallbac...
      method areItemsTheSame (line 173) | public boolean areItemsTheSame(Package oldItem, Package newItem) {
      method areContentsTheSame (line 177) | public boolean areContentsTheSame(Package oldItem, Package newItem) {
    type PkgAdapterCallback (line 182) | public interface PkgAdapterCallback {
      method onClick (line 184) | void onClick(Package pkg);
      method onLongClick (line 186) | void onLongClick(Package pkg);

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/PkgLongPressDialogFrag.java
  class PkgLongPressDialogFrag (line 34) | public class PkgLongPressDialogFrag extends BottomSheetDialogFrag {
    method PkgLongPressDialogFrag (line 38) | public PkgLongPressDialogFrag(Package pkg) {
    method PkgLongPressDialogFrag (line 42) | public PkgLongPressDialogFrag() {
    method onCreateView (line 46) | public View onCreateView(
    method onCreateDialog (line 108) | public Dialog onCreateDialog(Bundle savedInstanceState) {
    method setPackageEnabledState (line 115) | void setPackageEnabledState() {
    method setPackageEnabledState (line 162) | private void setPackageEnabledState(Package pkg, boolean enabled) {
    method openAppInfo (line 168) | private void openAppInfo() {
    method openAppProc (line 192) | private void openAppProc() {
    method requireDaemon (line 214) | private void requireDaemon() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/main/PrivsCheckBoxFocus.java
  class PrivsCheckBoxFocus (line 28) | public class PrivsCheckBoxFocus {
    method PrivsCheckBoxFocus (line 34) | PrivsCheckBoxFocus(MainActivity act) {
    method doFocus (line 40) | void doFocus() {
    method endFocus (line 47) | void endFocus() {
    method endFocusUnlocked (line 53) | private void endFocusUnlocked() {
    class AnimationFocus (line 60) | private class AnimationFocus {
      method AnimationFocus (line 69) | private AnimationFocus() {
      method end (line 78) | private void end() {
      class DrawerListener (line 84) | private class DrawerListener extends SimpleDrawerListener {
        method onDrawerOpened (line 88) | public synchronized void onDrawerOpened(View drawerView) {
      method scrollToCheckBoxes (line 100) | private void scrollToCheckBoxes() {
      method showOverlayDelayed (line 130) | private void showOverlayDelayed() {
      method showOverlay (line 137) | private void showOverlay() {
      class Overlay (line 191) | private class Overlay extends FrameLayout {
        method Overlay (line 193) | public Overlay() {
        method onDraw (line 217) | protected void onDraw(Canvas canvas) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/AppOpsParser.java
  type AppOpsParser (line 24) | public enum AppOpsParser {
    method getOpsForPackage (line 29) | List<MyPackageOps> getOpsForPackage(int uid, String pkgName, Integer o...
    method getUidOps (line 48) | List<MyPackageOps> getUidOps(int uid) {
    method buildAppOpsList (line 69) | public void buildAppOpsList() {
    method buildAppOpsListInternal (line 73) | private void buildAppOpsListInternal() {
    method fixPermDb (line 127) | public boolean fixPermDb() {
    method getAppOpsNames (line 149) | public List<String> getAppOpsNames() {
    method getAppOpName (line 153) | public String getAppOpName(int op) {
    method getAppOpCode (line 158) | public Integer getAppOpCode(String opName) {
    method getAppOpModeCount (line 163) | public int getAppOpModeCount() {
    method isValidAppOpMode (line 167) | public boolean isValidAppOpMode(int opMode) {
    method opModeToName (line 171) | public String opModeToName(int opMode) {
    method getDependsOn (line 176) | public String getDependsOn(int op) {
    method getOpDefMode (line 189) | Integer getOpDefMode(int op) {
    method getPermToOpCode (line 194) | Integer getPermToOpCode(String perm) {
    method canReadAppOpsNoDaemon (line 202) | private boolean canReadAppOpsNoDaemon() {
    method canReadAppOps (line 206) | public boolean canReadAppOps() {
    method hasAppOps (line 210) | public boolean hasAppOps() {
    method handleException (line 214) | private void handleException(String method, Throwable t) {
    class AppPrivTasksCallbackImpl (line 221) | private static class AppPrivTasksCallbackImpl implements AppPrivTasks....
      method logErr (line 223) | public void logErr(String tag, String method, Throwable e) {
      method logErr (line 227) | public void logErr(String tag, String method, String err) {
      method showError (line 231) | public void showError(int error) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/Package.java
  class Package (line 11) | public class Package {
    method updatePackage (line 27) | void updatePackage(
    method getLabel (line 46) | public String getLabel() {
    method getName (line 50) | public String getName() {
    method getFormattedName (line 54) | public String getFormattedName() {
    method getPermList (line 58) | public List<Permission> getPermList() {
    method getFullPermsList (line 65) | public List<Permission> getFullPermsList() {
    method setSearchPermList (line 69) | public void setSearchPermList(List<Permission> permList) {
    method isFrameworkApp (line 73) | public boolean isFrameworkApp() {
    method isSystemApp (line 77) | public boolean isSystemApp() {
    method isEnabled (line 81) | public boolean isEnabled() {
    method isCriticalApp (line 85) | public boolean isCriticalApp() {
    method isChangeable (line 89) | public boolean isChangeable() {
    method setTotalPermCount (line 93) | public void setTotalPermCount(int count) {
    method getTotalPermCount (line 97) | public int getTotalPermCount() {
    method setPermCount (line 101) | public void setPermCount(int count) {
    method setSearchPermCount (line 105) | public void setSearchPermCount(int count) {
    method getPermCount (line 111) | public String getPermCount() {
    method setTotalAppOpsCount (line 129) | public void setTotalAppOpsCount(int count) {
    method getTotalAppOpsCount (line 133) | public int getTotalAppOpsCount() {
    method setAppOpsCount (line 137) | public void setAppOpsCount(int count) {
    method setSearchAppOpsCount (line 141) | public void setSearchAppOpsCount(int count) {
    method getAppOpsCount (line 145) | private String getAppOpsCount() {
    method getUid (line 157) | public int getUid() {
    method isReferenced (line 161) | public Boolean isReferenced() {
    method shouldShowRefs (line 167) | public boolean shouldShowRefs() {
    method getDate (line 172) | public String getDate() {
    method isRemoved (line 178) | public boolean isRemoved() {
    method setPkgRemoved (line 182) | public void setPkgRemoved(boolean isRemoved) {
    method contains (line 186) | public boolean contains(String queryText) {
    method contains_ (line 204) | private boolean contains_(String queryText) {
    method _contains (line 216) | private boolean _contains(String queryText) {
    method searchableFields (line 239) | private String[] searchableFields() {
    method areContentsTheSame (line 258) | public boolean areContentsTheSame(Package pkg) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/PackageParser.java
  type PackageParser (line 54) | public enum PackageParser {
    method updatePkgListIfChanged (line 80) | public void updatePkgListIfChanged() {
    method updatePkgList (line 86) | public void updatePkgList() {
    method updatePkgList (line 90) | public void updatePkgList(boolean rebuildPkgInfoList) {
    method updatePkgListWithResult (line 98) | public List<Package> updatePkgListWithResult(boolean rebuildPkgInfoLis...
    method updatePkgListInternal (line 105) | private List<Package> updatePkgListInternal() {
    method isUpdating (line 152) | private boolean isUpdating() {
    method buildPkgInfoList (line 156) | private List<PackageInfo> buildPkgInfoList() {
    method clearPkgInfoList (line 199) | public void clearPkgInfoList() {
    method buildRequiredData (line 210) | public void buildRequiredData() {
    method getPkgList (line 251) | public List<Package> getPkgList() {
    method getPkg (line 257) | public Package getPkg(int position) {
    method getPkgPosition (line 267) | public int getPkgPosition(Package pkg) {
    method updatePackage (line 278) | public void updatePackage(Package pkg, boolean filterPerms) {
    method removePackage (line 294) | public void removePackage(Package pkg) {
    method getPkgListLive (line 315) | public LiveData<List<Package>> getPkgListLive() {
    method getChangedPkg (line 319) | public LiveData<Package> getChangedPkg() {
    method getProgMax (line 323) | public LiveData<Integer> getProgMax() {
    method getProgNow (line 327) | public LiveData<Integer> getProgNow() {
    method getListCompleted (line 331) | public LiveData<Integer> getListCompleted() {
    method updateAndPostLivePkgList (line 335) | private void updateAndPostLivePkgList(List<Package> pkgList, boolean i...
    method postLivePkgList (line 353) | private void postLivePkgList(List<Package> pkgList, boolean mustSend) {
    method setRepeatUpdates (line 359) | public void setRepeatUpdates(boolean doRepeatUpdates) {
    method setProgress (line 366) | private void setProgress(int value, boolean isMax, boolean isFinal) {
    method sendListCompleted (line 378) | private void sendListCompleted(int isFinal, int pkgCount) {
    method getProgMsg (line 389) | public int getProgMsg(int progMax) {
    method isPkgUpdated (line 399) | boolean isPkgUpdated(PackageInfo pkgInfo, Package pkg, boolean filterP...
    method isSystemApp (line 455) | private boolean isSystemApp(PackageInfo packageInfo) {
    method getSystemSignatures (line 461) | public List<Integer> getSystemSignatures() {
    method isFrameworkApp (line 473) | private boolean isFrameworkApp(PackageInfo packageInfo) {
    method isFilteredOutPkgName (line 477) | private boolean isFilteredOutPkgName(String pkgName) {
    method isFilteredOutSystemPkg (line 481) | private boolean isFilteredOutSystemPkg(boolean isSystemPkg) {
    method isFilteredOutFrameworkPkg (line 485) | private boolean isFilteredOutFrameworkPkg(boolean isFrameworkPkg) {
    method isFilteredOutUserPkg (line 489) | private boolean isFilteredOutUserPkg(boolean isFrameworkPkg, boolean i...
    method isFilteredOutDisabledPkg (line 493) | private boolean isFilteredOutDisabledPkg(boolean isDisabledPkg) {
    method isFilteredOutNoIconPkg (line 497) | private boolean isFilteredOutNoIconPkg(boolean isNoIconPkg) {
    method isFilteredOutNoPermPkg (line 501) | private boolean isFilteredOutNoPermPkg(Package pkg) {
    method getPermList (line 507) | private List<Permission> getPermList(PackageInfo pkgInfo, Package pkg,...
    method isNotFilteredOut (line 567) | private boolean isNotFilteredOut(Permission perm) {
    method createPerm (line 604) | private boolean createPerm(
    method getPermissionFlags (line 663) | private int getPermissionFlags(String perm, PackageInfo pkgInfo) {
    method createPermsAppOpsNotSet (line 679) | private int[] createPermsAppOpsNotSet(
    method createSetAppOps (line 701) | private int[] createSetAppOps(
    method createExtraAppOps (line 709) | private int[] createExtraAppOps(
    method createAppOpsList (line 714) | private int[] createAppOpsList(
    method createAppOp (line 788) | private int[] createAppOp(
    method getPkgInfo (line 869) | static PackageInfo getPkgInfo(String pkgName, Integer pmFlags) {
    method getProtectionLevel (line 881) | public static int getProtectionLevel(PermissionInfo permInfo) {
    method getManifestPermFlags (line 887) | private ManifestPermFlags getManifestPermFlags(String permName) {
    method getManifestPermFlags (line 902) | public static ManifestPermFlags getManifestPermFlags(PermissionInfo pe...
    class ManifestPermFlags (line 934) | public static class ManifestPermFlags {
    method handleSearchQuery (line 951) | public void handleSearchQuery() {
    method handleSearchQuery (line 955) | private void handleSearchQuery(int isFinal) {
    method doSearchInBg (line 974) | private void doSearchInBg(int isFinal) {
    method updateSearchLists (line 1024) | private void updateSearchLists(Package pkg, boolean removeOnly) {
    method removeSearchPackage (line 1066) | private void removeSearchPackage(Package pkg) {
    method clearSearchLists (line 1073) | private void clearSearchLists() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/PermGroupsMapping.java
  type PermGroupsMapping (line 9) | public enum PermGroupsMapping {
    method get (line 33) | public PermGroupInfo get(String perm, boolean isAppOp) {
    method getGroupId (line 39) | public int getGroupId(String perm, boolean isAppOp) {
    class PermGroupInfo (line 44) | public static class PermGroupInfo {
      method PermGroupInfo (line 49) | private PermGroupInfo(int groupId, int icon) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/Permission.java
  class Permission (line 20) | public class Permission {
    method Permission (line 59) | Permission(
    method Permission (line 99) | Permission(
    method getGroupId (line 139) | public int getGroupId() {
    method getIconResId (line 143) | public int getIconResId() {
    method isAppOp (line 147) | public boolean isAppOp() {
    method isPerUid (line 151) | public boolean isPerUid() {
    method hasUnknownOpMode (line 155) | public boolean hasUnknownOpMode() {
    method isAppOpModeSet (line 159) | public boolean isAppOpModeSet() {
    method getAppOpMode (line 163) | public int getAppOpMode() {
    method getAppOpAccessTime (line 167) | public String getAppOpAccessTime() {
    method hasDependsOnPerm (line 178) | public boolean hasDependsOnPerm() {
    method getDependsOnName (line 182) | public CharSequence getDependsOnName() {
    method setExtraAppOp (line 186) | public void setExtraAppOp() {
    method isExtraAppOp (line 190) | public boolean isExtraAppOp() {
    method getName (line 194) | public String getName() {
    method isGranted (line 198) | public boolean isGranted() {
    method getProtectionLevel (line 202) | public String getProtectionLevel() {
    method isPrivileged (line 206) | public boolean isPrivileged() {
    method hasProviderPkg (line 210) | public boolean hasProviderPkg() {
    method setReference (line 214) | public void setReference(Boolean isReferenced, String reference) {
    method isReferenced (line 219) | public Boolean isReferenced() {
    method getReference (line 223) | public String getReference() {
    method isCritical (line 227) | public boolean isCritical() {
    method isChangeable (line 233) | public boolean isChangeable() {
    method isChangeableInternal (line 240) | private boolean isChangeableInternal() {
    method isAppOpPermChangeable (line 254) | public static boolean isAppOpPermChangeable(String dependsOn) {
    method contains (line 258) | public boolean contains(String queryText, boolean caseSensitive) {
    method containsAnd (line 276) | private boolean containsAnd(String queryText, boolean caseSensitive) {
    method containsNot (line 288) | private boolean containsNot(String queryText, boolean caseSensitive) {
    method areContentsTheSame (line 325) | public boolean areContentsTheSame(Permission newPerm) {
    method isSamePerm (line 353) | public boolean isSamePerm(Permission newPerm) {
    method setAppOpMode (line 359) | public void setAppOpMode(Package pkg, int mode) {
    method toggleState (line 370) | public void toggleState(Package pkg) {
    method createRefStringForDb (line 377) | public String createRefStringForDb() {
    method createRefStringForDb (line 381) | public static String createRefStringForDb(boolean granted) {
    method createRefStringForDb (line 385) | public static String createRefStringForDb(int appOpMode) {
    method isAppOpGranted (line 389) | public static boolean isAppOpGranted(int appOpMode) {
    method getAppOpMode (line 395) | public static int getAppOpMode(boolean granted) {
    method isReferenced (line 399) | public static Boolean isReferenced(String dbRefString, boolean granted) {
    method isReferenced (line 403) | public static Boolean isReferenced(String dbRefString, int appOpMode) {
    method getPermNameString (line 407) | public CharSequence getPermNameString() {
    method getLocalizedProtectionLevel (line 415) | private static String getLocalizedProtectionLevel(String protectionLev...
    method getLocalizedProtLevelString (line 426) | public static String getLocalizedProtLevelString(
    method getLocalizedProtLevelString (line 461) | public String getLocalizedProtLevelString() {
    method getLocalizedPermStateName (line 473) | public String getLocalizedPermStateName() {
    method getLocalizedAppOpModeName (line 481) | public static String getLocalizedAppOpModeName(String appOpModeName) {
    method getLocalizedPermStateName (line 495) | public static String getLocalizedPermStateName(boolean granted) {
    method getLocalizedPermStateNames (line 499) | public static void getLocalizedPermStateNames(
    method getLocalizedAppOpModeNames (line 512) | public static void getLocalizedAppOpModeNames(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/SearchConstants.java
  type SearchConstants (line 7) | public enum SearchConstants {
    method SearchConstants (line 10) | SearchConstants() {
    method recreate (line 37) | public void recreate() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/permsdb/PermissionDao.java
  type PermissionDao (line 10) | @Dao
    method getAll (line 13) | @Query("SELECT * FROM PermissionEntity")
    method getId (line 16) | @Query(
    method insertAll (line 25) | @Insert(onConflict = OnConflictStrategy.REPLACE)
    method deletePkg (line 28) | @Query("DELETE FROM PermissionEntity WHERE pkgName IS :pkgName AND use...
    method deletePerm (line 31) | @Query(
    method deleteAll (line 40) | @Query("DELETE FROM PermissionEntity")
    method deletePerms (line 43) | @Query("DELETE FROM PermissionEntity WHERE id IN (:ids)")
    method deletePerms (line 46) | static void deletePerms(PermissionDao dao, List<Integer> ids) {
    method deleteDuplicates (line 52) | @Query(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/permsdb/PermissionDatabase.java
  class PermissionDatabase (line 6) | @Database(entities = PermissionEntity.class, version = 2, exportSchema =...
    method permissionDao (line 9) | public abstract PermissionDao permissionDao();

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/permsdb/PermissionEntity.java
  class PermissionEntity (line 7) | @Entity
    method PermissionEntity (line 31) | public PermissionEntity() {}
    method PermissionEntity (line 33) | public PermissionEntity(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/parser/permsdb/PermsDb.java
  type PermsDb (line 14) | public enum PermsDb {
    class MigrationV1ToV2 (line 23) | private static class MigrationV1ToV2 extends Migration {
      method MigrationV1ToV2 (line 25) | public MigrationV1ToV2() {
      method migrate (line 29) | public void migrate(SupportSQLiteDatabase database) {
    method getDb (line 37) | public PermissionDao getDb() {
    method refsBuilt (line 45) | public boolean refsBuilt() {
    method buildRefs (line 49) | public boolean buildRefs() {
    method createKey (line 77) | public static String createKey(
    method updateRefs (line 82) | public void updateRefs(
    method getRef (line 91) | public String getRef(String pkgName, String permName, boolean isAppOp,...
    method updateRefsDb (line 103) | public void updateRefsDb(PermissionEntity... entities) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/pkg/PackageActivity.java
  class PackageActivity (line 57) | public class PackageActivity extends OnBackPressedCallback implements Pe...
    method PackageActivity (line 75) | public PackageActivity(PackageActivityM activity) {
    method onCreated (line 98) | public void onCreated() {
    method onCreateOptionsMenu (line 135) | public boolean onCreateOptionsMenu(Menu menu) {
    method onPrepareOptionsMenu (line 175) | public boolean onPrepareOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 184) | public boolean onOptionsItemSelected(MenuItem item) {
    method onResume (line 212) | public void onResume() {
    method handleOnBackPressed (line 216) | public void handleOnBackPressed() {
    method createDialog (line 229) | public AlertDialog createDialog(String tag) {
    method onPermClick (line 277) | public void onPermClick(Permission perm, int yLocation) {
    method onPermLongClick (line 281) | public void onPermLongClick(Permission perm) {
    method onPermSwitchToggle (line 285) | public void onPermSwitchToggle(Permission perm) {
    method updatePkg (line 293) | void updatePkg() {
    method postPkgUpdate (line 305) | private void postPkgUpdate() {
    method sortPermList (line 311) | private void sortPermList() {
    method postPermListUpdate (line 323) | private void postPermListUpdate() {
    method checkEmptyPermissionsList (line 328) | private void checkEmptyPermissionsList() {
    method collapseSearchView (line 354) | private void collapseSearchView() {
    method submitPermList (line 364) | private void submitPermList() {
    method handleSearchQuery (line 374) | private void handleSearchQuery(String queryText) {
    method submitList (line 387) | private void submitList(List<Permission> permList) {
    method isDaemonAlive (line 392) | private boolean isDaemonAlive() {
    method createDangPermChangeWarn (line 400) | private String createDangPermChangeWarn() {
    method setAllReferences (line 411) | private void setAllReferences() {
    method buildRefsFromCurrentPermStates (line 423) | public static void buildRefsFromCurrentPermStates(
    method clearReferences (line 438) | private void clearReferences() {
    method onAppOpModeSelect (line 455) | void onAppOpModeSelect(Permission appOp, int mode) {
    method getAffectedPkgCount (line 463) | private Integer getAffectedPkgCount(Permission appOp) {
    method onAppOpModeSelect (line 472) | private void onAppOpModeSelect(Permission appOp, int mode, Integer aff...
    method setAppOpMode (line 520) | private void setAppOpMode(Permission appOp, int mode) {
    method resetAppOps (line 548) | private void resetAppOps() {
    method onManifestPermStateChanged (line 553) | void onManifestPermStateChanged(Permission perm) {
    method setPermission (line 583) | private void setPermission(Permission perm) {
    method start (line 588) | public static void start(Activity activity, Package pkg, String permFi...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/pkg/PermDetailDialog.java
  class PermDetailDialog (line 18) | class PermDetailDialog {
    method PermDetailDialog (line 22) | PermDetailDialog(PackageActivity act) {
    method show (line 29) | void show(Permission perm, int yLocation) {
    method setPerm (line 92) | private void setPerm(Permission perm) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/pkg/PermLongPressDialogFrag.java
  class PermLongPressDialogFrag (line 25) | public class PermLongPressDialogFrag extends BottomSheetDialogFrag {
    method PermLongPressDialogFrag (line 30) | PermLongPressDialogFrag(Permission perm, Package pkg) {
    method PermLongPressDialogFrag (line 35) | public PermLongPressDialogFrag() {
    method onAttach (line 41) | public void onAttach(Context context) {
    method onCreateView (line 46) | public View onCreateView(
    method onCreateDialog (line 105) | public Dialog onCreateDialog(Bundle savedInstanceState) {
    method excludePerm (line 112) | private void excludePerm() {
    method setOrClearRef (line 119) | private void setOrClearRef(boolean isReferenced, String permState) {
    method setRef (line 133) | static void setRef(Package pkg, Permission perm, String state) {
    method show (line 143) | public static void show(Permission perm, Package pkg, FragmentManager ...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/pkg/PermissionAdapter.java
  class PermissionAdapter (line 29) | public class PermissionAdapter extends MyListAdapter<Permission, ItemVie...
    method PermissionAdapter (line 39) | public PermissionAdapter(Context context, PermAdapterCallback callback...
    method onCreateViewHolder (line 49) | public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewTyp...
    method onBindViewHolder (line 55) | public void onBindViewHolder(ItemViewHolder holder, int position) {
    class ItemViewHolder (line 59) | class ItemViewHolder extends RecyclerView.ViewHolder
      method ItemViewHolder (line 64) | public ItemViewHolder(RvItemPermBinding binding) {
      method bind (line 75) | public void bind(int pos) {
      method onClick (line 170) | public void onClick(View v) {
      method onLongClick (line 180) | public boolean onLongClick(View v) {
    class DiffUtilItemCallBack (line 190) | private static class DiffUtilItemCallBack extends DiffUtil.ItemCallbac...
      method areItemsTheSame (line 192) | public boolean areItemsTheSame(Permission oldItem, Permission newIte...
      method areContentsTheSame (line 196) | public boolean areContentsTheSame(Permission oldItem, Permission new...
    type PermAdapterCallback (line 201) | public interface PermAdapterCallback {
      method onPermClick (line 203) | void onPermClick(Permission perm, int yLocation);
      method onPermLongClick (line 205) | void onPermLongClick(Permission perm);
      method onPermSwitchToggle (line 207) | void onPermSwitchToggle(Permission perm);

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/AppUpdate.java
  class AppUpdate (line 32) | public class AppUpdate {
    method AppUpdate (line 41) | private AppUpdate() {}
    method check (line 43) | public static AppUpdateResult check(boolean notify) {
    method getVersion (line 94) | private static int getVersion(String version) throws NumberFormatExcep...
    method getBetaSubVersion (line 98) | private static int getBetaSubVersion(String version) throws NumberForm...
    method getLatestFossVersion (line 110) | private static String getLatestFossVersion() throws IOException, JSONE...
    method showNotification (line 158) | private static void showNotification(String version) {
    class AppUpdateResult (line 191) | public static class AppUpdateResult {
      method AppUpdateResult (line 196) | private AppUpdateResult(boolean failed, @Nullable String version) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/ExcFiltersData.java
  type ExcFiltersData (line 28) | public enum ExcFiltersData {
    method isCriticalApp (line 36) | public boolean isCriticalApp(String packageName) {
    method getExcludedAppsLabels (line 43) | public CharSequence[] getExcludedAppsLabels() {
    method getExcludedApps (line 48) | public Set<String> getExcludedApps() {
    method getExcludedAppsCount (line 53) | public int getExcludedAppsCount() {
    method isPkgExcluded (line 57) | public boolean isPkgExcluded(String packageName) {
    method canBeExcluded (line 61) | public boolean canBeExcluded(Package pkg) {
    method populateExcludedAppsList (line 67) | private void populateExcludedAppsList(boolean force, boolean loadDefau...
    class Pkg (line 125) | private static class Pkg {
      method Pkg (line 130) | Pkg(SpannableString label, String name) {
    method getExcludedPerms (line 138) | public Set<String> getExcludedPerms() {
    method getExcludedPermsCount (line 143) | public int getExcludedPermsCount() {
    method isPermExcluded (line 147) | public boolean isPermExcluded(String permissionName) {
    method canBeExcluded (line 151) | public boolean canBeExcluded(Permission perm) {
    method populateExcludedPermsList (line 159) | private void populateExcludedPermsList(boolean force) {
    method getExtraAppOps (line 180) | public Set<String> getExtraAppOps() {
    method getExtraAppOpsCount (line 185) | public int getExtraAppOpsCount() {
    method isExtraAppOp (line 189) | public boolean isExtraAppOp(String opName) {
    method populateExtraAppOpsList (line 195) | public void populateExtraAppOpsList(boolean force, boolean loadDefault...
    method updateList (line 229) | public void updateList(String key) {
    method populateLists (line 239) | public void populateLists(boolean force) {
    method resetExcFilters (line 245) | public void resetExcFilters() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/MySettings.java
  type MySettings (line 21) | public enum MySettings {
    method isDebug (line 26) | public boolean isDebug() {
    method setDebugLog (line 30) | public void setDebugLog(boolean debugLog) {
    method getDefPrefs (line 34) | public static SharedPreferences getDefPrefs() {
    method getNoBackupPrefs (line 38) | public static SharedPreferences getNoBackupPrefs() {
    method getBoolPref (line 44) | public boolean getBoolPref(int key, int def) {
    method getBoolPref (line 48) | public boolean getBoolPref(int key, boolean def) {
    method getIntPref (line 57) | public int getIntPref(int key, int def) {
    method getIntegerPref (line 61) | public int getIntegerPref(int key, int defValue) {
    method getLongPref (line 70) | private long getLongPref(int key) {
    method getStringPref (line 79) | public String getStringPref(int key, int def) {
    method getStringPref (line 83) | public String getStringPref(int key, String def) {
    method getSetPref (line 92) | public Set<String> getSetPref(int key) {
    method savePref (line 96) | public void savePref(int key, boolean val) {
    method savePref (line 105) | public void savePref(int key, int val) {
    method savePref (line 114) | private void savePref(int key, long val) {
    method getDarkThemeMode (line 123) | public String getDarkThemeMode() {
    method shouldRemindMissingPrivileges (line 133) | public boolean shouldRemindMissingPrivileges() {
    method setPrivReminderOff (line 139) | public void setPrivReminderOff() {
    method getLocale (line 143) | public String getLocale() {
    method shouldCheckForUpdates (line 147) | public boolean shouldCheckForUpdates() {
    method setCheckForUpdatesTs (line 157) | public void setCheckForUpdatesTs(long timeStamp) {
    method getShowUnsupportedSdkWarning (line 161) | public boolean getShowUnsupportedSdkWarning() {
    method onUnsupportedSdkWarningShown (line 167) | public void onUnsupportedSdkWarningShown() {
    method plusAppLaunchCount (line 171) | public void plusAppLaunchCount() {
    method setMayAskForFeedback (line 179) | public void setMayAskForFeedback(boolean askForFeedback) {
    method shouldAskForFeedback (line 183) | public boolean shouldAskForFeedback() {
    method setAskForFeedbackTs (line 213) | public void setAskForFeedbackTs(boolean longTs) {
    method shouldGrantAppPrivs (line 220) | public boolean shouldGrantAppPrivs() {
    method shouldAskForNotifPerm (line 230) | public boolean shouldAskForNotifPerm() {
    method setAskForNotifPermTs (line 235) | public void setAskForNotifPermTs() {
    method shouldAskToSendCrashReport (line 239) | public boolean shouldAskToSendCrashReport() {
    method shouldClearWebViewCache (line 262) | public boolean shouldClearWebViewCache() {
    method getHelpFontSize (line 270) | public int getHelpFontSize() {
    method setHelpFontSize (line 274) | public void setHelpFontSize(int size) {
    method warnDangerousPkgChanges (line 278) | public boolean warnDangerousPkgChanges() {
    method disableWarnDangerousPkgChanges (line 283) | public void disableWarnDangerousPkgChanges() {
    method warnDangerousPermChanges (line 287) | public boolean warnDangerousPermChanges() {
    method disableWarnDangerousPermChanges (line 293) | public void disableWarnDangerousPermChanges() {
    method isRootEnabled (line 297) | public boolean isRootEnabled() {
    method setRootEnabled (line 302) | public void setRootEnabled(boolean granted) {
    method isAdbEnabled (line 307) | public boolean isAdbEnabled() {
    method setAdbEnabled (line 312) | public void setAdbEnabled(boolean connected) {
    method getRootDaemonPort (line 317) | public int getRootDaemonPort() {
    method saveRootDaemonPort (line 323) | public void saveRootDaemonPort(int port) {
    method getAdbDaemonPort (line 327) | public int getAdbDaemonPort() {
    method saveAdbDaemonPort (line 333) | public void saveAdbDaemonPort(int port) {
    method getAdbPort (line 337) | public int getAdbPort() {
    method saveAdbPort (line 341) | public void saveAdbPort(int port) {
    method setAdbHost (line 351) | public void setAdbHost(String host) {
    method getAdbHost (line 355) | public String getAdbHost() {
    method getDaemonUid (line 359) | public int getDaemonUid() {
    method getDaemonContext (line 366) | public String getDaemonContext() {
    method shouldDaemonExitOnAppDeath (line 374) | public boolean shouldDaemonExitOnAppDeath() {
    method getDaemonPort (line 380) | public int getDaemonPort() {
    method saveDaemonPort (line 385) | public void saveDaemonPort(int port) {
    method shouldRestartDaemon (line 389) | public boolean shouldRestartDaemon() {
    method setDaemonStartTs (line 394) | public void setDaemonStartTs(long ts) {
    method getSuExePath (line 398) | public String getSuExePath() {
    method useUniqueRefForAppOpUidMode (line 403) | public boolean useUniqueRefForAppOpUidMode() {
    method shouldFixPermDb (line 409) | public boolean shouldFixPermDb() {
    method setFixPermDb (line 413) | public void setFixPermDb(boolean fixPermDb) {
    method getQueryText (line 419) | public String getQueryText() {
    method setQueryText (line 423) | public void setQueryText(String queryText) {
    method isSearching (line 427) | public boolean isSearching() {
    method isDeepSearching (line 431) | public boolean isDeepSearching() {
    method isDeepSearchEnabled (line 435) | public boolean isDeepSearchEnabled() {
    method isCaseSensitiveSearch (line 439) | public boolean isCaseSensitiveSearch() {
    method isSpecialSearch (line 445) | public boolean isSpecialSearch() {
    method getExcFiltersEnabled (line 450) | public boolean getExcFiltersEnabled() {
    method setExcFiltersEnabled (line 455) | public void setExcFiltersEnabled(boolean enabled) {
    method saveExcludedList (line 459) | public void saveExcludedList(int key, Set<String> set) {
    method manuallyExcludeApps (line 464) | public boolean manuallyExcludeApps() {
    method excludeNoIconApps (line 471) | public boolean excludeNoIconApps() {
    method excludeUserApps (line 478) | public boolean excludeUserApps() {
    method excludeSystemApps (line 485) | public boolean excludeSystemApps() {
    method excludeFrameworkApps (line 492) | public boolean excludeFrameworkApps() {
    method excludeDisabledApps (line 499) | public boolean excludeDisabledApps() {
    method excludeNoPermsApps (line 506) | public boolean excludeNoPermsApps() {
    method clearExcludedAppsList (line 513) | public void clearExcludedAppsList() {
    method addPkgToExcludedApps (line 517) | public void addPkgToExcludedApps(String pkgName) {
    method excludeInvalidPerms (line 528) | public boolean excludeInvalidPerms() {
    method excludeNotChangeablePerms (line 535) | public boolean excludeNotChangeablePerms() {
    method excludeNotGrantedPerms (line 542) | public boolean excludeNotGrantedPerms() {
    method manuallyExcludePerms (line 549) | public boolean manuallyExcludePerms() {
    method excludeNormalPerms (line 556) | public boolean excludeNormalPerms() {
    method excludeDangerousPerms (line 563) | public boolean excludeDangerousPerms() {
    method excludeSignaturePerms (line 570) | public boolean excludeSignaturePerms() {
    method excludePrivilegedPerms (line 577) | public boolean excludePrivilegedPerms() {
    method clearExcludedPermsList (line 584) | public void clearExcludedPermsList() {
    method addPermToExcludedPerms (line 588) | public void addPermToExcludedPerms(String permName) {
    method excludeAppOpsPerms (line 599) | public boolean excludeAppOpsPerms() {
    method excludeNotSetAppOps (line 606) | public boolean excludeNotSetAppOps() {
    method showExtraAppOps (line 613) | public boolean showExtraAppOps() {
    method clearExtraAppOpsList (line 620) | public void clearExtraAppOpsList() {
    method drawerPrefChanged (line 629) | private void drawerPrefChanged() {
    method recreateMainActivity (line 633) | public void recreateMainActivity() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/fwk/CustomPrefDialogFrag.java
  class CustomPrefDialogFrag (line 13) | public class CustomPrefDialogFrag {
    method CustomPrefDialogFrag (line 15) | private CustomPrefDialogFrag() {}
    method showPrefDialogFrag (line 26) | public static boolean showPrefDialogFrag(Preference preference, Fragme...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/fwk/EditTextPrefDialogFrag.java
  class EditTextPrefDialogFrag (line 10) | public class EditTextPrefDialogFrag extends EditTextPreferenceDialogFrag...
    method onAttach (line 14) | public void onAttach(Context context) {
    method onCreateDialog (line 19) | public Dialog onCreateDialog(Bundle savedInstanceState) {
    method getArgKey (line 25) | String getArgKey() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/fwk/ListPrefDialogFrag.java
  class ListPrefDialogFrag (line 10) | public class ListPrefDialogFrag extends ListPreferenceDialogFragmentComp...
    method onAttach (line 14) | public void onAttach(Context context) {
    method onCreateDialog (line 19) | public Dialog onCreateDialog(Bundle savedInstanceState) {
    method getArgKey (line 25) | String getArgKey() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/fwk/MultiSelectListPrefDialogFrag.java
  class MultiSelectListPrefDialogFrag (line 10) | public class MultiSelectListPrefDialogFrag extends MultiSelectListPrefer...
    method onAttach (line 14) | public void onAttach(Context context) {
    method onCreateDialog (line 19) | public Dialog onCreateDialog(Bundle savedInstanceState) {
    method getArgKey (line 25) | String getArgKey() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/AdvSettingsActivity.java
  class AdvSettingsActivity (line 27) | public class AdvSettingsActivity {
    method AdvSettingsActivity (line 31) | public AdvSettingsActivity(AdvSettingsActivityM activity) {
    method onCreate (line 37) | public void onCreate(Bundle savedInstanceState) {
    method showPermDbResetDialog (line 56) | void showPermDbResetDialog() {
    method startPermDbReset (line 69) | private void startPermDbReset(boolean cleanup, Uri uri) {
    method handleBackupResult (line 91) | private void handleBackupResult(
    method handlePkgList (line 123) | private void handlePkgList(
    method doPermDbCleanup (line 137) | public static int doPermDbCleanup(List<Package> pkgList) {
    method onResetCompleted (line 167) | private void onResetCompleted(AlertDialogFragment frag, int removed) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/AdvSettingsFrag.java
  class AdvSettingsFrag (line 31) | public class AdvSettingsFrag extends PreferenceFragmentCompat
    method onAttach (line 36) | public void onAttach(Context context) {
    method onPause (line 41) | public void onPause() {
    method onResume (line 46) | public void onResume() {
    method findPref (line 51) | private <T extends Preference> T findPref(int keyResId) {
    method onCreatePreferences (line 62) | public void onCreatePreferences(Bundle savedInstanceState, String root...
    method updateUi (line 100) | private void updateUi() {
    method onDisplayPreferenceDialog (line 112) | public void onDisplayPreferenceDialog(Preference preference) {
    method isNotExecutableFile (line 118) | private static boolean isNotExecutableFile(CharSequence path) {
    class SuPathWatcher (line 123) | private static class SuPathWatcher implements TextWatcher {
      method SuPathWatcher (line 127) | private SuPathWatcher(EditText editText) {
      method beforeTextChanged (line 131) | public void beforeTextChanged(CharSequence s, int start, int count, ...
      method onTextChanged (line 133) | public void onTextChanged(CharSequence s, int start, int before, int...
      method afterTextChanged (line 139) | public void afterTextChanged(Editable s) {}
    method onDestroy (line 142) | public void onDestroy() {
    method onSharedPreferenceChanged (line 155) | public void onSharedPreferenceChanged(SharedPreferences sharedPreferen...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/FilterSettingsActivity.java
  class FilterSettingsActivity (line 21) | public class FilterSettingsActivity {
    method FilterSettingsActivity (line 25) | public FilterSettingsActivity(FilterSettingsActivityM activity) {
    method onCreated (line 32) | public void onCreated(Bundle savedInstanceState) {
    method addFrag (line 61) | private void addFrag(Bundle savedInstanceState) {
    method removeFrag (line 73) | private void removeFrag() {
    method onCreateOptionsMenu (line 79) | public boolean onCreateOptionsMenu(Menu menu) {
    method onPrepareOptionsMenu (line 93) | public boolean onPrepareOptionsMenu(Menu menu) {
    method onOptionsItemSelected (line 102) | public boolean onOptionsItemSelected(MenuItem item) {
    method createDialog (line 132) | public AlertDialog createDialog(String tag) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/FilterSettingsFragment.java
  class FilterSettingsFragment (line 30) | public class FilterSettingsFragment extends PreferenceFragmentCompat
    method onAttach (line 60) | public void onAttach(Context context) {
    method onPause (line 65) | public void onPause() {
    method onResume (line 70) | public void onResume() {
    method onCreatePreferences (line 75) | public void onCreatePreferences(Bundle savedInstanceState, String root...
    method updateViews (line 123) | private void updateViews() {
    method buildAppOpsNamesList (line 195) | private Pair<String[], CharSequence[]> buildAppOpsNamesList() {
    class RedTextSpan (line 219) | private static class RedTextSpan extends MetricAffectingSpan {
      method updateDrawState (line 221) | public void updateDrawState(TextPaint tp) {
      method updateMeasureState (line 225) | public void updateMeasureState(TextPaint textPaint) {
    method updateExcludedAppsView (line 230) | private void updateExcludedAppsView(
    method updateExcludedPermsView (line 252) | private void updateExcludedPermsView(
    method updateExtraAppOpsView (line 274) | private void updateExtraAppOpsView(
    method onDisplayPreferenceDialog (line 305) | public void onDisplayPreferenceDialog(Preference preference) {
    method onSharedPreferenceChanged (line 311) | public void onSharedPreferenceChanged(SharedPreferences sharedPreferen...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SearchSettingsFrag.java
  class SearchSettingsFrag (line 16) | public class SearchSettingsFrag extends PreferenceFragmentCompat
    method onAttach (line 21) | public void onAttach(Context context) {
    method onPause (line 26) | public void onPause() {
    method onResume (line 31) | public void onResume() {
    method onCreatePreferences (line 36) | public void onCreatePreferences(Bundle savedInstanceState, String root...
    method onDisplayPreferenceDialog (line 44) | public void onDisplayPreferenceDialog(Preference preference) {
    method onSaveInstanceState (line 48) | public void onSaveInstanceState(Bundle outState) {}
    method onSharedPreferenceChanged (line 50) | public void onSharedPreferenceChanged(SharedPreferences sharedPreferen...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SettingsActivity.java
  class SettingsActivity (line 17) | public class SettingsActivity extends OnBackPressedCallback {
    method SettingsActivity (line 21) | public SettingsActivity(SettingsActivityM activity) {
    method onCreated (line 30) | public void onCreated(Bundle savedInstanceState) {
    method handleOnBackPressed (line 57) | public void handleOnBackPressed() {
    method onSaveInstanceState (line 61) | public void onSaveInstanceState(Bundle outState) {
    method onPreferenceStartFragment (line 71) | public boolean onPreferenceStartFragment(Preference pref) {
    method setActionBarTitle (line 87) | void setActionBarTitle(String title) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SettingsFrag.java
  class SettingsFrag (line 9) | public class SettingsFrag extends PreferenceFragmentCompat {
    method onStart (line 13) | public void onStart() {
    method onResume (line 18) | public void onResume() {
    method findPref (line 23) | private <T extends Preference> T findPref(int key) {
    method onCreatePreferences (line 27) | public void onCreatePreferences(Bundle savedInstanceState, String root...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SettingsFragGeneral.java
  class SettingsFragGeneral (line 20) | public class SettingsFragGeneral extends PreferenceFragmentCompat
    method onAttach (line 25) | public void onAttach(Context context) {
    method onPause (line 30) | public void onPause() {
    method onResume (line 35) | public void onResume() {
    method onCreatePreferences (line 40) | public void onCreatePreferences(Bundle savedInstanceState, String root...
    method onDisplayPreferenceDialog (line 48) | public void onDisplayPreferenceDialog(Preference preference) {
    method onSharedPreferenceChanged (line 54) | public void onSharedPreferenceChanged(SharedPreferences sharedPreferen...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SettingsFragTheme.java
  class SettingsFragTheme (line 16) | public class SettingsFragTheme extends PreferenceFragmentCompat
    method onAttach (line 21) | public void onAttach(Context context) {
    method onPause (line 26) | public void onPause() {
    method onResume (line 31) | public void onResume() {
    method onCreatePreferences (line 36) | public void onCreatePreferences(Bundle savedInstanceState, String root...
    method onDisplayPreferenceDialog (line 45) | public void onDisplayPreferenceDialog(Preference preference) {
    method onSharedPreferenceChanged (line 51) | public void onSharedPreferenceChanged(SharedPreferences sharedPreferen...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/privs/AdbConnManager.java
  class AdbConnManager (line 52) | public class AdbConnManager extends AbsAdbConnectionManager {
    method AdbConnManager (line 57) | public AdbConnManager() throws AdbException {
    method init (line 71) | private void init()
    method getPrivateKey (line 124) | protected PrivateKey getPrivateKey() {
    method getCertificate (line 128) | protected Certificate getCertificate() {
    method getDeviceName (line 132) | protected String getDeviceName() {
    method readCertificateFromFile (line 138) | private static Certificate readCertificateFromFile() throws IOExceptio...
    method writeCertificateToFile (line 146) | private static void writeCertificateToFile(Certificate certificate)
    method readPrivateKeyFromFile (line 162) | private static PrivateKey readPrivateKeyFromFile()
    method writePrivateKeyToFile (line 182) | private static void writePrivateKeyToFile(PrivateKey privateKey) throw...
    method getFile (line 189) | private static File getFile(String file) throws IOException {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/privs/DaemonHandler.java
  type DaemonHandler (line 43) | public enum DaemonHandler {
    method startDaemon (line 50) | private boolean startDaemon() {
    method startDaemon (line 56) | public boolean startDaemon(Boolean preferRoot) {
    method startDaemonInternal (line 67) | private boolean startDaemonInternal(boolean preferRoot) {
    method connectToDaemon (line 102) | private boolean connectToDaemon() {
    method savePort (line 143) | private void savePort(int port) {
    method onBinderReceived (line 149) | public void onBinderReceived(Intent intent) {
    method onHelloReceived (line 182) | private void onHelloReceived(DaemonState state) {
    method waitForHello (line 217) | private boolean waitForHello() {
    method onGreetingsEnd (line 222) | private void onGreetingsEnd() {
    method daemonStopped (line 226) | private void daemonStopped() {
    method onDaemonDied (line 232) | private void onDaemonDied() {
    method stopDaemon (line 260) | public boolean stopDaemon() {
    class IPrivTasksCb (line 284) | private class IPrivTasksCb extends IPrivTasksCallback.Stub {
      method IPrivTasksCb (line 288) | public IPrivTasksCb(IPrivTasks privTasks) {
      method hello (line 292) | public void hello(DaemonState daemonState) {
      method showError (line 297) | public void showError(int error) {
      method saveLog (line 301) | public void saveLog(String stackTrace) {
    method showError (line 306) | public void showError(int error) {
    method isDaemonAlive (line 316) | public boolean isDaemonAlive() {
    method isDaemonAlive (line 322) | public boolean isDaemonAlive(boolean showToast, boolean tryConnect) {
    method isPreferRoot (line 341) | public Boolean isPreferRoot() {
    method getUid (line 348) | public Integer getUid() {
    method getContext (line 357) | public String getContext() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/privs/DaemonIface.java
  type DaemonIface (line 21) | public enum DaemonIface {
    method onDaemonStarted (line 28) | void onDaemonStarted(IPrivTasks privTasks) {
    method onDaemonStopped (line 32) | void onDaemonStopped() {
    method isDaemonAlive (line 38) | private boolean isDaemonAlive() {
    method setExitOnAppDeath (line 42) | public void setExitOnAppDeath() {
    method getPrivsStatus (line 57) | public PrivsStatus getPrivsStatus() {
    method setDebug (line 74) | public void setDebug(IBinder logCb) {
    method dumpHeap (line 89) | public boolean dumpHeap() {
    method getAppOpsLists (line 108) | public AppOpsLists getAppOpsLists() {
    method getPermFixedFlags (line 125) | public PermFixedFlags getPermFixedFlags() {
    method getPackagesForUid (line 142) | public String[] getPackagesForUid(int uid) {
    method getOpsForPkg (line 163) | public List<MyPackageOps> getOpsForPkg(int uid, String pkgName, int[] ...
    method getPermFlags (line 186) | public Integer getPermFlags(String permName, String pkgName, int userI...
    method setPermState (line 203) | public void setPermState(boolean grant, String pkgName, String permNam...
    method setAppOpMode (line 222) | public void setAppOpMode(int uid, String pkgName, int op, int mode) {
    method resetAppOps (line 237) | public void resetAppOps(int userId, String pkgName) {
    method setPkgState (line 252) | public void setPkgState(boolean enable, String pkgName, int userId) {
    method openAppInfo (line 271) | public void openAppInfo(String pkgName, int userId) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/privs/DaemonStarter.java
  type DaemonStarter (line 14) | public enum DaemonStarter {
    method startPrivDaemon (line 19) | public void startPrivDaemon(
    method startDaemonLocked (line 28) | private synchronized void startDaemonLocked(
    method startPrivDaemon (line 40) | public synchronized int startPrivDaemon(boolean restart, boolean prefe...
    method connectOrStartDaemon (line 44) | private synchronized int connectOrStartDaemon(
    method switchToRootOrAdbDaemon (line 106) | public void switchToRootOrAdbDaemon(boolean preferRoot) {
    method stopDaemon (line 117) | public void stopDaemon(boolean preferRoot) {
    method getLiveProg (line 131) | public LiveEvent<String> getLiveProg() {
    method getLiveStartResult (line 135) | public LiveEvent<DaemonStartResult> getLiveStartResult() {
    method setProgress (line 139) | private void setProgress(int msg) {
    class DaemonStartResult (line 143) | public static class DaemonStartResult {
      method DaemonStartResult (line 149) | private DaemonStartResult(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/privs/NativeDaemon.java
  type NativeDaemon (line 29) | public enum NativeDaemon {
    method NativeDaemon (line 39) | NativeDaemon(boolean isAdb) {
    method connectToCheckAlive (line 56) | private void connectToCheckAlive() {
    method connectToDaemon (line 76) | private void connectToDaemon(int port, boolean printException) {
    method startRootDaemon (line 122) | private boolean startRootDaemon() {
    method startAdbDaemon (line 150) | private boolean startAdbDaemon(
    method waitForPort (line 225) | private void waitForPort(BufferedReader reader) {
    method stopDaemon (line 248) | public void stopDaemon() {
    method stopDaemonUnlocked (line 256) | private void stopDaemonUnlocked() {
    method daemonStopped (line 261) | private void daemonStopped(boolean holdLock) {
    method savePort (line 277) | private void savePort(int port) {
    method setExitOnAppDeath (line 285) | public void setExitOnAppDeath() {
    method setExitOnAppDeathUnlocked (line 293) | public void setExitOnAppDeathUnlocked() {
    method isAlive (line 297) | private boolean isAlive(boolean tryConnect) {
    method isAlive (line 301) | private boolean isAlive(boolean tryConnect, boolean forAutoExit) {
    method run (line 320) | public void run(String cmd, boolean background) {
    method runDaemon (line 324) | public void runDaemon(String codeWord) {
    method sendCommand (line 332) | private void sendCommand(String cmd) {
    method sendCommandLocked (line 336) | private void sendCommandLocked(String cmd) {
    method sendCmd (line 345) | void sendCmd(String cmd) {
    class State (line 354) | private static class State {
      method State (line 358) | private State(PrintWriter writer) {
    method hasRoot (line 363) | public static boolean hasRoot(boolean tryConnect) {
    method getRoot (line 367) | public static boolean getRoot() {
    method getRoot (line 371) | public static boolean getRoot(boolean ifEnabledOnly) {
    method hasAdb (line 376) | public static boolean hasAdb(boolean tryConnect) {
    method getAdb (line 380) | public static boolean getAdb() {
    method getAdb (line 384) | private static boolean getAdb(
    method getAdb (line 394) | public static boolean getAdb(
    method forceGetAdb (line 401) | public static boolean forceGetAdb(boolean retryConnect) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/profile/PermProfileBackupRestore.java
  class PermProfileBackupRestore (line 7) | public class PermProfileBackupRestore {
    method backup (line 9) | public static int backup(XmlSerializer ignored) throws IOException {
    method restore (line 13) | public static int restore(InputStream ignored) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/svc/AdbConnectSvc.java
  class AdbConnectSvc (line 24) | public class AdbConnectSvc {
    method AdbConnectSvc (line 30) | public AdbConnectSvc(AdbConnectSvcM svc) {
    method onStartCommand (line 37) | public int onStartCommand(Intent intent) {
    method connToAdbAndStartDaemon (line 62) | private void connToAdbAndStartDaemon(String host, int port) {
    method startDaemon (line 96) | private void startDaemon() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/svc/DaemonRcvSvc.java
  class DaemonRcvSvc (line 13) | public class DaemonRcvSvc {
    method DaemonRcvSvc (line 17) | public DaemonRcvSvc(DaemonRcvSvcM svc) {
    method onStartCommand (line 21) | public int onStartCommand(Intent intent) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/svc/LogcatSvc.java
  class LogcatSvc (line 41) | public class LogcatSvc {
    method LogcatSvc (line 47) | public LogcatSvc(LogcatSvcM svc) {
    method onStartCommand (line 54) | public int onStartCommand(Intent intent) {
    method onDestroy (line 75) | public void onDestroy() {
    method createSvcNotification (line 107) | private void createSvcNotification() {
    method startLogging (line 136) | private void startLogging(Uri logFile) {
    method sendDmnCallback (line 172) | private void sendDmnCallback() {
    method onFailed (line 178) | private void onFailed() {
    class Timer (line 185) | private class Timer extends CountDownTimer {
      method Timer (line 187) | private Timer() {
      method onTick (line 194) | public void onTick(long millisUntilFinished) {
      method onFinish (line 198) | public void onFinish() {
      method setNotificationProgress (line 204) | private void setNotificationProgress(int now) {
    class LogCallback (line 218) | private static class LogCallback extends ILogCallback.Stub {
      method LogCallback (line 222) | private LogCallback(LogcatSvc svc) {
      method writeToLogFile (line 226) | public boolean writeToLogFile(String line) {
    method writeToLogFile (line 235) | private boolean writeToLogFile(String line) {
    method start (line 246) | public static void start(Uri logFile) {
    method stopSvc (line 250) | public static void stopSvc() {
    method sendDaemonCallback (line 254) | public static void sendDaemonCallback() {
    method sendIntent (line 260) | private static void sendIntent(Intent intent) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/ApiUtils.java
  class ApiUtils (line 22) | public class ApiUtils {
    method ApiUtils (line 24) | private ApiUtils() {}
    method getString (line 26) | public static String getString(int resId, Object... args) {
    method getQtyString (line 30) | public static String getQtyString(int resId, int qty, Object... args) {
    method getInt (line 34) | public static int getInt(int resId) {
    method sendMail (line 38) | public static void sendMail(Activity activity, String body) {
    method sendMail (line 42) | public static boolean sendMail(Activity activity, String subject, Stri...
    method openWebUrl (line 58) | public static boolean openWebUrl(Activity activity, String url) {
    method getMyAppInfo (line 88) | public static ApplicationInfo getMyAppInfo() {
    method getAppInfo (line 96) | public static ApplicationInfo getAppInfo(String pkg, int flags)
    method getMyPkgInfo (line 105) | public static PackageInfo getMyPkgInfo() {
    method getMyPkgInfo (line 109) | public static PackageInfo getMyPkgInfo(int flags) {
    method getPkgInfo (line 117) | public static PackageInfo getPkgInfo(String pkg, int flags)
    method getInstalledPackages (line 126) | public static List<PackageInfo> getInstalledPackages(int flags) {
    method resolveActivity (line 134) | public static ResolveInfo resolveActivity(Intent intent, int flags) {
    method resolveService (line 142) | public static ResolveInfo resolveService(Intent intent, int flags) {
    method setTargetFragment (line 150) | public static void setTargetFragment(Fragment source, Fragment target) {
    method hasAppOpsPerm (line 154) | public static boolean hasAppOpsPerm() {
    method hasNotifPerm (line 158) | public static boolean hasNotifPerm() {
    method hasPerm (line 163) | public static boolean hasPerm(String perm) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/AppLifecycle.java
  class AppLifecycle (line 9) | public class AppLifecycle {
    method AppLifecycle (line 13) | private AppLifecycle() {}
    method isAppInFg (line 17) | public static boolean isAppInFg() {
    method isAppVisible (line 21) | public static boolean isAppVisible() {
    method init (line 25) | public static void init(Application app) {
    class Callbacks (line 29) | private static class Callbacks implements Application.ActivityLifecycl...
      method onActivityCreated (line 37) | public void onActivityCreated(Activity activity, Bundle savedInstanc...
      method onActivityStarted (line 41) | public void onActivityStarted(Activity activity) {
      method onActivityResumed (line 45) | public void onActivityResumed(Activity activity) {}
      method onActivityPaused (line 47) | public void onActivityPaused(Activity activity) {}
      method onActivityStopped (line 49) | public void onActivityStopped(Activity activity) {
      method onActivitySaveInstanceState (line 53) | public void onActivitySaveInstanceState(Activity activity, Bundle ou...
      method onActivityDestroyed (line 55) | public void onActivityDestroyed(Activity activity) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/LocaleUtils.java
  class LocaleUtils (line 12) | public class LocaleUtils {
    method LocaleUtils (line 14) | private LocaleUtils() {}
    method setLocale (line 16) | public static Context setLocale(Context context) {
    method updateConfiguration (line 25) | private static void updateConfiguration(Resources res, Configuration c...
    method setLocale (line 29) | public static Configuration setLocale(Configuration config) {
    method setLocale (line 33) | private static Configuration setLocale(Configuration config, Locale lo...
    method getLocale (line 39) | private static Locale getLocale() {
    method toLocalizedNum (line 50) | public static String toLocalizedNum(long num) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/LogUtils.java
  class LogUtils (line 31) | public class LogUtils {
    method LogUtils (line 35) | private LogUtils() {}
    method getCrashLogFile (line 37) | public static File getCrashLogFile() {
    method createCrashLogFile (line 48) | public static File createCrashLogFile() {
    method showCrashNotification (line 65) | public static void showCrashNotification(String stackTrace, boolean is...
    method getDeviceInfo (line 115) | public static String getDeviceInfo() {
    method getAppState (line 132) | public static String getAppState() {
    method isOfficialRelease (line 147) | public static boolean isOfficialRelease() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/NotifUtils.java
  class NotifUtils (line 24) | public class NotifUtils {
    method NotifUtils (line 29) | private NotifUtils() {}
    method askForNotifPerm (line 31) | public static void askForNotifPerm(
    method createNotifChannel (line 54) | public static void createNotifChannel(String id, String name, int impo...
    method createSilentFgNotif (line 63) | public static Notification createSilentFgNotif(
    method notify (line 80) | public static void notify(int id, Notification notif) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/SmallDimMarginSpan.java
  class SmallDimMarginSpan (line 7) | public class SmallDimMarginSpan extends ReplacementSpan {
    method getSize (line 9) | public int getSize(Paint paint, CharSequence text, int start, int end,...
    method draw (line 17) | public void draw(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/StdErrLogServer.java
  class StdErrLogServer (line 16) | public class StdErrLogServer extends ServerSocket {
    method StdErrLogServer (line 24) | public StdErrLogServer(String tag, StreamClosedCallback callback) thro...
    class ConnWaiter (line 34) | private class ConnWaiter implements Callable<Void> {
      method call (line 36) | public Void call() throws Exception {
    method waitForConn (line 46) | public void waitForConn() throws ExecutionException, InterruptedExcept...
    method readStdErr (line 50) | private void readStdErr(InputStream errStream) {
    type StreamClosedCallback (line 65) | public interface StreamClosedCallback {
      method onClose (line 67) | void onClose();

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/StringUtils.java
  class StringUtils (line 25) | public class StringUtils {
    method StringUtils (line 27) | private StringUtils() {}
    method htmlToString (line 29) | public static Spanned htmlToString(int resId) {
    method htmlToString (line 33) | public static Spanned htmlToString(String str) {
    method breakParas (line 76) | public static SpannableStringBuilder breakParas(String string) {
    method breakParas (line 80) | public static SpannableStringBuilder breakParas(SpannableStringBuilder...
    method getHighlightString (line 109) | public static SpannableString getHighlightString(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/UiUtils.java
  class UiUtils (line 31) | public class UiUtils {
    method UiUtils (line 33) | private UiUtils() {}
    method isNightMode (line 35) | public static boolean isNightMode(Activity activity) {
    method dpToPx (line 40) | public static int dpToPx(float dp) {
    method colorIntToRGB (line 46) | public static String colorIntToRGB(int color, boolean retainAlpha) {
    method getColor (line 54) | public static int getColor(Activity activity, int colorAttrResId) {
    method getBgColor (line 58) | public static int getBgColor(Activity activity) {
    method getSharpBgColor (line 62) | public static int getSharpBgColor(Activity activity) {
    method getDimBgColor (line 67) | public static int getDimBgColor(Activity activity) {
    method getAccentColor (line 72) | public static int getAccentColor() {
    method onCreateLayout (line 76) | public static void onCreateLayout(ViewGroup view) {
    method onCreateDialog (line 82) | public static void onCreateDialog(Dialog dialog, Activity activity) {
    method removeButtonPadding (line 93) | public static AlertDialog removeButtonPadding(AlertDialog dialog) {
    method getTextHighlightSpan (line 103) | public static TextAppearanceSpan getTextHighlightSpan(int colorInt) {
    method showToast (line 112) | public static void showToast(String msg) {
    method showToast (line 118) | public static void showToast(int resId, Object... args) {
    method showSnackBar (line 124) | public static void showSnackBar(
    method createSnackBar (line 134) | public static Snackbar createSnackBar(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/UserUtils.java
  class UserUtils (line 7) | public class UserUtils {
    method UserUtils (line 9) | private UserUtils() {}
    method getUserId (line 11) | public static int getUserId(int uid) {
    method getUserId (line 15) | public static int getUserId() {
    method getPackagesForUid (line 19) | public static String[] getPackagesForUid(int uid) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/Utils.java
  class Utils (line 9) | public class Utils {
    method Utils (line 11) | private Utils() {}
    method copyStream (line 13) | public static boolean copyStream(String tag, InputStream input, Output...
    method getAndroidVersionInt (line 28) | public static String getAndroidVersionInt() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveBgTask.java
  class LiveBgTask (line 7) | public class LiveBgTask {
    method LiveBgTask (line 11) | public LiveBgTask(LifecycleOwner owner, Runnable task) {
    method execute (line 16) | public void execute() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveEvent.java
  class LiveEvent (line 13) | public class LiveEvent<T> extends MutableLiveData<T> {
    method LiveEvent (line 17) | public LiveEvent(boolean oneshot) {
    method observe (line 24) | public void observe(LifecycleOwner owner, Observer<? super T> observer) {
    method observeForever (line 32) | public void observeForever(Observer<? super T> observer) {
    method isNewObserver (line 40) | private boolean isNewObserver(Observer<? super T> observer) {
    method removeObserver (line 44) | public void removeObserver(Observer<? super T> observer) {
    method setValue (line 55) | public void setValue(T value) {
    method setValue (line 59) | public void setValue(T value, boolean mustSend) {
    method postValue (line 70) | public void postValue(T value, boolean mustSend) {
    class ObserverWrapper (line 77) | private static class ObserverWrapper<T> implements Observer<T> {
      method ObserverWrapper (line 82) | private ObserverWrapper(Observer<? super T> observer, boolean onesho...
      method setPending (line 89) | private void setPending() {
      method addMustValue (line 97) | private void addMustValue(T value) {
      method onChanged (line 104) | public void onChanged(T t) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveMinDelayParamTask.java
  class LiveMinDelayParamTask (line 11) | public class LiveMinDelayParamTask<T> {
    method LiveMinDelayParamTask (line 15) | public LiveMinDelayParamTask(
    method cancelAndRunOrSchedule (line 33) | public void cancelAndRunOrSchedule(T param) {
    method cancelAndRunNow (line 37) | public void cancelAndRunNow(T param) {
    method cancelAndRunOrSchedule (line 43) | private void cancelAndRunOrSchedule(T param, boolean runNow) {
    method shutdownNow (line 59) | public void shutdownNow() {
    method runWithParam (line 66) | private void runWithParam(RunnableWithParam<T> task) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveSchedParamTask.java
  class LiveSchedParamTask (line 8) | public class LiveSchedParamTask<T> {
    method LiveSchedParamTask (line 12) | public LiveSchedParamTask(
    method runWithParam (line 22) | private void runWithParam(RunnableWithParam<T> task) {
    method cancelAndSchedule (line 34) | public void cancelAndSchedule(T param) {
    method cancel (line 43) | public void cancel() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveSchedTask.java
  class LiveSchedTask (line 9) | public class LiveSchedTask {
    method LiveSchedTask (line 15) | public LiveSchedTask(
    method LiveSchedTask (line 25) | private LiveSchedTask(
    method cancelAndSchedule (line 46) | public void cancelAndSchedule() {
    method cancel (line 50) | public void cancel() {
    method runAndShutdown (line 54) | private void runAndShutdown(Runnable task) {
    method isAlive (line 59) | public boolean isAlive() {
    method shutdownNow (line 63) | public void shutdownNow() {
    class Task (line 67) | private class Task implements Runnable, LifecycleWatcher.LifecycleCall...
      method Task (line 71) | private Task(Runnable task) {
      method run (line 75) | public void run() {
      method onDestroyed (line 86) | public void onDestroyed() {
    method schedule (line 92) | public static void schedule(

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveSingleParamTask.java
  class LiveSingleParamTask (line 9) | public class LiveSingleParamTask<T> extends SingleParamTask<T> {
    method LiveSingleParamTask (line 11) | public LiveSingleParamTask(LifecycleOwner owner, RunnableWithParam<T> ...

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveTasksQueue.java
  class LiveTasksQueue (line 10) | public class LiveTasksQueue {
    method LiveTasksQueue (line 12) | protected LiveTasksQueue(LifecycleOwner owner, Object task) {
    method LiveTasksQueue (line 17) | public LiveTasksQueue(LifecycleOwner owner, BgTask task) {
    method LiveTasksQueue (line 21) | public LiveTasksQueue(LifecycleOwner owner, long msDelay) {
    method onDestroyed (line 25) | protected void onDestroyed() {
    method isAlive (line 32) | protected boolean isAlive() {
    method onUi (line 36) | public LiveTasksQueue onUi(FgTask task) {
    method delay (line 41) | public LiveTasksQueue delay(long msDelay) {
    method addTask (line 48) | protected void addTask(Object task) {
    method assertNotRunning (line 58) | private void assertNotRunning() {
    method start (line 68) | public void start() {
    method start (line 72) | public void start(boolean blockedIfInBg) {
    method startBlocked (line 80) | public void startBlocked() {
    method run (line 97) | private void run() {
    method run (line 110) | protected void run(Object task) {
    type BgTask (line 118) | public interface BgTask extends Runnable {}
    type FgTask (line 120) | public interface FgTask extends Runnable {}

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveTasksQueueTyped.java
  class LiveTasksQueueTyped (line 5) | public class LiveTasksQueueTyped<T> extends LiveTasksQueue {
    method LiveTasksQueueTyped (line 7) | public LiveTasksQueueTyped(LifecycleOwner owner, BgTaskForResult<T> ta...
    method onDestroyed (line 11) | protected void onDestroyed() {
    method onUi (line 16) | public LiveTasksQueueTyped<T> onUi(FgTask task) {
    method onUiWith (line 21) | public LiveTasksQueueTyped<T> onUiWith(FgTaskWithResult<T> task) {
    method inBgWithFor (line 26) | public LiveTasksQueueTyped<T> inBgWithFor(BgTaskWithForResult<T> task) {
    method delay (line 31) | public LiveTasksQueueTyped<T> delay(long msDelay) {
    method run (line 38) | protected void run(Object task) {
    type BgTaskForResult (line 75) | public interface BgTaskForResult<E> {
      method run (line 77) | E run();
    type BgTaskWithResult (line 80) | public interface BgTaskWithResult<E> {
      method run (line 82) | void run(E result);
    type BgTaskWithForResult (line 85) | public interface BgTaskWithForResult<E> {
      method run (line 87) | E run(E result);
    type FgTaskForResult (line 90) | public interface FgTaskForResult<E> {
      method run (line 92) | E run();
    type FgTaskWithResult (line 95) | public interface FgTaskWithResult<E> {
      method run (line 97) | void run(E result);
    type FgTaskWithForResult (line 100) | public interface FgTaskWithForResult<E> {
      method run (line 102) | E run(E result);

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveUiParamTask.java
  class LiveUiParamTask (line 8) | public class LiveUiParamTask<T> {
    method LiveUiParamTask (line 13) | public LiveUiParamTask(LifecycleOwner owner, RunnableWithParam<T> task) {
    method runWithParam (line 18) | private void runWithParam(RunnableWithParam<T> task) {
    method post (line 22) | public void post(T param, boolean waitForCompletion) {
    method stop (line 38) | public void stop() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveUiTask.java
  class LiveUiTask (line 6) | public class LiveUiTask {
    method LiveUiTask (line 10) | public LiveUiTask(LifecycleOwner owner, Runnable task) {
    method post (line 15) | public void post() {
    method post (line 19) | public void post(boolean waitForCompletion) {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveUiWaitTask.java
  class LiveUiWaitTask (line 8) | public class LiveUiWaitTask {
    method LiveUiWaitTask (line 10) | private LiveUiWaitTask(LifecycleOwner owner, Runnable task) {
    method post (line 18) | public static LiveUiWaitTask post(Runnable task) {
    method waitForMe (line 24) | public void waitForMe() {
    class LiveWaitTask (line 31) | private class LiveWaitTask implements Runnable, LifecycleWatcher.Lifec...
      method LiveWaitTask (line 35) | private LiveWaitTask(Runnable task) {
      method run (line 39) | public void run() {
      method onDestroyed (line 47) | public void onDestroyed() {

FILE: app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/UiRunner.java
  class UiRunner (line 8) | public class UiRunner {
    method post (line 12) | public static void post(Runnable task) {
    method post (line 20) | public static void post(LifecycleOwner owner, Runnable task) {

FILE: help/assets/javascripts/lunr/tinyseg.js
  function TinySegmenter (line 33) | function TinySegmenter() {

FILE: help/assets/javascripts/lunr/wordcut.js
  function s (line 1) | function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&re...
  function isMatch (line 421) | function isMatch(pat, offset, ch) {
  function replacer (line 704) | function replacer(key, value) {
  function truncate (line 717) | function truncate(s, n) {
  function getMessage (line 725) | function getMessage(self) {
  function fail (line 742) | function fail(actual, expected, message, operator, stackStartFunction) {
  function ok (line 762) | function ok(value, message) {
  function _deepEqual (line 793) | function _deepEqual(actual, expected) {
  function isArguments (line 838) | function isArguments(object) {
  function objEquiv (line 842) | function objEquiv(a, b) {
  function expectedException (line 911) | function expectedException(actual, expected) {
  function _throws (line 927) | function _throws(shouldThrow, block, expected, message) {
  function balanced (line 983) | function balanced(a, b, str) {
  function maybeMatch (line 998) | function maybeMatch(reg, str) {
  function range (line 1004) | function range(a, b, str) {
  function numeric (line 1053) | function numeric(str) {
  function escapeBraces (line 1059) | function escapeBraces(str) {
  function unescapeBraces (line 1067) | function unescapeBraces(str) {
  function parseCommaParts (line 1079) | function parseCommaParts(str) {
  function expandTop (line 1106) | function expandTop(str) {
  function identity (line 1123) | function identity(e) {
  function embrace (line 1127) | function embrace(str) {
  function isPadded (line 1130) | function isPadded(el) {
  function lte (line 1134) | function lte(i, y) {
  function gte (line 1137) | function gte(i, y) {
  function expand (line 1141) | function expand(str, isTop) {
  function EventEmitter (line 1283) | function EventEmitter() {
  function g (line 1425) | function g() {
  function isFunction (line 1548) | function isFunction(arg) {
  function isNumber (line 1552) | function isNumber(arg) {
  function isObject (line 1556) | function isObject(arg) {
  function isUndefined (line 1560) | function isUndefined(arg) {
  function ownProp (line 1576) | function ownProp (obj, field) {
  function alphasorti (line 1585) | function alphasorti (a, b) {
  function alphasort (line 1589) | function alphasort (a, b) {
  function setupIgnores (line 1593) | function setupIgnores (self, options) {
  function ignoreMap (line 1604) | function ignoreMap (pattern) {
  function setopts (line 1617) | function setopts (self, pattern, options) {
  function deprecationWarning (line 1684) | function deprecationWarning(options) {
  function finish (line 1700) | function finish (self) {
  function mark (line 1753) | function mark (self, p) {
  function makeAbs (line 1777) | function makeAbs (self, f) {
  function isIgnored (line 1794) | function isIgnored (self, path) {
  function childrenIgnored (line 1803) | function childrenIgnored (self, path) {
  function glob (line 1878) | function glob (pattern, options, cb) {
  function Glob (line 1916) | function Glob (pattern, options, cb) {
  function next (line 2003) | function next () {
  function lstatcb_ (line 2294) | function lstatcb_ (er, lstat) {
  function readdirCb (line 2336) | function readdirCb (self, abs, cb) {
  function lstatcb_ (line 2531) | function lstatcb_ (er, lstat) {
  function globSync (line 2589) | function globSync (pattern, options) {
  function GlobSync (line 2597) | function GlobSync (pattern, options) {
  function inflight (line 3041) | function inflight (key, cb) {
  function makeres (line 3051) | function makeres (key) {
  function slice (line 3082) | function slice (args) {
  function charSet (line 3156) | function charSet (s) {
  function filter (line 3167) | function filter (pattern, options) {
  function ext (line 3174) | function ext (a, b) {
  function minimatch (line 3208) | function minimatch (p, pattern, options) {
  function Minimatch (line 3226) | function Minimatch (pattern, options) {
  function make (line 3258) | function make () {
  function parseNegate (line 3314) | function parseNegate () {
  function braceExpand (line 3349) | function braceExpand (pattern, options) {
  function parse (line 3387) | function parse (pattern, isSub) {
  function makeRe (line 3758) | function makeRe () {
  function match (line 3816) | function match (f, partial) {
  function globUnescape (line 4033) | function globUnescape (s) {
  function regExpEscape (line 4037) | function regExpEscape (s) {
  function once (line 4062) | function once (fn) {
  function onceStrict (line 4072) | function onceStrict (fn) {
  function normalizeArray (line 4112) | function normalizeArray(parts, allowAboveRoot) {
  function trim (line 4221) | function trim(arr) {
  function filter (line 4294) | function filter (xs, f) {
  function posix (line 4317) | function posix(path) {
  function win32 (line 4321) | function win32(path) {
  function defaultSetTimout (line 4349) | function defaultSetTimout() {
  function defaultClearTimeout (line 4352) | function defaultClearTimeout () {
  function runTimeout (line 4375) | function runTimeout(fun) {
  function runClearTimeout (line 4400) | function runClearTimeout(marker) {
  function cleanUpNextTick (line 4432) | function cleanUpNextTick() {
  function drainQueue (line 4447) | function drainQueue() {
  function Item (line 4485) | function Item(fun, array) {
  function noop (line 4499) | function noop() {}
  function createReduce (line 4701) | function createReduce(dir) {
  function createPredicateIndexFinder (line 5137) | function createPredicateIndexFinder(dir) {
  function createIndexFinder (line 5167) | function createIndexFinder(dir, predicateFind, sortedIndex) {
  function collectNonEnumProps (line 5432) | function collectNonEnumProps(obj, keys) {
  function deprecated (line 6161) | function deprecated() {
  function inspect (line 6208) | function inspect(obj, opts) {
  function stylizeWithColor (line 6266) | function stylizeWithColor(str, styleType) {
  function stylizeNoColor (line 6278) | function stylizeNoColor(str, styleType) {
  function arrayToHash (line 6283) | function arrayToHash(array) {
  function formatValue (line 6294) | function formatValue(ctx, value, recurseTimes) {
  function formatPrimitive (line 6407) | function formatPrimitive(ctx, value) {
  function formatError (line 6426) | function formatError(value) {
  function formatArray (line 6431) | function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
  function formatProperty (line 6451) | function formatProperty(ctx, value, recurseTimes, visibleKeys, key, arra...
  function reduceToSingleString (line 6510) | function reduceToSingleString(output, base, braces) {
  function isArray (line 6533) | function isArray(ar) {
  function isBoolean (line 6538) | function isBoolean(arg) {
  function isNull (line 6543) | function isNull(arg) {
  function isNullOrUndefined (line 6548) | function isNullOrUndefined(arg) {
  function isNumber (line 6553) | function isNumber(arg) {
  function isString (line 6558) | function isString(arg) {
  function isSymbol (line 6563) | function isSymbol(arg) {
  function isUndefined (line 6568) | function isUndefined(arg) {
  function isRegExp (line 6573) | function isRegExp(re) {
  function isObject (line 6578) | function isObject(arg) {
  function isDate (line 6583) | function isDate(d) {
  function isError (line 6588) | function isError(e) {
  function isFunction (line 6594) | function isFunction(arg) {
  function isPrimitive (line 6599) | function isPrimitive(arg) {
  function objectToString (line 6611) | function objectToString(o) {
  function pad (line 6616) | function pad(n) {
  function timestamp (line 6625) | function timestamp() {
  function hasOwnProperty (line 6667) | function hasOwnProperty(obj, prop) {
  function wrappy (line 6679) | function wrappy (fn, cb) {

FILE: help/javascript/extra.js
  function findCommonULAncestor (line 7) | function findCommonULAncestor(nodes) {
  function buildMapAndBind (line 37) | function buildMapAndBind() {
  function getSaved (line 70) | function getSaved(key) {
  function setSaved (line 73) | function setSaved(key, hreflang) {
  function removeSaved (line 76) | function removeSaved(key) {
  function getBrowserLang (line 81) | function getBrowserLang(langIds) {
  function redirectFAQ (line 109) | function redirectFAQ() {
  function init (line 123) | function init() {

FILE: hidden_apis/src/main/java/android/app/ActivityManagerNative.java
  class ActivityManagerNative (line 3) | public abstract class ActivityManagerNative {
    method getDefault (line 5) | public static IActivityManager getDefault() {

FILE: hidden_apis/src/main/java/android/app/AppOpsManager.java
  class AppOpsManager (line 5) | public class AppOpsManager {
    class PackageOps (line 7) | public abstract static class PackageOps {
      method getOps (line 9) | public abstract List<OpEntry> getOps();
      method getPackageName (line 11) | public abstract String getPackageName();
    class OpEntry (line 14) | public abstract static class OpEntry {
      method getOp (line 16) | public abstract int getOp();
      method getMode (line 18) | public abstract int getMode();
      method getLastAccessTime (line 20) | public abstract long getLastAccessTime(int i);
      method getTime (line 22) | public abstract long getTime();
    method getNumOps (line 37) | public static int getNumOps() {
    method opToDefaultMode (line 41) | public static int opToDefaultMode(int i) {
    method opToDefaultMode (line 45) | public static int opToDefaultMode(int i, boolean b) {
    method opToSwitch (line 49) | public static int opToSwitch(int i) {
    method opToName (line 53) | public static String opToName(int i) {
    method modeToName (line 57) | public static String modeToName(int i) {
    method permissionToOpCode (line 61) | public static int permissionToOpCode(String s) {
    method strDebugOpToOp (line 65) | public static int strDebugOpToOp(String s) {

FILE: hidden_apis/src/main/java/android/app/IActivityManager.java
  type IActivityManager (line 8) | public interface IActivityManager {
    method startActivityAsUser (line 10) | int startActivityAsUser(
    method startService (line 23) | ComponentName startService(
    method startService (line 26) | ComponentName startService(
    method startService (line 29) | ComponentName startService(IApplicationThread o1, Intent o2, String o3...
    method checkPermission (line 31) | int checkPermission(String s, int i1, int i2);
    class Stub (line 33) | abstract class Stub {
      method asInterface (line 35) | public static IActivityManager asInterface(IBinder o) {
  class IApplicationThread (line 41) | class IApplicationThread {}
  class ProfilerInfo (line 43) | class ProfilerInfo {}

FILE: hidden_apis/src/main/java/android/content/Context.java
  class Context (line 3) | public class Context {

FILE: hidden_apis/src/main/java/android/content/pm/IPackageManager.java
  type IPackageManager (line 5) | public interface IPackageManager {
    method getAllPermissionGroups (line 7) | ParceledListSlice<?> getAllPermissionGroups(int i);
    method queryPermissionsByGroup (line 9) | ParceledListSlice<?> queryPermissionsByGroup(String s, int i);
    method getPermissionFlags (line 11) | int getPermissionFlags(String s1, String s2, int i);
    method grantRuntimePermission (line 13) | void grantRuntimePermission(String s1, String s2, int i);
    method revokeRuntimePermission (line 15) | void revokeRuntimePermission(String s1, String s2, int i);
    method setApplicationEnabledSetting (line 17) | void setApplicationEnabledSetting(String s1, int i1, int i2, int i3, S...
    method getPackagesForUid (line 19) | String[] getPackagesForUid(int i);
    class Stub (line 21) | abstract class Stub {
      method asInterface (line 23) | public static IPackageManager asInterface(IBinder o) {

FILE: hidden_apis/src/main/java/android/content/pm/ParceledListSlice.java
  class ParceledListSlice (line 5) | public abstract class ParceledListSlice<T> {
    method getList (line 7) | public abstract List<T> getList();

FILE: hidden_apis/src/main/java/android/os/IDeviceIdleController.java
  type IDeviceIdleController (line 3) | public interface IDeviceIdleController {
    method addPowerSaveWhitelistApp (line 5) | void addPowerSaveWhitelistApp(String s);
    class Stub (line 7) | abstract class Stub {
      method asInterface (line 9) | public static IDeviceIdleController asInterface(IBinder o) {

FILE: hidden_apis/src/main/java/android/os/Process.java
  class Process (line 3) | public class Process {
    method getPidsForCommands (line 5) | public static int[] getPidsForCommands(String[] o) {
    method myPid (line 9) | public static int myPid() {

FILE: hidden_apis/src/main/java/android/os/ServiceManager.java
  class ServiceManager (line 3) | public class ServiceManager {
    method getService (line 5) | public static IBinder getService(String s) {

FILE: hidden_apis/src/main/java/android/permission/IPermissionManager.java
  type IPermissionManager (line 6) | public interface IPermissionManager {
    method getAllPermissionGroups (line 8) | ParceledListSlice<?> getAllPermissionGroups(int i);
    method queryPermissionsByGroup (line 10) | ParceledListSlice<?> queryPermissionsByGroup(String s, int i);
    method getPermissionFlags (line 12) | int getPermissionFlags(String s1, String s2, int i);
    method getPermissionFlags (line 14) | int getPermissionFlags(String s1, String s2, int i1, int i2);
    method getPermissionFlags (line 16) | int getPermissionFlags(String s1, String s2, String s3, int i2);
    method grantRuntimePermission (line 18) | void grantRuntimePermission(String s1, String s2, int i);
    method grantRuntimePermission (line 20) | void grantRuntimePermission(String s1, String s2, int i1, int i2);
    method grantRuntimePermission (line 22) | void grantRuntimePermission(String s1, String s2, String s3, int i2);
    method revokeRuntimePermission (line 24) | void revokeRuntimePermission(String s1, String s2, int i, String s3);
    method revokeRuntimePermission (line 26) | void revokeRuntimePermission(String s1, String s2, int i1, int i2, Str...
    method revokeRuntimePermission (line 28) | void revokeRuntimePermission(String s1, String s2, String s3, int i2, ...
    class Stub (line 30) | abstract class Stub {
      method asInterface (line 32) | public static IPermissionManager asInterface(IBinder o) {

FILE: hidden_apis/src/main/java/com/android/internal/app/IAppOpsService.java
  type IAppOpsService (line 7) | public interface IAppOpsService {
    method setMode (line 9) | void setMode(int i1, int i2, String s, int i3);
    method setUidMode (line 11) | void setUidMode(int i1, int i2, int i3);
    method resetAllModes (line 13) | void resetAllModes(int i, String s);
    method getUidOps (line 15) | List<PackageOps> getUidOps(int i, int[] o);
    method getOpsForPackage (line 17) | List<PackageOps> getOpsForPackage(int i, String s, int[] o);
    class Stub (line 19) | abstract class Stub {
      method asInterface (line 21) | public static IAppOpsService asInterface(IBinder o) {

FILE: native/pmxd.c
  function log_android_err (line 34) | static int log_android_err(bool print_code, const char *tag, char *forma...
  function send_stderr (line 60) | static bool send_stderr(int port)
  function JNICALL (line 91) | JNICALL Java_com_mirfatif_privdaemon_Jni_sendStdErr(JNIEnv *env, jobject...
  function close_stderr (line 96) | static bool close_stderr()
  function JNICALL (line 111) | JNICALL Java_com_mirfatif_privdaemon_Jni_closeStdErr(JNIEnv *env, jobjec...
  function matches (line 118) | static bool matches(const char *str, const char *reg, const char *tag)
  function JNICALL (line 137) | JNICALL Java_com_mirfatif_privdaemon_Jni_matches(JNIEnv *env, jobject ob...

FILE: native/pmxe.c
  function log_android_info (line 27) | static int log_android_info(char *format, ...)
  function log_android_err (line 36) | static void log_android_err(char *format, va_list args, bool print_code)
  function print_err (line 48) | static int print_err(char *format, ...)
  function print_err_code (line 63) | static int print_err_code(char *format, ...)
  function print_out (line 78) | static void print_out(char *format, ...)
  function is_number (line 88) | static bool is_number(char *num, char *type)
  function close_std_fd (line 103) | static int close_std_fd(int std_fd, int rw_flags)
  function set_namespace (line 118) | static int set_namespace(char *pid)
  function set_cgroups (line 135) | static int set_cgroups()
  function get_last_cap (line 188) | static int get_last_cap()
  function cap_t (line 213) | static cap_t get_caps()
  function has_cap (line 223) | static bool has_cap(cap_t caps, const cap_value_t cap, cap_flag_t type)
  function has_eff_cap (line 230) | static bool has_eff_cap(const cap_value_t cap)
  function print_missing_caps (line 241) | static void print_missing_caps(cap_flag_t type)
  function raise_cap (line 264) | static bool raise_cap(cap_value_t cap)
  function raise_setuid_cap (line 281) | static int raise_setuid_cap()
  function raise_setgid_cap (line 288) | static int raise_setgid_cap()
  function raise_eff_caps (line 295) | static int raise_eff_caps()
  function raise_amb_caps (line 327) | static int raise_amb_caps()
  function lock_caps (line 369) | static int lock_caps()
  function set_uid (line 376) | static int set_uid(uid_t uid)
  function set_gid (line 386) | static int set_gid(gid_t gid)
  function set_groups (line 399) | static int set_groups(char *groups)
  function set_context (line 427) | static int set_context(char *context)
  function set_privs (line 445) | static int set_privs(char *ns_pid, bool cgroups, int gid, char *groups, ...
  function exec_it (line 473) | static int exec_it(char **argv)
  function set_oom_scr_adj (line 505) | static void set_oom_scr_adj(pid_t pid, char *value)
  function run_cmd (line 525) | static void run_cmd(int argc, char *cmd, bool wait_for_child)
  function run_daemon (line 551) | static void run_daemon(char *args)
  function send_stderr (line 602) | static int send_stderr(int port)
  function wait_for_commands (line 640) | static void wait_for_commands()
  function wait_for_app (line 736) | static int wait_for_app(int sock_fd)
  function bind_server (line 785) | static int bind_server(int sock_fd)
  function kill_duplicate (line 854) | static int kill_duplicate()
  function daemonize (line 893) | static int daemonize(int argc, char **argv, char *suffix)
  function main (line 936) | int main(int argc, char **argv)

FILE: priv_daemon/src/main/java/com/mirfatif/privdaemon/Callbacks.java
  type Callbacks (line 23) | public enum Callbacks {
    method talkToApp (line 32) | void talkToApp(String appId, String codeWord) throws RemoteException {
    method talkToApp (line 50) | void talkToApp(String codeWord) throws RemoteException {
    method sendStdErr (line 60) | void sendStdErr(int port) throws HiddenAPIsException {
    method update (line 69) | void update(IPrivTasksCallback callback, String crashLogFile) throws R...
    method setExitOnAppDeath (line 78) | void setExitOnAppDeath(boolean exitOnAppDeath) {
    method onAppDied (line 82) | private void onAppDied() {
    method exit (line 91) | void exit() {
    method showError (line 98) | void showError(int error) {
    method saveCrashLog (line 108) | void saveCrashLog(Throwable e) {
    method getDaemonState (line 127) | private static String getDaemonState() {
    method getSEContext (line 131) | static String getSEContext() {
    method fireSvcIntent (line 135) | public void fireSvcIntent(Intent intent, String svcClass, boolean fg) ...
    method isDebug (line 144) | boolean isDebug() {
    method setDebug (line 148) | boolean setDebug(IBinder logCallback) {
    method writeToLogFile (line 168) | private boolean writeToLogFile(String line) {

FILE: priv_daemon/src/main/java/com/mirfatif/privdaemon/DaemonLog.java
  class DaemonLog (line 5) | public class DaemonLog {
    method DaemonLog (line 7) | private DaemonLog() {}
    method makeTag (line 9) | private static String makeTag(String tag) {
    method e (line 13) | public static void e(String tag, String method, Throwable e) {
    method e (line 17) | public static void e(String tag, String method, String err) {
    method w (line 21) | public static void w(String tag, String method, String msg) {
    method i (line 25) | public static void i(String tag, String method, String msg) {
    method d (line 29) | public static void d(String tag, String method, String msg) {

FILE: priv_daemon/src/main/java/com/mirfatif/privdaemon/IPrivTasksImpl.java
  class IPrivTasksImpl (line 27) | public class IPrivTasksImpl extends IPrivTasks.Stub {
    method IPrivTasksImpl (line 33) | IPrivTasksImpl() {
    method sendStdErr (line 37) | public void sendStdErr(int port, String jniLibPath) throws RemoteExcep...
    method hello (line 42) | public void hello(IBinder privTasksCb, String crashLogFile) throws Rem...
    method setExitOnAppDeath (line 50) | public void setExitOnAppDeath(boolean exitOnAppDeath) {
    method getPrivsStatus (line 54) | public PrivsStatus getPrivsStatus() throws RemoteException {
    method setDebug (line 58) | public boolean setDebug(IBinder logCb) {
    method dumpHeap (line 62) | public void dumpHeap(String directory) throws RemoteException {
    method grantAppPrivileges (line 78) | public void grantAppPrivileges(String pkgName, int uid) throws RemoteE...
    method stopDaemon (line 100) | public void stopDaemon() {
    method getAppOpsLists (line 104) | public AppOpsLists getAppOpsLists() throws RemoteException {
    method getPermFixedFlags (line 108) | public PermFixedFlags getPermFixedFlags() throws RemoteException {
    method getPackagesForUid (line 112) | public String[] getPackagesForUid(int uid) throws RemoteException {
    method getOpsForPackage (line 116) | public List<MyPackageOps> getOpsForPackage(int uid, String pkgName, in...
    method getPermFlags (line 121) | public int getPermFlags(String permName, String pkgName, int userId) t...
    method setPermState (line 125) | public void setPermState(boolean grant, String pkgName, String permNam...
    method setAppOpMode (line 134) | public void setAppOpMode(int uid, String pkgName, int op, int mode) th...
    method resetAppOps (line 142) | public void resetAppOps(int userId, String pkgName) throws RemoteExcep...
    method setPkgState (line 146) | public void setPkgState(boolean enable, String pkgName, int userId) th...
    method openAppInfo (line 159) | public void openAppInfo(String pkgName, int userId) throws RemoteExcep...
    class AppPrivTasksCallbackImpl (line 166) | private static class AppPrivTasksCallbackImpl implements AppPrivTasks....
      method logErr (line 168) | public void logErr(String tag, String method, Throwable e) {
      method logErr (line 172) | public void logErr(String tag, String method, String err) {
      method showError (line 176) | public void showError(int error) {

FILE: priv_daemon/src/main/java/com/mirfatif/privdaemon/Jni.java
  type Jni (line 5) | public enum Jni {
    method loadLib (line 10) | public void loadLib(String libPath) throws HiddenAPIsException {
    method sendStdErr (line 21) | public native boolean sendStdErr(int errPort);
    method closeStdErr (line 23) | public native void closeStdErr();
    method matches (line 25) | public native boolean matches(String string, String regex, String logT...

FILE: priv_daemon/src/main/java/com/mirfatif/privdaemon/Main.java
  class Main (line 3) | public class Main {
    method main (line 5) | public static void main(String[] args) {

FILE: priv_daemon/src/main/java/com/mirfatif/privdaemon/PrivDaemon.java
  class PrivDaemon (line 12) | class PrivDaemon {
    method PrivDaemon (line 16) | PrivDaemon() {
    method start (line 30) | void start(String[] args) {
    method prepareMainLooper (line 55) | private static void prepareMainLooper() {

FILE: priv_daemon/src/main/java/com/mirfatif/privdaemon/PrivsStatusReader.java
  class PrivsStatusReader (line 11) | public class PrivsStatusReader {
    method PrivsStatusReader (line 13) | private PrivsStatusReader() {}
    method getStatus (line 15) | static PrivsStatus getStatus(AppPrivTasks appPrivTasks) throws RemoteE...

FILE: priv_daemon/src/main/java/com/mirfatif/privdaemon/Server.java
  type Server (line 17) | public enum Server {
    method getPort (line 25) | int getPort() throws HiddenAPIsException {
    method waitForAppCalls (line 38) | private void waitForAppCalls() {
    method readMessage (line 51) | private static void readMessage(Socket client) {
    method isUUID (line 72) | public static boolean isUUID(String uuid) {

FILE: priv_library/src/main/java/com/mirfatif/err/ContainerException.java
  class ContainerException (line 8) | public class ContainerException extends RemoteException {
    method ContainerException (line 12) | public ContainerException(String stackTrace) {
    method printStackTrace (line 16) | public void printStackTrace(PrintStream s) {
    method printStackTrace (line 20) | public void printStackTrace(PrintWriter s) {
    method toStackTrace (line 24) | public static String toStackTrace(Throwable e) {

FILE: priv_library/src/main/java/com/mirfatif/err/HiddenAPIsException.java
  class HiddenAPIsException (line 5) | public class HiddenAPIsException extends RemoteException {
    method HiddenAPIsException (line 9) | public HiddenAPIsException(Throwable cause) {
    method HiddenAPIsException (line 14) | public HiddenAPIsException(String message) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/AppPrivTasks.java
  class AppPrivTasks (line 24) | public class AppPrivTasks {
    method AppPrivTasks (line 31) | public AppPrivTasks(AppPrivTasksCallback callback, boolean isDaemon) {
    method setAppOpsStatus (line 43) | public PrivsStatus setAppOpsStatus(PrivsStatus status) {
    method getAppOpsLists (line 53) | public AppOpsLists getAppOpsLists(PackageManager pm) throws RemoteExce...
    method buildAppOpsNames (line 62) | private List<String> buildAppOpsNames() throws HiddenAPIsException {
    method buildAppOpsModes (line 94) | private List<String> buildAppOpsModes() throws HiddenAPIsException {
    method buildOpDefModeList (line 152) | private List<Integer> buildOpDefModeList() throws HiddenAPIsException {
    method buildOpSwitchList (line 185) | private List<Integer> buildOpSwitchList() throws HiddenAPIsException {
    method buildPermToOpMap (line 213) | private StrIntMap buildPermToOpMap(PackageManager pm) throws RemoteExc...
    method getOpsForPkg (line 296) | public List<MyPackageOps> getOpsForPkg(int uid, String pkgName, int[] ...
    class AppOpsErrorCallbackImpl (line 311) | private class AppOpsErrorCallbackImpl implements HiddenAPIs.AppOpsErro...
      method onGetUidOpsNpException (line 327) | public void onGetUidOpsNpException(Exception e) {
      method onInvalidOpCode (line 333) | public void onInvalidOpCode(int opCode, String pkgName) {
    type AppPrivTasksCallback (line 342) | public interface AppPrivTasksCallback {
      method logErr (line 344) | void logErr(String tag, String method, Throwable e);
      method logErr (line 346) | void logErr(String tag, String method, String err);
      method showError (line 348) | void showError(int error);

FILE: priv_library/src/main/java/com/mirfatif/privtasks/Constants.java
  class Constants (line 3) | public class Constants {
    method Constants (line 5) | private Constants() {}

FILE: priv_library/src/main/java/com/mirfatif/privtasks/HiddenSdkIntConstants.java
  type HiddenSdkIntConstants (line 11) | public enum HiddenSdkIntConstants {
    method get (line 26) | public int get() throws HiddenAPIsException {
    method get (line 30) | public int get(boolean wrapHiddenSdkErrors) throws HiddenAPIsException {
    method getStaticIntField (line 76) | private static int getStaticIntField(String name, Class<?> cls) throws...
    method getPermFixedFlags (line 84) | public static PermFixedFlags getPermFixedFlags() throws HiddenAPIsExce...

FILE: priv_library/src/main/java/com/mirfatif/privtasks/HiddenSdkStringConstants.java
  type HiddenSdkStringConstants (line 6) | public enum HiddenSdkStringConstants {
    method get (line 11) | public String get() throws HiddenAPIsException {
    method get (line 15) | public String get(boolean wrapHiddenSdkErrors) throws HiddenAPIsExcept...
    method getStaticStringField (line 39) | private static String getStaticStringField(String name, Class<?> cls) ...

FILE: priv_library/src/main/java/com/mirfatif/privtasks/bind/AppOpsLists.java
  class AppOpsLists (line 9) | public class AppOpsLists implements Parcelable {
    method AppOpsLists (line 21) | public AppOpsLists(
    method AppOpsLists (line 34) | protected AppOpsLists(Parcel in) {
    method createFromParcel (line 44) | public AppOpsLists createFromParcel(Parcel in) {
    method newArray (line 48) | public AppOpsLists[] newArray(int size) {
    method describeContents (line 53) | public int describeContents() {
    method writeToParcel (line 57) | public void writeToParcel(Parcel dest, int flags) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/bind/DaemonState.java
  class DaemonState (line 8) | public class DaemonState implements Parcelable {
    method DaemonState (line 18) | public DaemonState(int pid, int uid, String context, int port) {
    method DaemonState (line 28) | protected DaemonState(Parcel in) {
    method writeToParcel (line 35) | public void writeToParcel(Parcel dest, int flags) {
    method describeContents (line 42) | public int describeContents() {
    method createFromParcel (line 48) | public DaemonState createFromParcel(Parcel in) {
    method newArray (line 52) | public DaemonState[] newArray(int size) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/bind/MyPackageInfo.java
  class MyPackageInfo (line 6) | public class MyPackageInfo implements Parcelable {
    method MyPackageInfo (line 16) | protected MyPackageInfo(Parcel in) {
    method createFromParcel (line 25) | public MyPackageInfo createFromParcel(Parcel in) {
    method newArray (line 29) | public MyPackageInfo[] newArray(int size) {
    method describeContents (line 34) | public int describeContents() {
    method writeToParcel (line 38) | public void writeToParcel(Parcel dest, int flags) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/bind/MyPackageOps.java
  class MyPackageOps (line 8) | public class MyPackageOps implements Parcelable {
    method MyPackageOps (line 13) | public MyPackageOps(String pkgName, List<MyOpEntry> opEntryList) {
    method MyPackageOps (line 18) | protected MyPackageOps(Parcel in) {
    method writeToParcel (line 23) | public void writeToParcel(Parcel dest, int flags) {
    method describeContents (line 28) | public int describeContents() {
    method createFromParcel (line 34) | public MyPackageOps createFromParcel(Parcel in) {
    method newArray (line 38) | public MyPackageOps[] newArray(int size) {
    class MyOpEntry (line 43) | public static class MyOpEntry implements Parcelable {
      method MyOpEntry (line 49) | public MyOpEntry() {}
      method MyOpEntry (line 51) | protected MyOpEntry(Parcel in) {
      method writeToParcel (line 57) | public void writeToParcel(Parcel dest, int flags) {
      method describeContents (line 63) | public int describeContents() {
      method createFromParcel (line 69) | public MyOpEntry createFromParcel(Parcel in) {
      method newArray (line 73) | public MyOpEntry[] newArray(int size) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/bind/PermFixedFlags.java
  class PermFixedFlags (line 6) | public class PermFixedFlags implements Parcelable {
    method PermFixedFlags (line 12) | public PermFixedFlags(int systemFixed, int policyFixed) {
    method PermFixedFlags (line 17) | protected PermFixedFlags(Parcel in) {
    method createFromParcel (line 24) | public PermFixedFlags createFromParcel(Parcel in) {
    method newArray (line 28) | public PermFixedFlags[] newArray(int size) {
    method describeContents (line 33) | public int describeContents() {
    method writeToParcel (line 37) | public void writeToParcel(Parcel dest, int flags) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/bind/PrivsStatus.java
  class PrivsStatus (line 8) | public class PrivsStatus implements Parcelable {
    method PrivsStatus (line 10) | public PrivsStatus() {}
    method PrivsStatus (line 26) | protected PrivsStatus(Parcel in) {
    method writeToParcel (line 36) | public void writeToParcel(Parcel dest, int flags) {
    method describeContents (line 46) | public int describeContents() {
    method createFromParcel (line 52) | public PrivsStatus createFromParcel(Parcel in) {
    method newArray (line 56) | public PrivsStatus[] newArray(int size) {
    class PermStatus (line 61) | public static class PermStatus implements Parcelable {
      method PermStatus (line 66) | public PermStatus(String name, boolean granted) {
      method PermStatus (line 71) | protected PermStatus(Parcel in) {
      method writeToParcel (line 76) | public void writeToParcel(Parcel dest, int flags) {
      method describeContents (line 81) | public int describeContents() {
      method createFromParcel (line 87) | public PermStatus createFromParcel(Parcel in) {
      method newArray (line 91) | public PermStatus[] newArray(int size) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/bind/StrIntMap.java
  class StrIntMap (line 7) | public class StrIntMap implements Parcelable {
    method StrIntMap (line 11) | public StrIntMap() {}
    method StrIntMap (line 13) | protected StrIntMap(Parcel in) {
    method writeToParcel (line 20) | public void writeToParcel(Parcel dest, int flags) {
    method describeContents (line 29) | public int describeContents() {
    method createFromParcel (line 35) | public StrIntMap createFromParcel(Parcel in) {
    method newArray (line 39) | public StrIntMap[] newArray(int size) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/hiddenapis/HiddenAPIs.java
  type HiddenAPIs (line 21) | public enum HiddenAPIs {
    method getNumOps (line 24) | public static int getNumOps() {
    method getOpModeNamesSize (line 28) | public static int getOpModeNamesSize() {
    method opToDefaultMode (line 32) | public static int opToDefaultMode(int opCode, boolean isLos) {
    method opToSwitch (line 40) | public static int opToSwitch(int opCode) {
    method opToName (line 44) | public static String opToName(int opCode) {
    method modeToName (line 48) | public static String modeToName(int opMode) {
    method permToOpCode (line 52) | public static int permToOpCode(String permName) {
    method setAppOpMode (line 56) | public void setAppOpMode(String pkgName, int uid, int op, int mode) th...
    method setAppOpUidMode (line 60) | public void setAppOpUidMode(int uid, int op, int mode) throws RemoteEx...
    method resetAllModes (line 64) | public void resetAllModes(int userId, String pkgName) throws RemoteExc...
    method getOpsForPkg (line 68) | public List<MyPackageOps> getOpsForPkg(int uid, String pkgName, int[] ...
    type AppOpsErrorCallback (line 119) | public interface AppOpsErrorCallback {
      method onGetUidOpsNpException (line 121) | void onGetUidOpsNpException(Exception e);
      method onInvalidOpCode (line 123) | void onInvalidOpCode(int opCode, String pkgName);
    method getPermGroupInfoList (line 126) | public List<?> getPermGroupInfoList() throws RemoteException {
    method getPermInfoList (line 137) | public List<?> getPermInfoList(String permGroup) throws RemoteException {
    method getPermFlags (line 147) | public int getPermFlags(
    method grantRuntimePermission (line 153) | public void grantRuntimePermission(
    method revokeRuntimePermission (line 159) | public void revokeRuntimePermission(
    method checkPermission (line 165) | public int checkPermission(String perm, int pid, int uid) throws Remot...
    method setApplicationEnabledSetting (line 169) | public void setApplicationEnabledSetting(
    method getPackagesForUid (line 180) | public String[] getPackagesForUid(int uid) throws RemoteException {
    method addPowerSaveWhitelistApp (line 184) | public void addPowerSaveWhitelistApp(String pkgName) throws RemoteExce...
    method openAppInfo (line 188) | public int openAppInfo(String pkgName, int userId) throws RemoteExcept...
    method fireSvcIntent (line 198) | public void fireSvcIntent(Intent intent, String appId, String svcClass...
    method getPidsForCommands (line 214) | public static int[] getPidsForCommands(String[] commands) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/hiddenapis/SysSvcFactory.java
  type SysSvcFactory (line 14) | enum SysSvcFactory {
    method getIAppOpsSvc (line 19) | IAppOpsService getIAppOpsSvc() throws HiddenAPIsException {
    method getIPkgMgr (line 34) | IPackageManager getIPkgMgr() throws HiddenAPIsException {
    method getIPermMgr (line 48) | IPermissionManager getIPermMgr() throws HiddenAPIsException {
    method getIActMgr (line 62) | IActivityManager getIActMgr() throws HiddenAPIsException {
    method getIDevIdleController (line 82) | IDeviceIdleController getIDevIdleController() throws HiddenAPIsExcepti...

FILE: priv_library/src/main/java/com/mirfatif/privtasks/iface/IPrivTasks.java
  type IPrivTasks (line 15) | public interface IPrivTasks extends IInterface {
    method sendStdErr (line 17) | void sendStdErr(int port, String jniLibPath) throws RemoteException;
    method hello (line 19) | void hello(IBinder privTasksCb, String crashLogFile) throws RemoteExce...
    method setExitOnAppDeath (line 21) | void setExitOnAppDeath(boolean exitOnAppDeath) throws RemoteException;
    method getPrivsStatus (line 23) | PrivsStatus getPrivsStatus() throws RemoteException;
    method setDebug (line 25) | boolean setDebug(IBinder logCb) throws RemoteException;
    method dumpHeap (line 27) | void dumpHeap(String dir) throws RemoteException;
    method grantAppPrivileges (line 29) | void grantAppPrivileges(String pkgName, int uid) throws RemoteException;
    method stopDaemon (line 31) | void stopDaemon() throws RemoteException;
    method getAppOpsLists (line 33) | AppOpsLists getAppOpsLists() throws RemoteException;
    method getPermFixedFlags (line 35) | PermFixedFlags getPermFixedFlags() throws RemoteException;
    method getPackagesForUid (line 37) | String[] getPackagesForUid(int uid) throws RemoteException;
    method getOpsForPackage (line 39) | List<MyPackageOps> getOpsForPackage(int uid, String pkgName, int[] ops...
    method getPermFlags (line 41) | int getPermFlags(String permName, String pkgName, int userId) throws R...
    method setPermState (line 43) | void setPermState(boolean grant, String pkgName, String permName, int ...
    method setAppOpMode (line 46) | void setAppOpMode(int uid, String pkgName, int op, int mode) throws Re...
    method resetAppOps (line 48) | void resetAppOps(int userId, String pkgName) throws RemoteException;
    method setPkgState (line 50) | void setPkgState(boolean enable, String pkgName, int userId) throws Re...
    method openAppInfo (line 52) | void openAppInfo(String pkgName, int userId) throws RemoteException;
    class Stub (line 54) | abstract class Stub extends Binder implements IPrivTasks {
      method Stub (line 58) | public Stub() {
      method asBinder (line 62) | public IBinder asBinder() {
      method onTransact (line 66) | public boolean onTransact(int code, Parcel data, Parcel reply, int f...
      method asInterface (line 112) | public static IPrivTasks asInterface(IBinder iBinder) {
      method sendStdErr (line 123) | private static void sendStdErr(int port, String jniLibPath, IBinder ...
      method sendStdErr (line 138) | private void sendStdErr(Parcel data, Parcel reply) {
      method hello (line 153) | private static void hello(IBinder privTasksCb, String crashLogFile, ...
      method hello (line 168) | private void hello(Parcel data, Parcel reply) {
      method setExitOnAppDeath (line 183) | private static void setExitOnAppDeath(boolean exitOnAppDeath, IBinde...
      method setExitOnAppDeath (line 197) | private void setExitOnAppDeath(Parcel data, Parcel reply) {
      method getPrivsStatus (line 211) | private static PrivsStatus getPrivsStatus(IBinder remote) throws Rem...
      method getPrivsStatus (line 223) | private void getPrivsStatus(Parcel data, Parcel reply) {
      method setDebug (line 235) | private static boolean setDebug(IBinder logCallback, IBinder remote)...
      method setDebug (line 249) | private void setDebug(Parcel data, Parcel reply) {
      method dumpHeap (line 264) | private static void dumpHeap(String dir, IBinder remote) throws Remo...
      method dumpHeap (line 277) | private void dumpHeap(Parcel data, Parcel reply) {
      method grantPrivileges (line 291) | private static void grantPrivileges(String pkgName, int uid, IBinder...
      method grantPrivileges (line 306) | private void grantPrivileges(Parcel data, Parcel reply) {
      method stopDaemon (line 321) | private static void stopDaemon(IBinder remote) throws RemoteException {
      method stopDaemon (line 332) | private void stopDaemon(Parcel data, Parcel reply) {
      method getAppOpsLists (line 344) | private static AppOpsLists getAppOpsLists(IBinder remote) throws Rem...
      method getAppOpsLists (line 356) | private void getAppOpsLists(Parcel data, Parcel reply) {
      method getPermFixedFlags (line 368) | private static PermFixedFlags getPermFixedFlags(IBinder remote) thro...
      method getPermFixedFlags (line 380) | private void getPermFixedFlags(Parcel data, Parcel reply) {
      method getPackagesForUid (line 392) | private static String[] getPackagesForUid(int uid, IBinder remote) t...
      method getPackagesForUid (line 406) | private void getPackagesForUid(Parcel data, Parcel reply) {
      method getOpsForPackage (line 420) | private static List<MyPackageOps> getOpsForPackage(
      method getOpsForPackage (line 437) | private void getOpsForPackage(Parcel data, Parcel reply) {
      method getPermFlags (line 453) | private static int getPermFlags(String permName, String pkgName, int...
      method getPermFlags (line 470) | private void getPermFlags(Parcel data, Parcel reply) {
      method setPermState (line 486) | private static void setPermState(
      method setPermState (line 504) | private void setPermState(Parcel data, Parcel reply) {
      method setAppOpMode (line 521) | private static void setAppOpMode(int uid, String pkgName, int op, in...
      method setAppOpMode (line 538) | private void setAppOpMode(Parcel data, Parcel reply) {
      method resetAppOps (line 555) | private static void resetAppOps(int userId, String pkgName, IBinder ...
      method resetAppOps (line 570) | private void resetAppOps(Parcel data, Parcel reply) {
      method setPkgState (line 585) | private static void setPkgState(boolean enable, String pkgName, int ...
      method setPkgState (line 601) | private void setPkgState(Parcel data, Parcel reply) {
      method openAppInfo (line 617) | private static void openAppInfo(String pkgName, int userId, IBinder ...
      method openAppInfo (line 632) | private void openAppInfo(Parcel data, Parcel reply) {
      method createTransactionCode (line 647) | private static int createTransactionCode() {
      method obtainData (line 651) | private static Parcel obtainData() {
      method recycle (line 657) | private static void recycle(Parcel data, Parcel reply) {
      method initReply (line 662) | private static void initReply(Parcel data, Parcel reply) {
      method writeException (line 670) | public static void writeException(Parcel reply, Throwable t) {
      method readException (line 678) | public static void readException(Parcel reply) throws RemoteException {
      class Proxy (line 684) | private static class Proxy implements IPrivTasks {
        method Proxy (line 688) | private Proxy(IBinder remote) {
        method asBinder (line 692) | public IBinder asBinder() {
        method sendStdErr (line 696) | public void sendStdErr(int port, String jniLibPath) throws RemoteE...
        method hello (line 700) | public void hello(IBinder privTasksCb, String crashLogFile) throws...
        method setExitOnAppDeath (line 704) | public void setExitOnAppDeath(boolean exitOnAppDeath) throws Remot...
        method getPrivsStatus (line 708) | public PrivsStatus getPrivsStatus() throws RemoteException {
        method setDebug (line 712) | public boolean setDebug(IBinder logCallback) throws RemoteException {
        method dumpHeap (line 716) | public void dumpHeap(String dir) throws RemoteException {
        method grantAppPrivileges (line 720) | public void grantAppPrivileges(String pkgName, int uid) throws Rem...
        method stopDaemon (line 724) | public void stopDaemon() throws RemoteException {
        method getAppOpsLists (line 728) | public AppOpsLists getAppOpsLists() throws RemoteException {
        method getPermFixedFlags (line 732) | public PermFixedFlags getPermFixedFlags() throws RemoteException {
        method getPackagesForUid (line 736) | public String[] getPackagesForUid(int uid) throws RemoteException {
        method getOpsForPackage (line 740) | public List<MyPackageOps> getOpsForPackage(int uid, String pkgName...
        method getPermFlags (line 745) | public int getPermFlags(String permName, String pkgName, int userI...
        method setPermState (line 749) | public void setPermState(boolean grant, String pkgName, String per...
        method setAppOpMode (line 754) | public void setAppOpMode(int uid, String pkgName, int op, int mode...
        method resetAppOps (line 758) | public void resetAppOps(int userId, String pkgName) throws RemoteE...
        method setPkgState (line 762) | public void setPkgState(boolean enable, String pkgName, int userId...
        method openAppInfo (line 766) | public void openAppInfo(String pkgName, int userId) throws RemoteE...

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/CloseableReadWriteLock.java
  class CloseableReadWriteLock (line 6) | public class CloseableReadWriteLock extends ReentrantReadWriteLock {
    method withWriteLock (line 8) | public void withWriteLock(Runnable task) {
    method withReadLock (line 17) | public <T> T withReadLock(RunnableWithResult<T> task) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/LogUtil.java
  class LogUtil (line 11) | public class LogUtil {
    method LogUtil (line 15) | private LogUtil() {}
    method writeCrashLog (line 17) | public static void writeCrashLog(
    method readLogcat (line 30) | public static SingleTaskExecutor readLogcat(LogCallback callback) {
    method readLogcatStream (line 44) | private static void readLogcatStream(Process process, LogCallback call...
    type LogCallback (line 73) | public interface LogCallback {
      method onNewLine (line 75) | boolean onNewLine(String line);

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/MyLog.java
  class MyLog (line 5) | public class MyLog {
    method MyLog (line 7) | private MyLog() {}
    method makeMsg (line 9) | private static String makeMsg(String method, String msg) {
    method e (line 13) | public static void e(String tag, String method, Throwable e) {
    method e (line 17) | public static void e(String tag, String method, String msg, Throwable ...
    method e (line 22) | public static void e(String tag, String method, String err) {
    method w (line 28) | public static void w(String tag, String method, String msg) {
    method i (line 32) | public static void i(String tag, String method, String msg) {
    method d (line 36) | public static void d(String tag, String method, String msg) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/NonBlockingReader.java
  class NonBlockingReader (line 11) | public class NonBlockingReader extends InputStreamReader {
    method NonBlockingReader (line 15) | public NonBlockingReader(InputStream inputStream) {
    method readLine (line 23) | public String readLine(long msTimeout) throws IOException, Interrupted...
    method readLine (line 29) | public String readLine(Process process, long msTimeout) throws IOExcep...

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/Util.java
  class Util (line 17) | public class Util {
    method Util (line 19) | private Util() {}
    method runProc (line 21) | public static Process runProc(String tag, String method, boolean redir...
    method getCurrDateTime (line 34) | public static String getCurrDateTime(boolean spaced, boolean utc) {
    method readNullTermFile (line 43) | public static String readNullTermFile(String path) {
    method getArray (line 52) | public static int[] getArray(List<Integer> list) {
    method getList (line 56) | public static List<Integer> getList(int[] array) {
    method buildPmSignFlag (line 62) | private static int buildPmSignFlag() {
    method getPackageSignatures (line 68) | public static Signature[] getPackageSignatures(PackageInfo pkgInfo) {
    method isFwkPkg (line 78) | public static boolean isFwkPkg(PackageInfo packageInfo, List<Integer> ...

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/BgRunner.java
  class BgRunner (line 8) | public class BgRunner {
    method execute (line 13) | public static void execute(Runnable task) {
    method submit (line 17) | public static <T> Future<T> submit(Callable<T> task) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/MinDelayTaskExecutor.java
  class MinDelayTaskExecutor (line 5) | public class MinDelayTaskExecutor {
    method MinDelayTaskExecutor (line 10) | public MinDelayTaskExecutor(Runnable task, long delay, TimeUnit unit, ...
    method runOrSchedule (line 15) | public void runOrSchedule(boolean cancel) {
    method cancelAndRunNow (line 29) | public void cancelAndRunNow() {
    method runNow (line 38) | private void runNow(long delay) {
    method shutdownNow (line 42) | public void shutdownNow() {
    method isAlive (line 46) | public boolean isAlive() {
    method run (line 50) | private void run(Runnable task) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/NotifyWaiter.java
  class NotifyWaiter (line 8) | public class NotifyWaiter {
    method NotifyWaiter (line 14) | public NotifyWaiter() {
    method NotifyWaiter (line 18) | public NotifyWaiter(long timeout, TimeUnit unit) {
    method NotifyWaiter (line 23) | public NotifyWaiter(Condition condition) {
    method waitForNotifyNoThrow (line 28) | public void waitForNotifyNoThrow() {
    method waitForNotifyNoThrow (line 32) | public void waitForNotifyNoThrow(Condition condition) {
    method waitForNotify (line 39) | public void waitForNotify() throws InterruptedException {
    method waitForNotify (line 43) | public void waitForNotify(Condition condition) throws InterruptedExcep...
    method waitForNotify (line 47) | private void waitForNotify(boolean noThrow, Condition condition) throw...
    method notify (line 71) | public void notify(boolean all) {
    type Condition (line 83) | public interface Condition {
      method shouldWait (line 85) | boolean shouldWait();

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/RateLimitedTask.java
  class RateLimitedTask (line 5) | public class RateLimitedTask {
    method RateLimitedTask (line 10) | public RateLimitedTask(long minDelay, TimeUnit unit, Runnable task) {
    method run (line 15) | public void run() {
    method run (line 19) | public void run(boolean force) {
    method run (line 25) | public synchronized void run(boolean force, boolean inBg) {
    method run (line 37) | private void run(Runnable task) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/RateLimitedTaskTyped.java
  class RateLimitedTaskTyped (line 5) | public class RateLimitedTaskTyped<T> {
    method RateLimitedTaskTyped (line 10) | public RateLimitedTaskTyped(long minDelay, TimeUnit unit, RunnableWith...
    method run (line 15) | public void run(T param) {
    method run (line 19) | public synchronized void run(T param, boolean force) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/RateLimiter.java
  class RateLimiter (line 5) | public class RateLimiter {
    method RateLimiter (line 10) | public RateLimiter(long minDelay, TimeUnit unit) {
    method getRemainingMillis (line 14) | public long getRemainingMillis() {
    method can (line 18) | public boolean can() {
    method can (line 22) | public boolean can(boolean setTs) {
    method setTs (line 32) | public void setTs() {
    method waitUntilCanNoThrow (line 36) | public void waitUntilCanNoThrow(boolean setTs) {
    method waitUntilCan (line 43) | public void waitUntilCan(boolean setTs) throws InterruptedException {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/RunnableWithParam.java
  type RunnableWithParam (line 3) | public interface RunnableWithParam<T> {
    method run (line 5) | void run(T param);

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/RunnableWithResult.java
  type RunnableWithResult (line 3) | public interface RunnableWithResult<T> {
    method run (line 5) | T run();

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/SingleParamTask.java
  class SingleParamTask (line 5) | public class SingleParamTask<T> {
    method SingleParamTask (line 11) | public SingleParamTask(RunnableWithParam<T> task, String threadName) {
    method runPendingParams (line 16) | private void runPendingParams() {
    method enqueueParam (line 23) | private void enqueueParam(T param) {
    method submitIfIdle (line 30) | public synchronized void submitIfIdle(T param) {
    method cancelAndSubmit (line 36) | public synchronized void cancelAndSubmit(T param, boolean interrupt) {
    method cancel (line 43) | public void cancel(boolean interrupt) {
    method shutdownNow (line 48) | public synchronized void shutdownNow() {
    method hasRunningOrPendingTasks (line 52) | public boolean hasRunningOrPendingTasks() {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/SingleSchedTaskExecutor.java
  class SingleSchedTaskExecutor (line 12) | public class SingleSchedTaskExecutor extends SingleTaskExecutorAbstract {
    method SingleSchedTaskExecutor (line 18) | public SingleSchedTaskExecutor(Runnable task, String threadName) {
    method SingleSchedTaskExecutor (line 22) | private SingleSchedTaskExecutor(Runnable task, boolean oneshot, String...
    method runAndShutdown (line 28) | private void runAndShutdown(Runnable task) {
    method poll (line 33) | protected Runnable poll() {
    method getTimeoutMillis (line 38) | protected long getTimeoutMillis() {
    method getQueue (line 43) | protected Queue<?> getQueue() {
    method schedule (line 47) | public void schedule(long delay, TimeUnit unit) {
    method scheduleIfIdle (line 55) | public void scheduleIfIdle(long delay, TimeUnit unit) {
    method cancelAndSchedule (line 61) | public void cancelAndSchedule(boolean interrupt, long delay, TimeUnit ...
    method schedule (line 69) | public static void schedule(Runnable task, long delay, TimeUnit unit, ...
    class DelayedRunnable (line 73) | private static class DelayedRunnable implements Runnable, Delayed {
      method DelayedRunnable (line 77) | public DelayedRunnable(Runnable task) {
      method run (line 81) | public void run() {
      method setTime (line 87) | private DelayedRunnable setTime(TimeUnit unit, long delay) {
      method compareTo (line 92) | public int compareTo(Delayed other) {
      method getDelay (line 101) | public long getDelay(TimeUnit unit) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/SingleTaskExecutor.java
  class SingleTaskExecutor (line 6) | public class SingleTaskExecutor extends SingleTaskExecutorAbstract {
    method SingleTaskExecutor (line 12) | public SingleTaskExecutor(Runnable task, String threadName) {
    method SingleTaskExecutor (line 16) | public SingleTaskExecutor(Runnable task, String threadName, int thread...
    method poll (line 22) | protected Runnable poll() {
    method getTimeoutMillis (line 26) | protected long getTimeoutMillis() {
    method getQueue (line 30) | protected Queue<?> getQueue() {
    method submit (line 34) | public void submit() {
    method cancelAndSubmit (line 42) | public void cancelAndSubmit(boolean interrupt) {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/SingleTaskExecutorAbstract.java
  class SingleTaskExecutorAbstract (line 6) | public abstract class SingleTaskExecutorAbstract {
    method SingleTaskExecutorAbstract (line 10) | protected SingleTaskExecutorAbstract(String threadName) {
    method SingleTaskExecutorAbstract (line 14) | protected SingleTaskExecutorAbstract(String threadName, int threadPrio...
    method start (line 23) | protected void start() {
    method finalize (line 27) | protected void finalize() {
    method poll (line 31) | protected abstract Runnable poll();
    method getTimeoutMillis (line 33) | protected abstract long getTimeoutMillis();
    method getQueue (line 35) | protected abstract Queue<?> getQueue();
    method runLoop (line 41) | private void runLoop() {
    method clearInterrupt (line 75) | private static void clearInterrupt() {
    method clearQueue (line 79) | private void clearQueue(boolean interrupt) {
    method cancelAndAddTask (line 90) | protected <T> void cancelAndAddTask(boolean interrupt, T task, Queue<T...
    method addTask (line 95) | protected <T> void addTask(T task, Queue<T> queue) {
    method isAlive (line 102) | public boolean isAlive() {
    method hasPendingTasks (line 106) | public boolean hasPendingTasks() {
    method hasRunningOrPendingTasks (line 110) | public boolean hasRunningOrPendingTasks() {
    method cancel (line 114) | public void cancel(boolean interrupt) {
    method shutdownNow (line 122) | public void shutdownNow() {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/SingleTaskExecutorTyped.java
  class SingleTaskExecutorTyped (line 3) | public class SingleTaskExecutorTyped<T> extends SingleTaskExecutor {
    method SingleTaskExecutorTyped (line 9) | public SingleTaskExecutorTyped(
    method cancelSubmitGet (line 17) | public T cancelSubmitGet(boolean interrupt) {
    method runTask (line 32) | private void runTask() {
    method getResult (line 42) | private T getResult() {

FILE: priv_library/src/main/java/com/mirfatif/privtasks/util/bg/ThreadUtils.java
  class ThreadUtils (line 6) | public class ThreadUtils {
    method ThreadUtils (line 8) | private ThreadUtils() {}
    method isMainThread (line 10) | public static boolean isMainThread() {
    method assertNotMainThread (line 18) | public static void assertNotMainThread() {
    method createDaemonThread (line 24) | public static Thread createDaemonThread(Runnable r) {
Condensed preview — 512 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (6,421K chars).
[
  {
    "path": ".gitignore",
    "chars": 72,
    "preview": "**/.gradle/\n**/.idea/\n\n**/build/\n\n**/.kotlin/\n\n/local.properties\n\n/out/\n"
  },
  {
    "path": ".gitmodules",
    "chars": 115,
    "preview": "[submodule \"native/libcap\"]\n\tpath = native/libcap\n\turl = https://android.googlesource.com/platform/external/libcap\n"
  },
  {
    "path": "404.html",
    "chars": 2105,
    "preview": "<!doctype html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"utf-8\" />\n  <meta name=\"viewport\" content=\"width=device-width,"
  },
  {
    "path": "LICENSE",
    "chars": 34524,
    "preview": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C)"
  },
  {
    "path": "PRIVACY.html",
    "chars": 5146,
    "preview": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n<head>\n    <title>PMX Privacy Policy</title>\n    <meta charset=\"UTF-8\" />\n    <meta n"
  },
  {
    "path": "README.md",
    "chars": 8003,
    "preview": "# PermissionManagerX\neXtended Permission Manager for Android - view and set Manifest Permissions and AppOps\n\n<a href=\"ht"
  },
  {
    "path": "app/.gitignore",
    "chars": 24,
    "preview": "/build/\n/src/*/jniLibs/\n"
  },
  {
    "path": "app/build.gradle",
    "chars": 3607,
    "preview": "import java.nio.file.Paths\n\napply plugin: 'apk-conventions'\n\nfinal NDK_VER = '28.2.13676358'\n\nandroid {\n    namespace = "
  },
  {
    "path": "app/proguard-rules.pro",
    "chars": 722,
    "preview": "# Preserve the line number information for debugging stack traces.\n-keepattributes SourceFile,LineNumberTable\n\n# Keep th"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "chars": 3251,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  xmlns:tool"
  },
  {
    "path": "app/src/main/java/com/mirfatif/err/AdbException.java",
    "chars": 139,
    "preview": "package com.mirfatif.err;\n\npublic class AdbException extends Exception {\n\n  public AdbException(Throwable cause) {\n    s"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/about/AboutActivity.java",
    "chars": 9775,
    "preview": "package com.mirfatif.permissionmanagerx.about;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/about/CrashReportActivity.kt",
    "chars": 6168,
    "preview": "package com.mirfatif.permissionmanagerx.about\n\nimport android.content.Intent\nimport android.view.View\nimport androidx.an"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/about/PrivilegesAdapter.java",
    "chars": 1987,
    "preview": "package com.mirfatif.permissionmanagerx.about;\n\nimport android.view.LayoutInflater;\nimport android.view.ViewGroup;\nimpor"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/about/PrivilegesDialog.java",
    "chars": 3095,
    "preview": "package com.mirfatif.permissionmanagerx.about;\n\nimport android.graphics.drawable.ShapeDrawable;\nimport android.graphics."
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/about/TransCreditsDialogFrag.java",
    "chars": 3135,
    "preview": "package com.mirfatif.permissionmanagerx.about;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.openWebUrl;\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/app/App.java",
    "chars": 2120,
    "preview": "package com.mirfatif.permissionmanagerx.app;\n\nimport android.content.Context;\nimport android.content.pm.PackageManager;\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/backup/BackupFileSelector.java",
    "chars": 1709,
    "preview": "package com.mirfatif.permissionmanagerx.backup;\n\nimport android.content.ActivityNotFoundException;\nimport android.net.Ur"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/backup/BackupRestore.java",
    "chars": 15907,
    "preview": "package com.mirfatif.permissionmanagerx.backup;\n\nimport android.content.SharedPreferences;\nimport android.content.pm.Pac"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/base/AlertDialogFragment.java",
    "chars": 3220,
    "preview": "package com.mirfatif.permissionmanagerx.base;\n\nimport android.app.Dialog;\nimport android.content.Context;\nimport android"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/base/BaseActivity.java",
    "chars": 3959,
    "preview": "package com.mirfatif.permissionmanagerx.base;\n\nimport android.content.Context;\nimport android.content.res.Configuration;"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/base/BottomSheetDialogFrag.java",
    "chars": 1426,
    "preview": "package com.mirfatif.permissionmanagerx.base;\n\nimport android.app.Dialog;\nimport android.content.Context;\nimport android"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/base/DialogBg.java",
    "chars": 1592,
    "preview": "package com.mirfatif.permissionmanagerx.base;\n\nimport android.app.Activity;\nimport android.graphics.drawable.Drawable;\ni"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/base/MyListAdapter.java",
    "chars": 1887,
    "preview": "package com.mirfatif.permissionmanagerx.base;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport androidx.recyclerview.wi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AboutActivityM.java",
    "chars": 1179,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.os.Bundle;\nimport android.view.Menu;\nimport android.view.Me"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AdbConnectSvcM.java",
    "chars": 475,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.app.Service;\nimport android.content.Intent;\nimport android."
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AdvSettingsActivityM.java",
    "chars": 482,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.os.Bundle;\nimport com.mirfatif.permissionmanagerx.base.Base"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/AppM.java",
    "chars": 466,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.app.Application;\nimport android.content.res.Configuration;\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/CrashReportActivityM.java",
    "chars": 410,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.os.Bundle;\nimport com.mirfatif.permissionmanagerx.about.Cra"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/CustomButton.java",
    "chars": 2038,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport androi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/DaemonRcvSvcM.java",
    "chars": 471,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.app.Service;\nimport android.content.Intent;\nimport android."
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/DialogHelpIcon.java",
    "chars": 1044,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport andr"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/FilterSettingsActivityM.java",
    "chars": 1146,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.os.Bundle;\nimport android.view.Menu;\nimport android.view.Me"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/HelpActivityM.java",
    "chars": 772,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.os.Bundle;\nimport android.view.Menu;\nimport android.view.Me"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/LifecycleWatcher.java",
    "chars": 1580,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport androidx.lifecycle.Lifecycle;\nimport androidx.lifecycle.Lifecycle.E"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/LogcatSvcM.java",
    "chars": 535,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.app.Service;\nimport android.content.Intent;\nimport android."
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MainActivityM.java",
    "chars": 1463,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.vi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MoveUpBehavior.java",
    "chars": 1025,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.view.View;\nimport androidx.coordinatorlayout.widget.Coordin"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyCoordinatorLayout.java",
    "chars": 423,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport a"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyDrawerLayout.java",
    "chars": 398,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport a"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyLinearLayout.java",
    "chars": 384,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport a"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyNavigationView.java",
    "chars": 416,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport c"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MySearchView.java",
    "chars": 326,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Context;\nimport androidx.appcompat.widget.SearchVie"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/MyWebView.java",
    "chars": 364,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport a"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/NumPickerPref.java",
    "chars": 447,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimp"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/PackageActivityM.java",
    "chars": 1165,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.os.Bundle;\nimport android.view.Menu;\nimport android.view.Me"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/ProgressLinearLayout.java",
    "chars": 771,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\n\npublic "
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/fwk/SettingsActivityM.java",
    "chars": 877,
    "preview": "package com.mirfatif.permissionmanagerx.fwk;\n\nimport android.os.Bundle;\nimport androidx.preference.Preference;\nimport an"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/help/HelpActivity.java",
    "chars": 6616,
    "preview": "package com.mirfatif.permissionmanagerx.help;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\ni"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/help/HelpJsInterface.java",
    "chars": 1082,
    "preview": "package com.mirfatif.permissionmanagerx.help;\n\nimport android.app.Activity;\nimport android.graphics.Color;\nimport androi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/main/AdbConnectDialog.java",
    "chars": 14680,
    "preview": "package com.mirfatif.permissionmanagerx.main;\n\nimport static com.mirfatif.permissionmanagerx.main.MainActivity.TAG_ADB_C"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/main/BackupRestoreDialog.java",
    "chars": 5000,
    "preview": "package com.mirfatif.permissionmanagerx.main;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\ni"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/main/DaemonStartProg.java",
    "chars": 3564,
    "preview": "package com.mirfatif.permissionmanagerx.main;\n\nimport static com.mirfatif.permissionmanagerx.main.MainActivity.ACTION_SH"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/main/Feedback.java",
    "chars": 2165,
    "preview": "package com.mirfatif.permissionmanagerx.main;\n\nimport android.view.View;\nimport android.view.animation.Animation;\nimport"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/main/FeedbackDialogFrag.java",
    "chars": 4843,
    "preview": "package com.mirfatif.permissionmanagerx.main;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.openWebUrl;\n\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/main/MainActivity.java",
    "chars": 24076,
    "preview": "package com.mirfatif.permissionmanagerx.main;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getQtyString;"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/main/PackageAdapter.java",
    "chars": 6310,
    "preview": "package com.mirfatif.permissionmanagerx.main;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\ni"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/main/PkgLongPressDialogFrag.java",
    "chars": 7246,
    "preview": "package com.mirfatif.permissionmanagerx.main;\n\nimport android.app.Dialog;\nimport android.content.ActivityNotFoundExcepti"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/main/PrivsCheckBoxFocus.java",
    "chars": 7059,
    "preview": "package com.mirfatif.permissionmanagerx.main;\n\nimport android.animation.Animator;\nimport android.animation.ValueAnimator"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/AppOpsParser.java",
    "chars": 7335,
    "preview": "package com.mirfatif.permissionmanagerx.parser;\n\nimport android.os.RemoteException;\nimport android.util.ArrayMap;\nimport"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/Package.java",
    "chars": 6603,
    "preview": "package com.mirfatif.permissionmanagerx.parser;\n\nimport android.text.TextUtils;\nimport com.mirfatif.permissionmanagerx.p"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/PackageParser.java",
    "chars": 32179,
    "preview": "package com.mirfatif.permissionmanagerx.parser;\n\nimport static android.content.pm.PermissionInfo.PROTECTION_INTERNAL;\nim"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/PermGroupsMapping.java",
    "chars": 1522,
    "preview": "package com.mirfatif.permissionmanagerx.parser;\n\nimport android.content.res.TypedArray;\nimport com.mirfatif.permissionma"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/Permission.java",
    "chars": 15581,
    "preview": "package com.mirfatif.permissionmanagerx.parser;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/SearchConstants.java",
    "chars": 2253,
    "preview": "package com.mirfatif.permissionmanagerx.parser;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/permsdb/PermissionDao.java",
    "chars": 1848,
    "preview": "package com.mirfatif.permissionmanagerx.parser.permsdb;\n\nimport androidx.room.Dao;\nimport androidx.room.Insert;\nimport a"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/permsdb/PermissionDatabase.java",
    "chars": 320,
    "preview": "package com.mirfatif.permissionmanagerx.parser.permsdb;\n\nimport androidx.room.Database;\nimport androidx.room.RoomDatabas"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/permsdb/PermissionEntity.java",
    "chars": 890,
    "preview": "package com.mirfatif.permissionmanagerx.parser.permsdb;\n\nimport androidx.room.ColumnInfo;\nimport androidx.room.Entity;\ni"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/parser/permsdb/PermsDb.java",
    "chars": 3090,
    "preview": "package com.mirfatif.permissionmanagerx.parser.permsdb;\n\nimport androidx.room.Room;\nimport androidx.room.migration.Migra"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/pkg/PackageActivity.java",
    "chars": 19591,
    "preview": "package com.mirfatif.permissionmanagerx.pkg;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\nim"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/pkg/PermDetailDialog.java",
    "chars": 3354,
    "preview": "package com.mirfatif.permissionmanagerx.pkg;\n\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/pkg/PermLongPressDialogFrag.java",
    "chars": 4851,
    "preview": "package com.mirfatif.permissionmanagerx.pkg;\n\nimport android.app.Dialog;\nimport android.content.Context;\nimport android."
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/pkg/PermissionAdapter.java",
    "chars": 7411,
    "preview": "package com.mirfatif.permissionmanagerx.pkg;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\nim"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/AppUpdate.java",
    "chars": 7004,
    "preview": "package com.mirfatif.permissionmanagerx.prefs;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/ExcFiltersData.java",
    "chars": 8524,
    "preview": "package com.mirfatif.permissionmanagerx.prefs;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/MySettings.java",
    "chars": 20053,
    "preview": "package com.mirfatif.permissionmanagerx.prefs;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/fwk/CustomPrefDialogFrag.java",
    "chars": 2062,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.fwk;\n\nimport android.os.Bundle;\nimport androidx.fragment.app.DialogFragmen"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/fwk/EditTextPrefDialogFrag.java",
    "chars": 732,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.fwk;\n\nimport android.app.Activity;\nimport android.app.Dialog;\nimport andro"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/fwk/ListPrefDialogFrag.java",
    "chars": 746,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.fwk;\n\nimport android.app.Dialog;\nimport android.content.Context;\nimport an"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/fwk/MultiSelectListPrefDialogFrag.java",
    "chars": 779,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.fwk;\n\nimport android.app.Dialog;\nimport android.content.Context;\nimport an"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/AdvSettingsActivity.java",
    "chars": 6127,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.settings;\n\nimport android.net.Uri;\nimport android.os.Bundle;\nimport androi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/AdvSettingsFrag.java",
    "chars": 6722,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.settings;\n\nimport android.content.Context;\nimport android.content.SharedPr"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/FilterSettingsActivity.java",
    "chars": 6306,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.settings;\n\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSIO"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/FilterSettingsFragment.java",
    "chars": 12667,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.settings;\n\nimport android.content.Context;\nimport android.content.SharedPr"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SearchSettingsFrag.java",
    "chars": 2028,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.settings;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.get"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SettingsActivity.java",
    "chars": 2910,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.settings;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.get"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SettingsFrag.java",
    "chars": 1059,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.settings;\n\nimport android.os.Bundle;\nimport androidx.preference.Preference"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SettingsFragGeneral.java",
    "chars": 2285,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.settings;\n\nimport android.content.Context;\nimport android.content.SharedPr"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/prefs/settings/SettingsFragTheme.java",
    "chars": 2049,
    "preview": "package com.mirfatif.permissionmanagerx.prefs.settings;\n\nimport android.content.Context;\nimport android.content.SharedPr"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/privs/AdbConnManager.java",
    "chars": 7477,
    "preview": "package com.mirfatif.permissionmanagerx.privs;\n\nimport android.os.Build;\nimport android.sun.misc.BASE64Encoder;\nimport a"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/privs/DaemonHandler.java",
    "chars": 10100,
    "preview": "package com.mirfatif.permissionmanagerx.privs;\n\nimport static com.mirfatif.permissionmanagerx.BuildConfig.APPLICATION_ID"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/privs/DaemonIface.java",
    "chars": 7680,
    "preview": "package com.mirfatif.permissionmanagerx.privs;\n\nimport android.os.IBinder;\nimport android.os.RemoteException;\nimport com"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/privs/DaemonStarter.java",
    "chars": 5011,
    "preview": "package com.mirfatif.permissionmanagerx.privs;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/privs/NativeDaemon.java",
    "chars": 11702,
    "preview": "package com.mirfatif.permissionmanagerx.privs;\n\nimport static com.mirfatif.permissionmanagerx.BuildConfig.APPLICATION_ID"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/profile/PermProfileBackupRestore.java",
    "chars": 348,
    "preview": "package com.mirfatif.permissionmanagerx.profile;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport org.xml"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/svc/AdbConnectSvc.java",
    "chars": 3592,
    "preview": "package com.mirfatif.permissionmanagerx.svc;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getInt;\n\nimpor"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/svc/DaemonRcvSvc.java",
    "chars": 1046,
    "preview": "package com.mirfatif.permissionmanagerx.svc;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getInt;\n\nimpor"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/svc/LogcatSvc.java",
    "chars": 7827,
    "preview": "package com.mirfatif.permissionmanagerx.svc;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\nim"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/ApiUtils.java",
    "chars": 5633,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport android.Manifest;\nimport android.app.Activity;\nimport android.cont"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/AppLifecycle.java",
    "chars": 1611,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport android.app.Activity;\nimport android.app.Application;\nimport andro"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/LocaleUtils.java",
    "chars": 1660,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport android.content.Context;\nimport android.content.res.Configuration;"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/LogUtils.java",
    "chars": 6676,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport static com.mirfatif.permissionmanagerx.util.ApiUtils.getString;\n\ni"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/NotifUtils.java",
    "chars": 3381,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport static android.app.PendingIntent.FLAG_IMMUTABLE;\nimport static and"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/SmallDimMarginSpan.java",
    "chars": 788,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\nimport and"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/StdErrLogServer.java",
    "chars": 1862,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport com.mirfatif.privtasks.util.MyLog;\nimport com.mirfatif.privtasks.u"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/StringUtils.java",
    "chars": 4312,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;\nimport stati"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/UiUtils.java",
    "chars": 4718,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport android.animation.LayoutTransition;\nimport android.app.Activity;\ni"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/UserUtils.java",
    "chars": 652,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport android.os.Build;\nimport com.mirfatif.permissionmanagerx.app.App;\n"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/Utils.java",
    "chars": 988,
    "preview": "package com.mirfatif.permissionmanagerx.util;\n\nimport android.os.Build;\nimport com.mirfatif.privtasks.util.MyLog;\nimport"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveBgTask.java",
    "chars": 521,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport com.mirfatif.permissi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveEvent.java",
    "chars": 3246,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport androidx.lifecycle.Mu"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveMinDelayParamTask.java",
    "chars": 1818,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport com.mirfatif.permissi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveSchedParamTask.java",
    "chars": 1221,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport com.mirfatif.privtask"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveSchedTask.java",
    "chars": 2295,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport com.mirfatif.permissi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveSingleParamTask.java",
    "chars": 601,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport com.mirfatif.permissi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveTasksQueue.java",
    "chars": 2668,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport android.os.SystemClock;\nimport androidx.lifecycle.LifecycleOwne"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveTasksQueueTyped.java",
    "chars": 2350,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\n\npublic class LiveTasksQueue"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveUiParamTask.java",
    "chars": 985,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport com.mirfatif.permissi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveUiTask.java",
    "chars": 645,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport com.mirfatif.permissi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/LiveUiWaitTask.java",
    "chars": 1304,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport androidx.lifecycle.LifecycleOwner;\nimport com.mirfatif.permissi"
  },
  {
    "path": "app/src/main/java/com/mirfatif/permissionmanagerx/util/bg/UiRunner.java",
    "chars": 571,
    "preview": "package com.mirfatif.permissionmanagerx.util.bg;\n\nimport android.os.Handler;\nimport android.os.Looper;\nimport androidx.l"
  },
  {
    "path": "app/src/main/res/anim/shake.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <translate\n   "
  },
  {
    "path": "app/src/main/res/color/active_disabled.xml",
    "chars": 247,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <item and"
  },
  {
    "path": "app/src/main/res/color/slim_switch.xml",
    "chars": 349,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <item and"
  },
  {
    "path": "app/src/main/res/drawable/accessibility.xml",
    "chars": 411,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/advanced_settings.xml",
    "chars": 1350,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/arrow_right.xml",
    "chars": 386,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/backup_restore.xml",
    "chars": 559,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/check_circle.xml",
    "chars": 488,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/circle_progress_bar.xml",
    "chars": 338,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:inner"
  },
  {
    "path": "app/src/main/res/drawable/color.xml",
    "chars": 610,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/crash_report_text_bg.xml",
    "chars": 260,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:shape"
  },
  {
    "path": "app/src/main/res/drawable/cross_red.xml",
    "chars": 381,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:viewportHeight=\"24\""
  },
  {
    "path": "app/src/main/res/drawable/danger.xml",
    "chars": 1787,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/dark_mode.xml",
    "chars": 675,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/database.xml",
    "chars": 3311,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/donate.xml",
    "chars": 664,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/email.xml",
    "chars": 448,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/exit.xml",
    "chars": 518,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/filter.xml",
    "chars": 360,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_accounts.xml",
    "chars": 2153,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:viewportWidth=\"512\"\n  android:width=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_audio.xml",
    "chars": 1817,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:viewportWidth=\"512\"\n  android:width=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_background.xml",
    "chars": 1292,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"200\"\n  android:viewportWidth=\"200\"\n  android:width=\"24dp\"\n  xmln"
  },
  {
    "path": "app/src/main/res/drawable/g_biometrics.xml",
    "chars": 5839,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:viewportWidth=\"512\"\n  android:width=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_bluetooth.xml",
    "chars": 1237,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:viewportWidth=\"512\"\n  android:width=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_calendar.xml",
    "chars": 449,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_calllog.xml",
    "chars": 660,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_camera.xml",
    "chars": 602,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_clipboard.xml",
    "chars": 4223,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:viewportWidth=\"512\"\n  android:width=\"24dp\"\n  xmln"
  },
  {
    "path": "app/src/main/res/drawable/g_contacts.xml",
    "chars": 730,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_data.xml",
    "chars": 620,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_display.xml",
    "chars": 401,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/g_hardware.xml",
    "chars": 3516,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/g_home.xml",
    "chars": 384,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/g_location.xml",
    "chars": 629,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_log.xml",
    "chars": 2101,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/g_mic.xml",
    "chars": 517,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_network.xml",
    "chars": 1080,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:viewportHeight=\"350"
  },
  {
    "path": "app/src/main/res/drawable/g_notif.xml",
    "chars": 549,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/g_others.xml",
    "chars": 318,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_package.xml",
    "chars": 463,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/g_phone.xml",
    "chars": 423,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_power.xml",
    "chars": 533,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/g_sensors.xml",
    "chars": 1853,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:viewportHeight=\"480"
  },
  {
    "path": "app/src/main/res/drawable/g_settings.xml",
    "chars": 3154,
    "preview": "<vector xmlns:tools=\"http://schemas.android.com/tools\"\n  android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:"
  },
  {
    "path": "app/src/main/res/drawable/g_sms.xml",
    "chars": 1619,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:viewportWidth=\"512\"\n  android:width=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_storage.xml",
    "chars": 457,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_vibration.xml",
    "chars": 1226,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"200\"\n  android:viewportWidth=\"200\"\n  android:width=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/g_wifi.xml",
    "chars": 484,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/github_mark.xml",
    "chars": 2109,
    "preview": "<vector xmlns:tools=\"http://schemas.android.com/tools\"\n  android:height=\"24dp\"\n  android:viewportHeight=\"120\"\n  android:"
  },
  {
    "path": "app/src/main/res/drawable/help.xml",
    "chars": 577,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/hinge.xml",
    "chars": 231,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:shape"
  },
  {
    "path": "app/src/main/res/drawable/info.xml",
    "chars": 467,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/issues.xml",
    "chars": 1236,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  xmlns:tools=\"http://schemas.android.com/tools\"\n  an"
  },
  {
    "path": "app/src/main/res/drawable/key.xml",
    "chars": 695,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/label.xml",
    "chars": 503,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/link.xml",
    "chars": 1555,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:viewportHeight=\"384"
  },
  {
    "path": "app/src/main/res/drawable/locale.xml",
    "chars": 1246,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/log.xml",
    "chars": 2097,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:viewportWidth=\"512\"\n  android:width=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/main_act_big_prog_bg.xml",
    "chars": 1563,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <item\n "
  },
  {
    "path": "app/src/main/res/drawable/notification_icon.xml",
    "chars": 2823,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  xmlns:tools=\"http://schemas.android.com/tools\"\n  an"
  },
  {
    "path": "app/src/main/res/drawable/paid.xml",
    "chars": 582,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/perm_watcher.xml",
    "chars": 4039,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/permission.xml",
    "chars": 2151,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/privacy_policy.xml",
    "chars": 704,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/report.xml",
    "chars": 392,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/root.xml",
    "chars": 1520,
    "preview": "<vector xmlns:tools=\"http://schemas.android.com/tools\"\n  android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:"
  },
  {
    "path": "app/src/main/res/drawable/schedule.xml",
    "chars": 582,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/search_settings.xml",
    "chars": 2783,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/search_settings_bg.xml",
    "chars": 450,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<inset xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:inset"
  },
  {
    "path": "app/src/main/res/drawable/settings.xml",
    "chars": 2130,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  xmlns:tools=\"http://schemas.android.com/tools\"\n  an"
  },
  {
    "path": "app/src/main/res/drawable/share.xml",
    "chars": 737,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:tint=\"?attr/colorCo"
  },
  {
    "path": "app/src/main/res/drawable/shell.xml",
    "chars": 1724,
    "preview": "<vector xmlns:tools=\"http://schemas.android.com/tools\"\n  android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:"
  },
  {
    "path": "app/src/main/res/drawable/slim_switch_thumb.xml",
    "chars": 276,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:shape"
  },
  {
    "path": "app/src/main/res/drawable/slim_switch_track.xml",
    "chars": 249,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:shape"
  },
  {
    "path": "app/src/main/res/drawable/star.xml",
    "chars": 508,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/telegram.xml",
    "chars": 1729,
    "preview": "<vector android:height=\"24dp\"\n  android:viewportHeight=\"512\"\n  android:viewportWidth=\"512\"\n  android:width=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/theme.xml",
    "chars": 1230,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:width=\"24dp\"\n  android:height=\"24dp\"\n  andr"
  },
  {
    "path": "app/src/main/res/drawable/tick.xml",
    "chars": 332,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:height=\"24dp\"\n  android:viewportHeight=\"24\""
  },
  {
    "path": "app/src/main/res/drawable/triangle.xml",
    "chars": 393,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <item>\n"
  }
]

// ... and 312 more files (download for full content)

About this extraction

This page contains the full source code of the mirfatif/PermissionManagerX GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 512 files (5.3 MB), approximately 1.4M tokens, and a symbol index with 1844 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!