Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
7756e107
Commit
7756e107
authored
Jun 10, 2019
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rewrite configs with Kotlin delagate properties
parent
3e58d502
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
57 changed files
with
988 additions
and
1193 deletions
+988
-1193
Config.java
app/src/main/java/com/topjohnwu/magisk/Config.java
+0
-399
Config.kt
app/src/main/java/com/topjohnwu/magisk/Config.kt
+196
-0
ConfigLeanback.kt
app/src/main/java/com/topjohnwu/magisk/ConfigLeanback.kt
+0
-52
Const.kt
app/src/main/java/com/topjohnwu/magisk/Const.kt
+0
-1
Info.java
app/src/main/java/com/topjohnwu/magisk/Info.java
+36
-0
KConfig.kt
app/src/main/java/com/topjohnwu/magisk/KConfig.kt
+0
-46
LogDao.kt
...rc/main/java/com/topjohnwu/magisk/data/database/LogDao.kt
+1
-2
RepoDatabaseHelper.java
...om/topjohnwu/magisk/data/database/RepoDatabaseHelper.java
+0
-118
RepoDatabaseHelper.kt
.../com/topjohnwu/magisk/data/database/RepoDatabaseHelper.kt
+109
-0
GithubRawApiServices.kt
...com/topjohnwu/magisk/data/network/GithubRawApiServices.kt
+6
-7
DBConfig.kt
...ain/java/com/topjohnwu/magisk/data/repository/DBConfig.kt
+95
-0
MagiskRepository.kt
.../com/topjohnwu/magisk/data/repository/MagiskRepository.kt
+33
-24
SettingRepository.kt
...com/topjohnwu/magisk/data/repository/SettingRepository.kt
+0
-11
StringRepository.kt
.../com/topjohnwu/magisk/data/repository/StringRepository.kt
+0
-11
RepositoryModule.kt
...src/main/java/com/topjohnwu/magisk/di/RepositoryModule.kt
+0
-2
DownloadModuleService.java
...opjohnwu/magisk/model/download/DownloadModuleService.java
+2
-2
BaseModule.java
...in/java/com/topjohnwu/magisk/model/entity/BaseModule.java
+2
-2
Policy.java
...c/main/java/com/topjohnwu/magisk/model/entity/Policy.java
+3
-3
Repo.java
...src/main/java/com/topjohnwu/magisk/model/entity/Repo.java
+2
-2
PreferenceModel.kt
.../com/topjohnwu/magisk/model/preference/PreferenceModel.kt
+16
-0
GeneralReceiver.kt
...va/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt
+3
-4
UpdateCheckService.kt
...a/com/topjohnwu/magisk/model/update/UpdateCheckService.kt
+4
-4
DelegateWorker.java
...ava/com/topjohnwu/magisk/model/worker/DelegateWorker.java
+6
-6
MagiskInstaller.java
...main/java/com/topjohnwu/magisk/tasks/MagiskInstaller.java
+7
-7
UpdateRepos.java
...src/main/java/com/topjohnwu/magisk/tasks/UpdateRepos.java
+6
-5
MainActivity.kt
app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt
+4
-3
SplashActivity.kt
app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt
+6
-8
BasePreferenceFragment.kt
...va/com/topjohnwu/magisk/ui/base/BasePreferenceFragment.kt
+0
-18
MagiskActivity.kt
.../main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt
+1
-3
MagiskHideFragment.kt
...n/java/com/topjohnwu/magisk/ui/hide/MagiskHideFragment.kt
+2
-9
HomeFragment.kt
...rc/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
+1
-1
HomeViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
+13
-24
ReposFragment.kt
...main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt
+2
-2
SettingsFragment.kt
...java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt
+35
-40
SuRequestViewModel.kt
...a/com/topjohnwu/magisk/ui/surequest/SuRequestViewModel.kt
+2
-3
DownloadApp.java
...src/main/java/com/topjohnwu/magisk/utils/DownloadApp.java
+4
-3
FingerprintHelper.java
...in/java/com/topjohnwu/magisk/utils/FingerprintHelper.java
+0
-124
FingerprintHelper.kt
...main/java/com/topjohnwu/magisk/utils/FingerprintHelper.kt
+119
-0
LocaleManager.kt
...src/main/java/com/topjohnwu/magisk/utils/LocaleManager.kt
+2
-2
Logger.java
app/src/main/java/com/topjohnwu/magisk/utils/Logger.java
+2
-2
PatchAPK.java
app/src/main/java/com/topjohnwu/magisk/utils/PatchAPK.java
+4
-4
RootUtils.kt
app/src/main/java/com/topjohnwu/magisk/utils/RootUtils.kt
+6
-6
SuLogger.kt
app/src/main/java/com/topjohnwu/magisk/utils/SuLogger.kt
+5
-3
Utils.java
app/src/main/java/com/topjohnwu/magisk/utils/Utils.java
+0
-142
Utils.kt
app/src/main/java/com/topjohnwu/magisk/utils/Utils.kt
+123
-0
XNetwork.kt
app/src/main/java/com/topjohnwu/magisk/utils/XNetwork.kt
+0
-39
MarkDownWindow.java
...c/main/java/com/topjohnwu/magisk/view/MarkDownWindow.java
+2
-1
Notifications.java
...rc/main/java/com/topjohnwu/magisk/view/Notifications.java
+8
-8
ProgressNotification.java
.../java/com/topjohnwu/magisk/view/ProgressNotification.java
+3
-3
Shortcuts.kt
app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.kt
+72
-0
EnvFixDialog.java
.../java/com/topjohnwu/magisk/view/dialogs/EnvFixDialog.java
+3
-3
FingerprintAuthDialog.java
.../topjohnwu/magisk/view/dialogs/FingerprintAuthDialog.java
+10
-8
InstallMethodDialog.java
...om/topjohnwu/magisk/view/dialogs/InstallMethodDialog.java
+7
-7
MagiskInstallDialog.java
...om/topjohnwu/magisk/view/dialogs/MagiskInstallDialog.java
+7
-7
ManagerInstallDialog.java
...m/topjohnwu/magisk/view/dialogs/ManagerInstallDialog.java
+5
-5
UninstallDialog.java
...va/com/topjohnwu/magisk/view/dialogs/UninstallDialog.java
+7
-7
app_settings.xml
app/src/main/res/xml/app_settings.xml
+6
-0
No files found.
app/src/main/java/com/topjohnwu/magisk/Config.java
deleted
100644 → 0
View file @
3e58d502
This diff is collapsed.
Click to expand it.
app/src/main/java/com/topjohnwu/magisk/Config.kt
0 → 100644
View file @
7756e107
package
com.topjohnwu.magisk
import
android.content.Context
import
android.util.Xml
import
androidx.core.content.edit
import
com.topjohnwu.magisk.data.repository.DBConfig
import
com.topjohnwu.magisk.data.database.SettingsDao
import
com.topjohnwu.magisk.data.database.StringDao
import
com.topjohnwu.magisk.di.Protected
import
com.topjohnwu.magisk.model.preference.PreferenceModel
import
com.topjohnwu.magisk.utils.*
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.io.SuFile
import
com.topjohnwu.superuser.io.SuFileInputStream
import
org.xmlpull.v1.XmlPullParser
import
java.io.File
object
Config
:
PreferenceModel
,
DBConfig
{
override
val
stringDao
:
StringDao
by
inject
()
override
val
settingsDao
:
SettingsDao
by
inject
()
override
val
context
:
Context
by
inject
(
Protected
)
object
Key
{
// db configs
const
val
ROOT_ACCESS
=
"root_access"
const
val
SU_MULTIUSER_MODE
=
"multiuser_mode"
const
val
SU_MNT_NS
=
"mnt_ns"
const
val
SU_MANAGER
=
"requester"
const
val
SU_FINGERPRINT
=
"su_fingerprint"
// prefs
const
val
SU_REQUEST_TIMEOUT
=
"su_request_timeout"
const
val
SU_AUTO_RESPONSE
=
"su_auto_response"
const
val
SU_NOTIFICATION
=
"su_notification"
const
val
SU_REAUTH
=
"su_reauth"
const
val
CHECK_UPDATES
=
"check_update"
const
val
UPDATE_CHANNEL
=
"update_channel"
const
val
CUSTOM_CHANNEL
=
"custom_channel"
const
val
LOCALE
=
"locale"
const
val
DARK_THEME
=
"dark_theme"
const
val
ETAG_KEY
=
"ETag"
const
val
REPO_ORDER
=
"repo_order"
const
val
SHOW_SYSTEM_APP
=
"show_system"
// system state
const
val
MAGISKHIDE
=
"magiskhide"
const
val
COREONLY
=
"disable"
}
object
Value
{
// Update channels
const
val
DEFAULT_CHANNEL
=
-
1
const
val
STABLE_CHANNEL
=
0
const
val
BETA_CHANNEL
=
1
const
val
CUSTOM_CHANNEL
=
2
const
val
CANARY_CHANNEL
=
3
const
val
CANARY_DEBUG_CHANNEL
=
4
// root access mode
const
val
ROOT_ACCESS_DISABLED
=
0
const
val
ROOT_ACCESS_APPS_ONLY
=
1
const
val
ROOT_ACCESS_ADB_ONLY
=
2
const
val
ROOT_ACCESS_APPS_AND_ADB
=
3
// su multiuser
const
val
MULTIUSER_MODE_OWNER_ONLY
=
0
const
val
MULTIUSER_MODE_OWNER_MANAGED
=
1
const
val
MULTIUSER_MODE_USER
=
2
// su mnt ns
const
val
NAMESPACE_MODE_GLOBAL
=
0
const
val
NAMESPACE_MODE_REQUESTER
=
1
const
val
NAMESPACE_MODE_ISOLATE
=
2
// su notification
const
val
NO_NOTIFICATION
=
0
const
val
NOTIFICATION_TOAST
=
1
// su auto response
const
val
SU_PROMPT
=
0
const
val
SU_AUTO_DENY
=
1
const
val
SU_AUTO_ALLOW
=
2
// su timeout
val
TIMEOUT_LIST
=
intArrayOf
(
0
,
-
1
,
10
,
20
,
30
,
60
)
// repo order
const
val
ORDER_NAME
=
0
const
val
ORDER_DATE
=
1
}
private
val
defaultChannel
=
if
(
Utils
.
isCanary
)
Value
.
CANARY_DEBUG_CHANNEL
else
Value
.
DEFAULT_CHANNEL
var
repoOrder
by
preference
(
Key
.
REPO_ORDER
,
Value
.
ORDER_DATE
)
var
suDefaultTimeout
by
preferenceStrInt
(
Key
.
SU_REQUEST_TIMEOUT
,
10
)
var
suAutoReponse
by
preferenceStrInt
(
Key
.
SU_AUTO_RESPONSE
,
Value
.
SU_PROMPT
)
var
suNotification
by
preferenceStrInt
(
Key
.
SU_NOTIFICATION
,
Value
.
NOTIFICATION_TOAST
)
var
updateChannel
by
preferenceStrInt
(
Key
.
UPDATE_CHANNEL
,
defaultChannel
)
var
darkTheme
by
preference
(
Key
.
DARK_THEME
,
true
)
var
suReAuth
by
preference
(
Key
.
SU_REAUTH
,
false
)
var
checkUpdate
by
preference
(
Key
.
CHECK_UPDATES
,
true
)
@JvmStatic
var
magiskHide
by
preference
(
Key
.
MAGISKHIDE
,
true
)
var
coreOnly
by
preference
(
Key
.
COREONLY
,
false
)
var
showSystemApp
by
preference
(
Key
.
SHOW_SYSTEM_APP
,
false
)
var
customChannelUrl
by
preference
(
Key
.
CUSTOM_CHANNEL
,
""
)
var
locale
by
preference
(
Key
.
LOCALE
,
""
)
@JvmStatic
var
etagKey
by
preference
(
Key
.
ETAG_KEY
,
""
)
var
rootMode
by
dbSettings
(
Key
.
ROOT_ACCESS
,
Value
.
ROOT_ACCESS_APPS_AND_ADB
)
var
suMntNamespaceMode
by
dbSettings
(
Key
.
SU_MNT_NS
,
Value
.
NAMESPACE_MODE_REQUESTER
)
var
suMultiuserMode
by
dbSettings
(
Key
.
SU_MULTIUSER_MODE
,
Value
.
MULTIUSER_MODE_OWNER_ONLY
)
var
suFingerprint
by
dbSettings
(
Key
.
SU_FINGERPRINT
,
false
)
@JvmStatic
var
suManager
by
dbStrings
(
Key
.
SU_MANAGER
,
""
)
fun
initialize
()
=
prefs
.
edit
{
val
config
=
SuFile
.
open
(
"/data/adb"
,
Const
.
MANAGER_CONFIGS
)
if
(
config
.
exists
())
runCatching
{
val
input
=
SuFileInputStream
(
config
).
buffered
()
val
parser
=
Xml
.
newPullParser
()
parser
.
setFeature
(
XmlPullParser
.
FEATURE_PROCESS_NAMESPACES
,
false
)
parser
.
setInput
(
input
,
"UTF-8"
)
parser
.
nextTag
()
parser
.
require
(
XmlPullParser
.
START_TAG
,
null
,
"map"
)
while
(
parser
.
next
()
!=
XmlPullParser
.
END_TAG
)
{
if
(
parser
.
eventType
!=
XmlPullParser
.
START_TAG
)
continue
val
key
:
String
=
parser
.
getAttributeValue
(
null
,
"name"
)
val
value
:
String
=
parser
.
getAttributeValue
(
null
,
"value"
)
when
(
parser
.
name
)
{
"string"
->
{
parser
.
require
(
XmlPullParser
.
START_TAG
,
null
,
"string"
)
putString
(
key
,
parser
.
nextText
())
parser
.
require
(
XmlPullParser
.
END_TAG
,
null
,
"string"
)
}
"boolean"
->
{
parser
.
require
(
XmlPullParser
.
START_TAG
,
null
,
"boolean"
)
putBoolean
(
key
,
value
.
toBoolean
())
parser
.
nextTag
()
parser
.
require
(
XmlPullParser
.
END_TAG
,
null
,
"boolean"
)
}
"int"
->
{
parser
.
require
(
XmlPullParser
.
START_TAG
,
null
,
"int"
)
putInt
(
key
,
value
.
toInt
())
parser
.
nextTag
()
parser
.
require
(
XmlPullParser
.
END_TAG
,
null
,
"int"
)
}
"long"
->
{
parser
.
require
(
XmlPullParser
.
START_TAG
,
null
,
"long"
)
putLong
(
key
,
value
.
toLong
())
parser
.
nextTag
()
parser
.
require
(
XmlPullParser
.
END_TAG
,
null
,
"long"
)
}
"float"
->
{
parser
.
require
(
XmlPullParser
.
START_TAG
,
null
,
"int"
)
putFloat
(
key
,
value
.
toFloat
())
parser
.
nextTag
()
parser
.
require
(
XmlPullParser
.
END_TAG
,
null
,
"int"
)
}
else
->
parser
.
next
()
}
}
config
.
delete
()
}
remove
(
Key
.
ETAG_KEY
)
if
(!
prefs
.
contains
(
Key
.
UPDATE_CHANNEL
))
putString
(
Key
.
UPDATE_CHANNEL
,
defaultChannel
.
toString
())
// Get actual state
putBoolean
(
Key
.
COREONLY
,
Const
.
MAGISK_DISABLE_FILE
.
exists
())
// Write database configs
putString
(
Key
.
ROOT_ACCESS
,
rootMode
.
toString
())
putString
(
Key
.
SU_MNT_NS
,
suMntNamespaceMode
.
toString
())
putString
(
Key
.
SU_MULTIUSER_MODE
,
suMultiuserMode
.
toString
())
putBoolean
(
Key
.
SU_FINGERPRINT
,
FingerprintHelper
.
useFingerprint
())
}
@JvmStatic
fun
export
()
{
// Flush prefs to disk
prefs
.
edit
().
apply
()
val
xml
=
File
(
"${get<Context>(Protected).filesDir.parent}/shared_prefs"
,
"${packageName}_preferences.xml"
)
Shell
.
su
(
"cat $xml > /data/adb/${Const.MANAGER_CONFIGS}"
).
exec
()
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/ConfigLeanback.kt
deleted
100644 → 0
View file @
3e58d502
package
com.topjohnwu.magisk
import
android.content.Context
import
android.content.SharedPreferences
import
androidx.annotation.AnyThread
import
androidx.annotation.WorkerThread
import
com.skoumal.teanity.extensions.subscribeK
import
com.topjohnwu.magisk.data.repository.SettingRepository
import
com.topjohnwu.magisk.data.repository.StringRepository
import
com.topjohnwu.magisk.di.Protected
import
com.topjohnwu.magisk.utils.inject
object
ConfigLeanback
{
@JvmStatic
val
protectedContext
:
Context
by
inject
(
Protected
)
@JvmStatic
val
prefs
:
SharedPreferences
by
inject
()
private
val
settingRepo
:
SettingRepository
by
inject
()
private
val
stringRepo
:
StringRepository
by
inject
()
@JvmStatic
@AnyThread
fun
put
(
key
:
String
,
value
:
Int
)
{
settingRepo
.
put
(
key
,
value
).
subscribeK
()
}
@JvmStatic
@WorkerThread
fun
get
(
key
:
String
,
defaultValue
:
Int
):
Int
=
settingRepo
.
fetch
(
key
,
defaultValue
).
blockingGet
()
@JvmStatic
@AnyThread
fun
put
(
key
:
String
,
value
:
String
?)
{
val
task
=
value
?.
let
{
stringRepo
.
put
(
key
,
it
)
}
?:
stringRepo
.
delete
(
key
)
task
.
subscribeK
()
}
@JvmStatic
@WorkerThread
fun
get
(
key
:
String
,
defaultValue
:
String
?):
String
=
stringRepo
.
fetch
(
key
,
defaultValue
.
orEmpty
()).
blockingGet
()
@JvmStatic
@AnyThread
fun
delete
(
key
:
String
)
{
settingRepo
.
delete
(
key
).
subscribeK
()
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/Const.kt
View file @
7756e107
...
@@ -19,7 +19,6 @@ object Const {
...
@@ -19,7 +19,6 @@ object Const {
const
val
MAGISK_LOG
=
"/cache/magisk.log"
const
val
MAGISK_LOG
=
"/cache/magisk.log"
// Versions
// Versions
const
val
UPDATE_SERVICE_VER
=
1
const
val
SNET_EXT_VER
=
12
const
val
SNET_EXT_VER
=
12
const
val
SNET_REVISION
=
"b66b1a914978e5f4c4bbfd74a59f4ad371bac107"
const
val
SNET_REVISION
=
"b66b1a914978e5f4c4bbfd74a59f4ad371bac107"
const
val
BOOTCTL_REVISION
=
"9c5dfc1b8245c0b5b524901ef0ff0f8335757b77"
const
val
BOOTCTL_REVISION
=
"9c5dfc1b8245c0b5b524901ef0ff0f8335757b77"
...
...
app/src/main/java/com/topjohnwu/magisk/Info.java
0 → 100644
View file @
7756e107
package
com
.
topjohnwu
.
magisk
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
public
final
class
Info
{
public
static
int
magiskVersionCode
=
-
1
;
// Current status
public
static
String
magiskVersionString
=
""
;
// Update Info
public
static
String
remoteMagiskVersionString
=
""
;
public
static
int
remoteMagiskVersionCode
=
-
1
;
public
static
String
magiskLink
=
""
;
public
static
String
magiskNoteLink
=
""
;
public
static
String
magiskMD5
=
""
;
public
static
String
remoteManagerVersionString
=
""
;
public
static
int
remoteManagerVersionCode
=
-
1
;
public
static
String
managerLink
=
""
;
public
static
String
managerNoteLink
=
""
;
public
static
String
uninstallerLink
=
""
;
// Install flags
public
static
boolean
keepVerity
=
false
;
public
static
boolean
keepEnc
=
false
;
public
static
boolean
recovery
=
false
;
public
static
void
loadMagiskInfo
()
{
try
{
magiskVersionString
=
ShellUtils
.
fastCmd
(
"magisk -v"
).
split
(
":"
)[
0
];
magiskVersionCode
=
Integer
.
parseInt
(
ShellUtils
.
fastCmd
(
"magisk -V"
));
Config
.
setMagiskHide
(
Shell
.
su
(
"magiskhide --status"
).
exec
().
isSuccess
());
}
catch
(
NumberFormatException
ignored
)
{
}
}
}
app/src/main/java/com/topjohnwu/magisk/KConfig.kt
deleted
100644 → 0
View file @
3e58d502
package
com.topjohnwu.magisk
import
android.content.Context
import
com.topjohnwu.magisk.KConfig.UpdateChannel.STABLE
import
com.topjohnwu.magisk.di.Protected
import
com.topjohnwu.magisk.model.preference.PreferenceModel
import
com.topjohnwu.magisk.utils.inject
object
KConfig
:
PreferenceModel
{
override
val
context
:
Context
by
inject
(
Protected
)
private
var
internalUpdateChannel
by
preference
(
Config
.
Key
.
UPDATE_CHANNEL
,
STABLE
.
id
.
toString
())
var
useCustomTabs
by
preference
(
"useCustomTabs"
,
true
)
@JvmStatic
var
customUpdateChannel
by
preference
(
Config
.
Key
.
CUSTOM_CHANNEL
,
""
)
@JvmStatic
var
updateChannel
:
UpdateChannel
get
()
=
UpdateChannel
.
byId
(
internalUpdateChannel
.
toIntOrNull
()
?:
STABLE
.
id
)
set
(
value
)
{
internalUpdateChannel
=
value
.
id
.
toString
()
}
internal
const
val
DEFAULT_CHANNEL
=
"topjohnwu/magisk_files"
enum
class
UpdateChannel
(
val
id
:
Int
)
{
STABLE
(
Config
.
Value
.
STABLE_CHANNEL
),
BETA
(
Config
.
Value
.
BETA_CHANNEL
),
CANARY
(
Config
.
Value
.
CANARY_CHANNEL
),
CANARY_DEBUG
(
Config
.
Value
.
CANARY_DEBUG_CHANNEL
),
CUSTOM
(
Config
.
Value
.
CUSTOM_CHANNEL
);
companion
object
{
fun
byId
(
id
:
Int
)
=
when
(
id
)
{
Config
.
Value
.
STABLE_CHANNEL
->
STABLE
Config
.
Value
.
BETA_CHANNEL
->
BETA
Config
.
Value
.
CUSTOM_CHANNEL
->
CUSTOM
Config
.
Value
.
CANARY_CHANNEL
->
CANARY
Config
.
Value
.
CANARY_DEBUG_CHANNEL
->
CANARY_DEBUG
else
->
STABLE
}
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/data/database/LogDao.kt
View file @
7756e107
package
com.topjohnwu.magisk.data.database
package
com.topjohnwu.magisk.data.database
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.data.database.base.*
import
com.topjohnwu.magisk.data.database.base.*
import
com.topjohnwu.magisk.model.entity.MagiskLog
import
com.topjohnwu.magisk.model.entity.MagiskLog
import
com.topjohnwu.magisk.model.entity.toLog
import
com.topjohnwu.magisk.model.entity.toLog
...
@@ -12,7 +11,7 @@ class LogDao : BaseDao() {
...
@@ -12,7 +11,7 @@ class LogDao : BaseDao() {
override
val
table
=
DatabaseDefinition
.
Table
.
LOG
override
val
table
=
DatabaseDefinition
.
Table
.
LOG
fun
deleteOutdated
(
fun
deleteOutdated
(
suTimeout
:
Long
=
Config
.
suLogTimeout
*
TimeUnit
.
DAYS
.
toMillis
(
1
)
suTimeout
:
Long
=
TimeUnit
.
DAYS
.
toMillis
(
14
)
)
=
query
<
Delete
>
{
)
=
query
<
Delete
>
{
condition
{
condition
{
lessThan
(
"time"
,
suTimeout
.
toString
())
lessThan
(
"time"
,
suTimeout
.
toString
())
...
...
app/src/main/java/com/topjohnwu/magisk/data/database/RepoDatabaseHelper.java
deleted
100644 → 0
View file @
3e58d502
package
com
.
topjohnwu
.
magisk
.
data
.
database
;
import
android.content.Context
;
import
android.database.Cursor
;
import
android.database.sqlite.SQLiteDatabase
;
import
android.database.sqlite.SQLiteOpenHelper
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.model.entity.Repo
;
import
java.util.HashSet
;
import
java.util.Set
;
@Deprecated
public
class
RepoDatabaseHelper
extends
SQLiteOpenHelper
{
private
static
final
int
DATABASE_VER
=
5
;
private
static
final
String
TABLE_NAME
=
"repos"
;
private
final
SQLiteDatabase
mDb
;
@Deprecated
public
RepoDatabaseHelper
(
Context
context
)
{
super
(
context
,
"repo.db"
,
null
,
DATABASE_VER
);
mDb
=
getWritableDatabase
();
}
@Override
public
void
onCreate
(
SQLiteDatabase
db
)
{
onUpgrade
(
db
,
0
,
DATABASE_VER
);
}
@Override
public
void
onUpgrade
(
SQLiteDatabase
db
,
int
oldVersion
,
int
newVersion
)
{
if
(
oldVersion
!=
newVersion
)
{
// Nuke old DB and create new table
db
.
execSQL
(
"DROP TABLE IF EXISTS "
+
TABLE_NAME
);
db
.
execSQL
(
"CREATE TABLE IF NOT EXISTS "
+
TABLE_NAME
+
" "
+
"(id TEXT, name TEXT, version TEXT, versionCode INT, "
+
"author TEXT, description TEXT, last_update INT, PRIMARY KEY(id))"
);
Config
.
remove
(
Config
.
Key
.
ETAG_KEY
);
}
}
@Override
public
void
onDowngrade
(
SQLiteDatabase
db
,
int
oldVersion
,
int
newVersion
)
{
onUpgrade
(
db
,
0
,
DATABASE_VER
);
}
@Deprecated
public
void
clearRepo
()
{
mDb
.
delete
(
TABLE_NAME
,
null
,
null
);
}
@Deprecated
public
void
removeRepo
(
String
id
)
{
mDb
.
delete
(
TABLE_NAME
,
"id=?"
,
new
String
[]{
id
});
}
@Deprecated
public
void
removeRepo
(
Repo
repo
)
{
removeRepo
(
repo
.
getId
());
}
@Deprecated
public
void
removeRepo
(
Iterable
<
String
>
list
)
{
for
(
String
id
:
list
)
{
if
(
id
==
null
)
continue
;
mDb
.
delete
(
TABLE_NAME
,
"id=?"
,
new
String
[]{
id
});
}
}
@Deprecated
public
void
addRepo
(
Repo
repo
)
{
mDb
.
replace
(
TABLE_NAME
,
null
,
repo
.
getContentValues
());
}
@Deprecated
public
Repo
getRepo
(
String
id
)
{
try
(
Cursor
c
=
mDb
.
query
(
TABLE_NAME
,
null
,
"id=?"
,
new
String
[]{
id
},
null
,
null
,
null
))
{
if
(
c
.
moveToNext
())
{
return
new
Repo
(
c
);
}
}
return
null
;
}
@Deprecated
public
Cursor
getRawCursor
()
{
return
mDb
.
query
(
TABLE_NAME
,
null
,
null
,
null
,
null
,
null
,
null
);
}
@Deprecated
public
Cursor
getRepoCursor
()
{
String
orderBy
=
null
;
switch
((
int
)
Config
.
get
(
Config
.
Key
.
REPO_ORDER
))
{
case
Config
.
Value
.
ORDER_NAME
:
orderBy
=
"name COLLATE NOCASE"
;
break
;
case
Config
.
Value
.
ORDER_DATE
:
orderBy
=
"last_update DESC"
;
}
return
mDb
.
query
(
TABLE_NAME
,
null
,
null
,
null
,
null
,
null
,
orderBy
);
}
@Deprecated
public
Set
<
String
>
getRepoIDSet
()
{
HashSet
<
String
>
set
=
new
HashSet
<>(
300
);
try
(
Cursor
c
=
mDb
.
query
(
TABLE_NAME
,
null
,
null
,
null
,
null
,
null
,
null
))
{
while
(
c
.
moveToNext
())
{
set
.
add
(
c
.
getString
(
c
.
getColumnIndex
(
"id"
)));
}
}
return
set
;
}
}
app/src/main/java/com/topjohnwu/magisk/data/database/RepoDatabaseHelper.kt
0 → 100644
View file @
7756e107
package
com.topjohnwu.magisk.data.database
import
android.content.Context
import
android.database.Cursor
import
android.database.sqlite.SQLiteDatabase
import
android.database.sqlite.SQLiteOpenHelper
import
androidx.core.content.edit
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.model.entity.Repo
import
java.util.*
@Deprecated
(
""
)
class
RepoDatabaseHelper
constructor
(
context
:
Context
)
:
SQLiteOpenHelper
(
context
,
"repo.db"
,
null
,
DATABASE_VER
)
{
private
val
mDb
:
SQLiteDatabase
=
writableDatabase
val
rawCursor
:
Cursor
@Deprecated
(
""
)
get
()
=
mDb
.
query
(
TABLE_NAME
,
null
,
null
,
null
,
null
,
null
,
null
)
val
repoCursor
:
Cursor
@Deprecated
(
""
)
get
()
{
var
orderBy
:
String
?
=
null
when
(
Config
.
repoOrder
)
{
Config
.
Value
.
ORDER_NAME
->
orderBy
=
"name COLLATE NOCASE"
Config
.
Value
.
ORDER_DATE
->
orderBy
=
"last_update DESC"
}
return
mDb
.
query
(
TABLE_NAME
,
null
,
null
,
null
,
null
,
null
,
orderBy
)
}
val
repoIDSet
:
Set
<
String
>
@Deprecated
(
""
)
get
()
{
val
set
=
HashSet
<
String
>(
300
)
mDb
.
query
(
TABLE_NAME
,
null
,
null
,
null
,
null
,
null
,
null
).
use
{
c
->
while
(
c
.
moveToNext
())
{
set
.
add
(
c
.
getString
(
c
.
getColumnIndex
(
"id"
)))
}
}
return
set
}
override
fun
onCreate
(
db
:
SQLiteDatabase
)
{
onUpgrade
(
db
,
0
,
DATABASE_VER
)
}
override
fun
onUpgrade
(
db
:
SQLiteDatabase
,
oldVersion
:
Int
,
newVersion
:
Int
)
{
if
(
oldVersion
!=
newVersion
)
{
// Nuke old DB and create new table
db
.
execSQL
(
"DROP TABLE IF EXISTS $TABLE_NAME"
)
db
.
execSQL
(
"CREATE TABLE IF NOT EXISTS "
+
TABLE_NAME
+
" "
+
"(id TEXT, name TEXT, version TEXT, versionCode INT, "
+
"author TEXT, description TEXT, last_update INT, PRIMARY KEY(id))"
)
Config
.
prefs
.
edit
{
remove
(
Config
.
Key
.
ETAG_KEY
)
}
}
}
override
fun
onDowngrade
(
db
:
SQLiteDatabase
,
oldVersion
:
Int
,
newVersion
:
Int
)
{
onUpgrade
(
db
,
0
,
DATABASE_VER
)
}
@Deprecated
(
""
)
fun
clearRepo
()
{
mDb
.
delete
(
TABLE_NAME
,
null
,
null
)
}
@Deprecated
(
""
)
fun
removeRepo
(
id
:
String
)
{
mDb
.
delete
(
TABLE_NAME
,
"id=?"
,
arrayOf
(
id
))
}
@Deprecated
(
""
)
fun
removeRepo
(
repo
:
Repo
)
{
removeRepo
(
repo
.
id
)
}
@Deprecated
(
""
)
fun
removeRepo
(
list
:
Iterable
<
String
>)
{
list
.
forEach
{
mDb
.
delete
(
TABLE_NAME
,
"id=?"
,
arrayOf
(
it
))
}
}
@Deprecated
(
""
)
fun
addRepo
(
repo
:
Repo
)
{
mDb
.
replace
(
TABLE_NAME
,
null
,
repo
.
contentValues
)
}
@Deprecated
(
""
)
fun
getRepo
(
id
:
String
):
Repo
?
{
mDb
.
query
(
TABLE_NAME
,
null
,
"id=?"
,
arrayOf
(
id
),
null
,
null
,
null
).
use
{
c
->
if
(
c
.
moveToNext
())
{
return
Repo
(
c
)
}
}
return
null
}
companion
object
{
private
val
DATABASE_VER
=
5
private
val
TABLE_NAME
=
"repos"
}
}
app/src/main/java/com/topjohnwu/magisk/data/network/GithubRawApiServices.kt
View file @
7756e107
package
com.topjohnwu.magisk.data.network
package
com.topjohnwu.magisk.data.network
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.KConfig
import
com.topjohnwu.magisk.model.entity.MagiskConfig
import
com.topjohnwu.magisk.model.entity.MagiskConfig
import
io.reactivex.Single
import
io.reactivex.Single
import
okhttp3.ResponseBody
import
okhttp3.ResponseBody
...
@@ -16,19 +15,19 @@ interface GithubRawApiServices {
...
@@ -16,19 +15,19 @@ interface GithubRawApiServices {
//region topjohnwu/magisk_files
//region topjohnwu/magisk_files
@GET
(
"$MAGISK_FILES/master/stable.json"
)
@GET
(
"$MAGISK_FILES/master/stable.json"
)
fun
fetch
Config
():
Single
<
MagiskConfig
>
fun
fetch
StableUpdate
():
Single
<
MagiskConfig
>
@GET
(
"$MAGISK_FILES/master/beta.json"
)
@GET
(
"$MAGISK_FILES/master/beta.json"
)
fun
fetchBeta
Config
():
Single
<
MagiskConfig
>
fun
fetchBeta
Update
():
Single
<
MagiskConfig
>
@GET
(
"$MAGISK_FILES/master/canary_builds/release.json"
)
@GET
(
"$MAGISK_FILES/master/canary_builds/release.json"
)
fun
fetchCanary
Config
():
Single
<
MagiskConfig
>
fun
fetchCanary
Update
():
Single
<
MagiskConfig
>
@GET
(
"$MAGISK_FILES/master/canary_builds/canary.json"
)
@GET
(
"$MAGISK_FILES/master/canary_builds/canary.json"
)
fun
fetchCanaryDebug
Config
():
Single
<
MagiskConfig
>
fun
fetchCanaryDebug
Update
():
Single
<
MagiskConfig
>
@GET
@GET
fun
fetchCustom
Config
(
@Url
url
:
String
):
Single
<
MagiskConfig
>
fun
fetchCustom
Update
(
@Url
url
:
String
):
Single
<
MagiskConfig
>
@GET
(
"$MAGISK_FILES/{$REVISION}/snet.apk"
)
@GET
(
"$MAGISK_FILES/{$REVISION}/snet.apk"
)
@Streaming
@Streaming
...
@@ -55,7 +54,7 @@ interface GithubRawApiServices {
...
@@ -55,7 +54,7 @@ interface GithubRawApiServices {
private
const
val
FILE
=
"file"
private
const
val
FILE
=
"file"
private
const
val
MAGISK_FILES
=
KConfig
.
DEFAULT_CHANNEL
private
const
val
MAGISK_FILES
=
"topjohnwu/magisk_files"
private
const
val
MAGISK_MASTER
=
"topjohnwu/Magisk/master"
private
const
val
MAGISK_MASTER
=
"topjohnwu/Magisk/master"
private
const
val
MAGISK_MODULES
=
"Magisk-Modules-Repo"
private
const
val
MAGISK_MODULES
=
"Magisk-Modules-Repo"
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/data/repository/DBConfig.kt
0 → 100644
View file @
7756e107
package
com.topjohnwu.magisk.data.repository
import
com.topjohnwu.magisk.data.database.SettingsDao
import
com.topjohnwu.magisk.data.database.StringDao
import
com.topjohnwu.magisk.utils.trimEmptyToNull
import
io.reactivex.schedulers.Schedulers
import
kotlin.properties.ReadWriteProperty
import
kotlin.reflect.KProperty
interface
DBConfig
{
val
settingsDao
:
SettingsDao
val
stringDao
:
StringDao
fun
dbSettings
(
name
:
String
,
default
:
Int
)
=
DBSettingsValue
(
name
,
default
)
fun
dbSettings
(
name
:
String
,
default
:
Boolean
)
=
DBBoolSettings
(
name
,
default
)
fun
dbStrings
(
name
:
String
,
default
:
String
)
=
DBStringsValue
(
name
,
default
)
}
class
DBSettingsValue
(
private
val
name
:
String
,
private
val
default
:
Int
)
:
ReadWriteProperty
<
DBConfig
,
Int
>
{
private
var
value
:
Int
?
=
null
private
fun
getKey
(
property
:
KProperty
<
*
>)
=
name
.
trimEmptyToNull
()
?:
property
.
name
@Synchronized
override
fun
getValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>):
Int
{
if
(
value
==
null
)
value
=
thisRef
.
settingsDao
.
fetch
(
getKey
(
property
),
default
).
blockingGet
()
return
value
!!
}
override
fun
setValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>,
value
:
Int
)
{
synchronized
(
this
)
{
this
.
value
=
value
}
thisRef
.
settingsDao
.
put
(
getKey
(
property
),
value
)
.
subscribeOn
(
Schedulers
.
io
())
.
subscribe
()
}
}
class
DBBoolSettings
(
name
:
String
,
default
:
Boolean
)
:
ReadWriteProperty
<
DBConfig
,
Boolean
>
{
val
base
=
DBSettingsValue
(
name
,
if
(
default
)
1
else
0
)
override
fun
getValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>):
Boolean
=
base
.
getValue
(
thisRef
,
property
)
!=
0
override
fun
setValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>,
value
:
Boolean
)
=
base
.
setValue
(
thisRef
,
property
,
if
(
value
)
1
else
0
)
}
class
DBStringsValue
(
private
val
name
:
String
,
private
val
default
:
String
)
:
ReadWriteProperty
<
DBConfig
,
String
>
{
private
var
value
:
String
?
=
null
private
fun
getKey
(
property
:
KProperty
<
*
>)
=
name
.
trimEmptyToNull
()
?:
property
.
name
@Synchronized
override
fun
getValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>):
String
{
if
(
value
==
null
)
value
=
thisRef
.
stringDao
.
fetch
(
getKey
(
property
),
default
).
blockingGet
()
return
value
!!
}
override
fun
setValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>,
value
:
String
)
{
synchronized
(
this
)
{
this
.
value
=
value
}
thisRef
.
stringDao
.
put
(
getKey
(
property
),
value
)
.
subscribeOn
(
Schedulers
.
io
())
.
subscribe
()
}
}
app/src/main/java/com/topjohnwu/magisk/data/repository/MagiskRepository.kt
View file @
7756e107
...
@@ -4,20 +4,17 @@ import android.content.Context
...
@@ -4,20 +4,17 @@ import android.content.Context
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager
import
com.topjohnwu.magisk.App
import
com.topjohnwu.magisk.App
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.
KConfig
import
com.topjohnwu.magisk.
Info
import
com.topjohnwu.magisk.data.database.base.su
import
com.topjohnwu.magisk.data.database.base.su
import
com.topjohnwu.magisk.data.database.base.suRaw
import
com.topjohnwu.magisk.data.network.GithubRawApiServices
import
com.topjohnwu.magisk.data.network.GithubRawApiServices
import
com.topjohnwu.magisk.model.entity.HideAppInfo
import
com.topjohnwu.magisk.model.entity.HideAppInfo
import
com.topjohnwu.magisk.model.entity.HideTarget
import
com.topjohnwu.magisk.model.entity.HideTarget
import
com.topjohnwu.magisk.model.entity.Version
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.magisk.utils.inject
import
com.topjohnwu.magisk.utils.inject
import
com.topjohnwu.magisk.utils.toSingle
import
com.topjohnwu.magisk.utils.toSingle
import
com.topjohnwu.magisk.utils.writeToFile
import
com.topjohnwu.magisk.utils.writeToFile
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
io.reactivex.Single
import
io.reactivex.Single
import
io.reactivex.functions.BiFunction
class
MagiskRepository
(
class
MagiskRepository
(
private
val
context
:
Context
,
private
val
context
:
Context
,
...
@@ -25,15 +22,15 @@ class MagiskRepository(
...
@@ -25,15 +22,15 @@ class MagiskRepository(
private
val
packageManager
:
PackageManager
private
val
packageManager
:
PackageManager
)
{
)
{
fun
fetchMagisk
()
=
fetch
Config
()
fun
fetchMagisk
()
=
fetch
Update
()
.
flatMap
{
apiRaw
.
fetchFile
(
it
.
magisk
.
link
)
}
.
flatMap
{
apiRaw
.
fetchFile
(
it
.
magisk
.
link
)
}
.
map
{
it
.
writeToFile
(
context
,
FILE_MAGISK_ZIP
)
}
.
map
{
it
.
writeToFile
(
context
,
FILE_MAGISK_ZIP
)
}
fun
fetchManager
()
=
fetch
Config
()
fun
fetchManager
()
=
fetch
Update
()
.
flatMap
{
apiRaw
.
fetchFile
(
it
.
app
.
link
)
}
.
flatMap
{
apiRaw
.
fetchFile
(
it
.
app
.
link
)
}
.
map
{
it
.
writeToFile
(
context
,
FILE_MAGISK_APK
)
}
.
map
{
it
.
writeToFile
(
context
,
FILE_MAGISK_APK
)
}
fun
fetchUninstaller
()
=
fetch
Config
()
fun
fetchUninstaller
()
=
fetch
Update
()
.
flatMap
{
apiRaw
.
fetchFile
(
it
.
uninstaller
.
link
)
}
.
flatMap
{
apiRaw
.
fetchFile
(
it
.
uninstaller
.
link
)
}
.
map
{
it
.
writeToFile
(
context
,
FILE_UNINSTALLER_ZIP
)
}
.
map
{
it
.
writeToFile
(
context
,
FILE_UNINSTALLER_ZIP
)
}
...
@@ -44,23 +41,35 @@ class MagiskRepository(
...
@@ -44,23 +41,35 @@ class MagiskRepository(
.
map
{
it
.
writeToFile
(
context
,
FILE_BOOTCTL_SH
)
}
.
map
{
it
.
writeToFile
(
context
,
FILE_BOOTCTL_SH
)
}
fun
fetchConfig
()
=
when
(
KConfig
.
updateChannel
)
{
fun
fetchUpdate
()
=
when
(
Config
.
updateChannel
)
{
KConfig
.
UpdateChannel
.
STABLE
->
apiRaw
.
fetchConfig
()
Config
.
Value
.
DEFAULT_CHANNEL
,
Config
.
Value
.
STABLE_CHANNEL
->
apiRaw
.
fetchStableUpdate
()
KConfig
.
UpdateChannel
.
BETA
->
apiRaw
.
fetchBetaConfig
()
Config
.
Value
.
BETA_CHANNEL
->
apiRaw
.
fetchBetaUpdate
()
KConfig
.
UpdateChannel
.
CANARY
->
apiRaw
.
fetchCanaryConfig
()
Config
.
Value
.
CANARY_CHANNEL
->
apiRaw
.
fetchCanaryUpdate
()
KConfig
.
UpdateChannel
.
CANARY_DEBUG
->
apiRaw
.
fetchCanaryDebugConfig
()
Config
.
Value
.
CANARY_DEBUG_CHANNEL
->
apiRaw
.
fetchCanaryDebugUpdate
()
KConfig
.
UpdateChannel
.
CUSTOM
->
apiRaw
.
fetchCustomConfig
(
KConfig
.
customUpdateChannel
)
Config
.
Value
.
CUSTOM_CHANNEL
->
apiRaw
.
fetchCustomUpdate
(
Config
.
customChannelUrl
)
}
else
->
throw
IllegalArgumentException
()
.
doOnSuccess
{
}.
flatMap
{
Config
.
remoteMagiskVersionCode
=
it
.
magisk
.
versionCode
.
toIntOrNull
()
?:
-
1
// If remote version is lower than current installed, try switching to beta
Config
.
magiskLink
=
it
.
magisk
.
link
if
(
it
.
magisk
.
versionCode
.
toIntOrNull
()
?:
-
1
<
Info
.
magiskVersionCode
Config
.
magiskNoteLink
=
it
.
magisk
.
note
&&
Config
.
updateChannel
==
Config
.
Value
.
DEFAULT_CHANNEL
)
{
Config
.
magiskMD5
=
it
.
magisk
.
hash
Config
.
updateChannel
=
Config
.
Value
.
BETA_CHANNEL
Config
.
remoteManagerVersionCode
=
it
.
app
.
versionCode
.
toIntOrNull
()
?:
-
1
apiRaw
.
fetchBetaUpdate
()
Config
.
remoteManagerVersionString
=
it
.
app
.
version
}
else
{
Config
.
managerLink
=
it
.
app
.
link
Single
.
just
(
it
)
Config
.
managerNoteLink
=
it
.
app
.
note
}
Config
.
uninstallerLink
=
it
.
uninstaller
.
link
}.
doOnSuccess
{
Info
.
remoteMagiskVersionString
=
it
.
magisk
.
version
Info
.
remoteMagiskVersionCode
=
it
.
magisk
.
versionCode
.
toIntOrNull
()
?:
-
1
Info
.
magiskLink
=
it
.
magisk
.
link
Info
.
magiskNoteLink
=
it
.
magisk
.
note
Info
.
magiskMD5
=
it
.
magisk
.
hash
Info
.
remoteManagerVersionString
=
it
.
app
.
version
Info
.
remoteManagerVersionCode
=
it
.
app
.
versionCode
.
toIntOrNull
()
?:
-
1
Info
.
managerLink
=
it
.
app
.
link
Info
.
managerNoteLink
=
it
.
app
.
note
Info
.
uninstallerLink
=
it
.
uninstaller
.
link
}
}
fun
fetchApps
()
=
fun
fetchApps
()
=
...
...
app/src/main/java/com/topjohnwu/magisk/data/repository/SettingRepository.kt
deleted
100644 → 0
View file @
3e58d502
package
com.topjohnwu.magisk.data.repository
import
com.topjohnwu.magisk.data.database.SettingsDao
class
SettingRepository
(
private
val
settingsDao
:
SettingsDao
)
{
fun
fetch
(
key
:
String
,
default
:
Int
)
=
settingsDao
.
fetch
(
key
,
default
)
fun
put
(
key
:
String
,
value
:
Int
)
=
settingsDao
.
put
(
key
,
value
)
fun
delete
(
key
:
String
)
=
settingsDao
.
delete
(
key
)
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/data/repository/StringRepository.kt
deleted
100644 → 0
View file @
3e58d502
package
com.topjohnwu.magisk.data.repository
import
com.topjohnwu.magisk.data.database.StringDao
class
StringRepository
(
private
val
stringDao
:
StringDao
)
{
fun
fetch
(
key
:
String
,
default
:
String
)
=
stringDao
.
fetch
(
key
,
default
)
fun
put
(
key
:
String
,
value
:
String
)
=
stringDao
.
put
(
key
,
value
)
fun
delete
(
key
:
String
)
=
stringDao
.
delete
(
key
)
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/di/RepositoryModule.kt
View file @
7756e107
...
@@ -8,6 +8,4 @@ val repositoryModule = module {
...
@@ -8,6 +8,4 @@ val repositoryModule = module {
single
{
MagiskRepository
(
get
(),
get
(),
get
())
}
single
{
MagiskRepository
(
get
(),
get
(),
get
())
}
single
{
LogRepository
(
get
())
}
single
{
LogRepository
(
get
())
}
single
{
AppRepository
(
get
())
}
single
{
AppRepository
(
get
())
}
single
{
SettingRepository
(
get
())
}
single
{
StringRepository
(
get
())
}
}
}
app/src/main/java/com/topjohnwu/magisk/model/download/DownloadModuleService.java
View file @
7756e107
...
@@ -6,6 +6,8 @@ import android.content.Intent;
...
@@ -6,6 +6,8 @@ import android.content.Intent;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.os.IBinder
;
import
android.os.IBinder
;
import
androidx.annotation.Nullable
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Const
;
...
@@ -29,8 +31,6 @@ import java.util.zip.ZipEntry;
...
@@ -29,8 +31,6 @@ import java.util.zip.ZipEntry;
import
java.util.zip.ZipInputStream
;
import
java.util.zip.ZipInputStream
;
import
java.util.zip.ZipOutputStream
;
import
java.util.zip.ZipOutputStream
;
import
androidx.annotation.Nullable
;
public
class
DownloadModuleService
extends
Service
{
public
class
DownloadModuleService
extends
Service
{
private
List
<
ProgressNotification
>
notifications
;
private
List
<
ProgressNotification
>
notifications
;
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/BaseModule.java
View file @
7756e107
...
@@ -5,10 +5,10 @@ import android.database.Cursor;
...
@@ -5,10 +5,10 @@ import android.database.Cursor;
import
android.os.Parcel
;
import
android.os.Parcel
;
import
android.os.Parcelable
;
import
android.os.Parcelable
;
import
java.util.List
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.NonNull
;
import
java.util.List
;
public
abstract
class
BaseModule
implements
Comparable
<
BaseModule
>,
Parcelable
{
public
abstract
class
BaseModule
implements
Comparable
<
BaseModule
>,
Parcelable
{
private
String
mId
,
mName
,
mVersion
,
mAuthor
,
mDescription
;
private
String
mId
,
mName
,
mVersion
,
mAuthor
,
mDescription
;
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/Policy.java
View file @
7756e107
...
@@ -4,10 +4,10 @@ import android.content.ContentValues;
...
@@ -4,10 +4,10 @@ import android.content.ContentValues;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.PackageManager
;
import
android.content.pm.PackageManager
;
import
com.topjohnwu.magisk.utils.Utils
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.NonNull
;
import
com.topjohnwu.magisk.utils.Utils
;
public
class
Policy
implements
Comparable
<
Policy
>{
public
class
Policy
implements
Comparable
<
Policy
>{
public
static
final
int
INTERACTIVE
=
0
;
public
static
final
int
INTERACTIVE
=
0
;
...
@@ -27,7 +27,7 @@ public class Policy implements Comparable<Policy>{
...
@@ -27,7 +27,7 @@ public class Policy implements Comparable<Policy>{
this
.
uid
=
uid
;
this
.
uid
=
uid
;
packageName
=
pkgs
[
0
];
packageName
=
pkgs
[
0
];
info
=
pm
.
getApplicationInfo
(
packageName
,
0
);
info
=
pm
.
getApplicationInfo
(
packageName
,
0
);
appName
=
Utils
.
getAppLabel
(
info
,
pm
);
appName
=
Utils
.
INSTANCE
.
getAppLabel
(
info
,
pm
);
}
}
public
Policy
(
ContentValues
values
,
PackageManager
pm
)
throws
PackageManager
.
NameNotFoundException
{
public
Policy
(
ContentValues
values
,
PackageManager
pm
)
throws
PackageManager
.
NameNotFoundException
{
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/Repo.java
View file @
7756e107
...
@@ -54,7 +54,7 @@ public class Repo extends BaseModule {
...
@@ -54,7 +54,7 @@ public class Repo extends BaseModule {
}
}
public
void
update
()
throws
IllegalRepoException
{
public
void
update
()
throws
IllegalRepoException
{
String
[]
props
=
Utils
.
dlString
(
getPropUrl
()).
split
(
"\\n"
);
String
[]
props
=
Utils
.
INSTANCE
.
dlString
(
getPropUrl
()).
split
(
"\\n"
);
try
{
try
{
parseProps
(
props
);
parseProps
(
props
);
}
catch
(
NumberFormatException
e
)
{
}
catch
(
NumberFormatException
e
)
{
...
@@ -103,7 +103,7 @@ public class Repo extends BaseModule {
...
@@ -103,7 +103,7 @@ public class Repo extends BaseModule {
}
}
public
String
getDownloadFilename
()
{
public
String
getDownloadFilename
()
{
return
Utils
.
getLegalFilename
(
getName
()
+
"-"
+
getVersion
()
+
".zip"
);
return
Utils
.
INSTANCE
.
getLegalFilename
(
getName
()
+
"-"
+
getVersion
()
+
".zip"
);
}
}
public
class
IllegalRepoException
extends
Exception
{
public
class
IllegalRepoException
extends
Exception
{
...
...
app/src/main/java/com/topjohnwu/magisk/model/preference/PreferenceModel.kt
View file @
7756e107
...
@@ -2,6 +2,8 @@ package com.topjohnwu.magisk.model.preference
...
@@ -2,6 +2,8 @@ package com.topjohnwu.magisk.model.preference
import
android.content.Context
import
android.content.Context
import
android.content.SharedPreferences
import
android.content.SharedPreferences
import
kotlin.properties.ReadWriteProperty
import
kotlin.reflect.KProperty
interface
PreferenceModel
{
interface
PreferenceModel
{
...
@@ -14,6 +16,20 @@ interface PreferenceModel {
...
@@ -14,6 +16,20 @@ interface PreferenceModel {
val
prefs
:
SharedPreferences
val
prefs
:
SharedPreferences
get
()
=
context
.
getSharedPreferences
(
fileName
,
Context
.
MODE_PRIVATE
)
get
()
=
context
.
getSharedPreferences
(
fileName
,
Context
.
MODE_PRIVATE
)
fun
preferenceStrInt
(
name
:
String
,
default
:
Int
,
writeDefault
:
Boolean
=
false
,
commit
:
Boolean
=
commitPrefs
)
=
object
:
ReadWriteProperty
<
PreferenceModel
,
Int
>
{
val
base
=
StringProperty
(
name
,
default
.
toString
(),
commit
)
override
fun
getValue
(
thisRef
:
PreferenceModel
,
property
:
KProperty
<
*
>):
Int
=
base
.
getValue
(
thisRef
,
property
).
toInt
()
override
fun
setValue
(
thisRef
:
PreferenceModel
,
property
:
KProperty
<
*
>,
value
:
Int
)
=
base
.
setValue
(
thisRef
,
property
,
value
.
toString
())
}
fun
preference
(
fun
preference
(
name
:
String
,
name
:
String
,
default
:
Boolean
,
default
:
Boolean
,
...
...
app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt
View file @
7756e107
...
@@ -6,6 +6,7 @@ import android.content.Intent
...
@@ -6,6 +6,7 @@ import android.content.Intent
import
com.topjohnwu.magisk.ClassMap
import
com.topjohnwu.magisk.ClassMap
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.Info
import
com.topjohnwu.magisk.data.database.base.su
import
com.topjohnwu.magisk.data.database.base.su
import
com.topjohnwu.magisk.data.repository.AppRepository
import
com.topjohnwu.magisk.data.repository.AppRepository
import
com.topjohnwu.magisk.ui.surequest.SuRequestActivity
import
com.topjohnwu.magisk.ui.surequest.SuRequestActivity
...
@@ -13,7 +14,6 @@ import com.topjohnwu.magisk.utils.DownloadApp
...
@@ -13,7 +14,6 @@ import com.topjohnwu.magisk.utils.DownloadApp
import
com.topjohnwu.magisk.utils.RootUtils
import
com.topjohnwu.magisk.utils.RootUtils
import
com.topjohnwu.magisk.utils.SuLogger
import
com.topjohnwu.magisk.utils.SuLogger
import
com.topjohnwu.magisk.utils.inject
import
com.topjohnwu.magisk.utils.inject
import
com.topjohnwu.magisk.utils.get
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.magisk.view.Shortcuts
import
com.topjohnwu.magisk.view.Shortcuts
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
...
@@ -64,9 +64,8 @@ open class GeneralReceiver : BroadcastReceiver() {
...
@@ -64,9 +64,8 @@ open class GeneralReceiver : BroadcastReceiver() {
}
}
Intent
.
ACTION_PACKAGE_REPLACED
->
Intent
.
ACTION_PACKAGE_REPLACED
->
// This will only work pre-O
// This will only work pre-O
if
(
Config
.
get
<
Boolean
>(
Config
.
Key
.
SU_REAUTH
)
!!
)
{
if
(
Config
.
suReAuth
)
appRepo
.
delete
(
getPkg
(
intent
)).
blockingGet
()
appRepo
.
delete
(
getPkg
(
intent
)).
blockingGet
()
}
Intent
.
ACTION_PACKAGE_FULLY_REMOVED
->
{
Intent
.
ACTION_PACKAGE_FULLY_REMOVED
->
{
val
pkg
=
getPkg
(
intent
)
val
pkg
=
getPkg
(
intent
)
appRepo
.
delete
(
pkg
).
blockingGet
()
appRepo
.
delete
(
pkg
).
blockingGet
()
...
@@ -74,7 +73,7 @@ open class GeneralReceiver : BroadcastReceiver() {
...
@@ -74,7 +73,7 @@ open class GeneralReceiver : BroadcastReceiver() {
}
}
Intent
.
ACTION_LOCALE_CHANGED
->
Shortcuts
.
setup
(
context
)
Intent
.
ACTION_LOCALE_CHANGED
->
Shortcuts
.
setup
(
context
)
Const
.
Key
.
BROADCAST_MANAGER_UPDATE
->
{
Const
.
Key
.
BROADCAST_MANAGER_UPDATE
->
{
Config
.
managerLink
=
intent
.
getStringExtra
(
Const
.
Key
.
INTENT_SET_LINK
)
Info
.
managerLink
=
intent
.
getStringExtra
(
Const
.
Key
.
INTENT_SET_LINK
)
DownloadApp
.
upgrade
(
intent
.
getStringExtra
(
Const
.
Key
.
INTENT_SET_NAME
))
DownloadApp
.
upgrade
(
intent
.
getStringExtra
(
Const
.
Key
.
INTENT_SET_NAME
))
}
}
Const
.
Key
.
BROADCAST_REBOOT
->
RootUtils
.
reboot
()
Const
.
Key
.
BROADCAST_REBOOT
->
RootUtils
.
reboot
()
...
...
app/src/main/java/com/topjohnwu/magisk/model/update/UpdateCheckService.kt
View file @
7756e107
...
@@ -2,7 +2,7 @@ package com.topjohnwu.magisk.model.update
...
@@ -2,7 +2,7 @@ package com.topjohnwu.magisk.model.update
import
androidx.work.ListenableWorker
import
androidx.work.ListenableWorker
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.
Config
import
com.topjohnwu.magisk.
Info
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.model.worker.DelegateWorker
import
com.topjohnwu.magisk.model.worker.DelegateWorker
import
com.topjohnwu.magisk.utils.inject
import
com.topjohnwu.magisk.utils.inject
...
@@ -14,10 +14,10 @@ class UpdateCheckService : DelegateWorker() {
...
@@ -14,10 +14,10 @@ class UpdateCheckService : DelegateWorker() {
override
fun
doWork
():
ListenableWorker
.
Result
{
override
fun
doWork
():
ListenableWorker
.
Result
{
return
runCatching
{
return
runCatching
{
magiskRepo
.
fetch
Config
().
blockingGet
()
magiskRepo
.
fetch
Update
().
blockingGet
()
if
(
BuildConfig
.
VERSION_CODE
<
Config
.
remoteManagerVersionCode
)
if
(
BuildConfig
.
VERSION_CODE
<
Info
.
remoteManagerVersionCode
)
Notifications
.
managerUpdate
()
Notifications
.
managerUpdate
()
else
if
(
Config
.
magiskVersionCode
<
Config
.
remoteManagerVersionCode
)
else
if
(
Info
.
magiskVersionCode
<
Info
.
remoteManagerVersionCode
)
Notifications
.
magiskUpdate
()
Notifications
.
magiskUpdate
()
ListenableWorker
.
Result
.
success
()
ListenableWorker
.
Result
.
success
()
}.
getOrElse
{
}.
getOrElse
{
...
...
app/src/main/java/com/topjohnwu/magisk/model/worker/DelegateWorker.java
View file @
7756e107
...
@@ -4,12 +4,6 @@ import android.content.Context;
...
@@ -4,12 +4,6 @@ import android.content.Context;
import
android.net.Network
;
import
android.net.Network
;
import
android.net.Uri
;
import
android.net.Uri
;
import
com.google.common.util.concurrent.ListenableFuture
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.UUID
;
import
androidx.annotation.MainThread
;
import
androidx.annotation.MainThread
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
...
@@ -17,6 +11,12 @@ import androidx.annotation.RequiresApi;
...
@@ -17,6 +11,12 @@ import androidx.annotation.RequiresApi;
import
androidx.work.Data
;
import
androidx.work.Data
;
import
androidx.work.ListenableWorker
;
import
androidx.work.ListenableWorker
;
import
com.google.common.util.concurrent.ListenableFuture
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.UUID
;
public
abstract
class
DelegateWorker
{
public
abstract
class
DelegateWorker
{
private
ListenableWorker
worker
;
private
ListenableWorker
worker
;
...
...
app/src/main/java/com/topjohnwu/magisk/tasks/MagiskInstaller.java
View file @
7756e107
...
@@ -8,8 +8,8 @@ import androidx.annotation.MainThread;
...
@@ -8,8 +8,8 @@ import androidx.annotation.MainThread;
import
androidx.annotation.WorkerThread
;
import
androidx.annotation.WorkerThread
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Info
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.net.DownloadProgressListener
;
import
com.topjohnwu.net.DownloadProgressListener
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.net.Networking
;
...
@@ -123,9 +123,9 @@ public abstract class MagiskInstaller {
...
@@ -123,9 +123,9 @@ public abstract class MagiskInstaller {
File
zip
=
new
File
(
App
.
self
.
getCacheDir
(),
"magisk.zip"
);
File
zip
=
new
File
(
App
.
self
.
getCacheDir
(),
"magisk.zip"
);
if
(!
ShellUtils
.
checkSum
(
"MD5"
,
zip
,
Config
.
magiskMD5
))
{
if
(!
ShellUtils
.
checkSum
(
"MD5"
,
zip
,
Info
.
magiskMD5
))
{
console
.
add
(
"- Downloading zip"
);
console
.
add
(
"- Downloading zip"
);
Networking
.
get
(
Config
.
magiskLink
)
Networking
.
get
(
Info
.
magiskLink
)
.
setDownloadProgressListener
(
new
ProgressLog
())
.
setDownloadProgressListener
(
new
ProgressLog
())
.
execForFile
(
zip
);
.
execForFile
(
zip
);
}
else
{
}
else
{
...
@@ -282,10 +282,10 @@ public abstract class MagiskInstaller {
...
@@ -282,10 +282,10 @@ public abstract class MagiskInstaller {
return
false
;
return
false
;
}
}
if
(!
Shell
.
sh
(
Utils
.
fmt
(
if
(!
Shell
.
sh
(
Utils
.
INSTANCE
.
fmt
(
"KEEPFORCEENCRYPT=%b KEEPVERITY=%b RECOVERYMODE=%b "
+
"KEEPFORCEENCRYPT=%b KEEPVERITY=%b RECOVERYMODE=%b "
+
"sh update-binary sh boot_patch.sh %s"
,
"sh update-binary sh boot_patch.sh %s"
,
Config
.
keepEnc
,
Config
.
keepVerity
,
Config
.
recovery
,
srcBoot
))
Info
.
keepEnc
,
Info
.
keepVerity
,
Info
.
recovery
,
srcBoot
))
.
to
(
console
,
logs
).
exec
().
isSuccess
())
.
to
(
console
,
logs
).
exec
().
isSuccess
())
return
false
;
return
false
;
...
@@ -311,10 +311,10 @@ public abstract class MagiskInstaller {
...
@@ -311,10 +311,10 @@ public abstract class MagiskInstaller {
}
}
protected
boolean
flashBoot
()
{
protected
boolean
flashBoot
()
{
if
(!
Shell
.
su
(
Utils
.
fmt
(
"direct_install %s %s"
,
installDir
,
srcBoot
))
if
(!
Shell
.
su
(
Utils
.
INSTANCE
.
fmt
(
"direct_install %s %s"
,
installDir
,
srcBoot
))
.
to
(
console
,
logs
).
exec
().
isSuccess
())
.
to
(
console
,
logs
).
exec
().
isSuccess
())
return
false
;
return
false
;
if
(!
Config
.
keepVerity
)
if
(!
Info
.
keepVerity
)
Shell
.
su
(
"patch_dtbo_image"
).
to
(
console
,
logs
).
exec
();
Shell
.
su
(
"patch_dtbo_image"
).
to
(
console
,
logs
).
exec
();
return
true
;
return
true
;
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/tasks/UpdateRepos.java
View file @
7756e107
...
@@ -3,6 +3,8 @@ package com.topjohnwu.magisk.tasks;
...
@@ -3,6 +3,8 @@ package com.topjohnwu.magisk.tasks;
import
android.database.Cursor
;
import
android.database.Cursor
;
import
android.util.Pair
;
import
android.util.Pair
;
import
androidx.annotation.NonNull
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Const
;
...
@@ -31,7 +33,6 @@ import java.util.concurrent.ConcurrentLinkedQueue;
...
@@ -31,7 +33,6 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.Future
;
import
androidx.annotation.NonNull
;
import
io.reactivex.Single
;
import
io.reactivex.Single
;
@Deprecated
@Deprecated
...
@@ -74,10 +75,10 @@ public class UpdateRepos {
...
@@ -74,10 +75,10 @@ public class UpdateRepos {
* first page is updated to determine whether the online repo database is changed
* first page is updated to determine whether the online repo database is changed
*/
*/
private
boolean
parsePage
(
int
page
)
{
private
boolean
parsePage
(
int
page
)
{
Request
req
=
Networking
.
get
(
Utils
.
fmt
(
Const
.
Url
.
REPO_URL
,
page
+
1
));
Request
req
=
Networking
.
get
(
Utils
.
INSTANCE
.
fmt
(
Const
.
Url
.
REPO_URL
,
page
+
1
));
if
(
page
==
0
)
{
if
(
page
==
0
)
{
String
etag
=
Config
.
get
(
Config
.
Key
.
ETAG_KEY
);
String
etag
=
Config
.
get
EtagKey
(
);
if
(
etag
!=
null
)
if
(
!
etag
.
isEmpty
()
)
req
.
addHeaders
(
Const
.
Key
.
IF_NONE_MATCH
,
etag
);
req
.
addHeaders
(
Const
.
Key
.
IF_NONE_MATCH
,
etag
);
}
}
Request
.
Result
<
JSONArray
>
res
=
req
.
execForJSONArray
();
Request
.
Result
<
JSONArray
>
res
=
req
.
execForJSONArray
();
...
@@ -110,7 +111,7 @@ public class UpdateRepos {
...
@@ -110,7 +111,7 @@ public class UpdateRepos {
String
etag
=
res
.
getConnection
().
getHeaderField
(
Config
.
Key
.
ETAG_KEY
);
String
etag
=
res
.
getConnection
().
getHeaderField
(
Config
.
Key
.
ETAG_KEY
);
if
(
etag
!=
null
)
{
if
(
etag
!=
null
)
{
etag
=
etag
.
substring
(
etag
.
indexOf
(
'\"'
),
etag
.
lastIndexOf
(
'\"'
)
+
1
);
etag
=
etag
.
substring
(
etag
.
indexOf
(
'\"'
),
etag
.
lastIndexOf
(
'\"'
)
+
1
);
Config
.
set
(
Config
.
Key
.
ETAG_KEY
,
etag
);
Config
.
set
EtagKey
(
etag
);
}
}
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt
View file @
7756e107
...
@@ -7,6 +7,7 @@ import androidx.fragment.app.Fragment
...
@@ -7,6 +7,7 @@ import androidx.fragment.app.Fragment
import
com.topjohnwu.magisk.ClassMap
import
com.topjohnwu.magisk.ClassMap
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Const.Key.OPEN_SECTION
import
com.topjohnwu.magisk.Const.Key.OPEN_SECTION
import
com.topjohnwu.magisk.Info
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ActivityMainBinding
import
com.topjohnwu.magisk.databinding.ActivityMainBinding
import
com.topjohnwu.magisk.model.navigation.Navigation
import
com.topjohnwu.magisk.model.navigation.Navigation
...
@@ -105,11 +106,11 @@ open class MainActivity : MagiskActivity<MainViewModel, ActivityMainBinding>() {
...
@@ -105,11 +106,11 @@ open class MainActivity : MagiskActivity<MainViewModel, ActivityMainBinding>() {
private
fun
checkHideSection
()
{
private
fun
checkHideSection
()
{
val
menu
=
binding
.
navView
.
menu
val
menu
=
binding
.
navView
.
menu
menu
.
findItem
(
R
.
id
.
magiskHideFragment
).
isVisible
=
menu
.
findItem
(
R
.
id
.
magiskHideFragment
).
isVisible
=
Shell
.
rootAccess
()
&&
Config
.
get
<
Any
>(
Config
.
Key
.
MAGISKHIDE
)
as
Boolean
Shell
.
rootAccess
()
&&
Config
.
magiskHide
menu
.
findItem
(
R
.
id
.
modulesFragment
).
isVisible
=
menu
.
findItem
(
R
.
id
.
modulesFragment
).
isVisible
=
Shell
.
rootAccess
()
&&
Config
.
magiskVersionCode
>=
0
Shell
.
rootAccess
()
&&
Info
.
magiskVersionCode
>=
0
menu
.
findItem
(
R
.
id
.
reposFragment
).
isVisible
=
menu
.
findItem
(
R
.
id
.
reposFragment
).
isVisible
=
(
Networking
.
checkNetworkStatus
(
this
)
&&
Shell
.
rootAccess
()
&&
Config
.
magiskVersionCode
>=
0
)
(
Networking
.
checkNetworkStatus
(
this
)
&&
Shell
.
rootAccess
()
&&
Info
.
magiskVersionCode
>=
0
)
menu
.
findItem
(
R
.
id
.
logFragment
).
isVisible
=
menu
.
findItem
(
R
.
id
.
logFragment
).
isVisible
=
Shell
.
rootAccess
()
Shell
.
rootAccess
()
menu
.
findItem
(
R
.
id
.
superuserFragment
).
isVisible
=
menu
.
findItem
(
R
.
id
.
superuserFragment
).
isVisible
=
...
...
app/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt
View file @
7756e107
...
@@ -7,6 +7,7 @@ import androidx.appcompat.app.AlertDialog
...
@@ -7,6 +7,7 @@ import androidx.appcompat.app.AlertDialog
import
androidx.appcompat.app.AppCompatActivity
import
androidx.appcompat.app.AppCompatActivity
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.extensions.subscribeK
import
com.topjohnwu.magisk.*
import
com.topjohnwu.magisk.*
import
com.topjohnwu.magisk.data.database.SettingsDao
import
com.topjohnwu.magisk.tasks.UpdateRepos
import
com.topjohnwu.magisk.tasks.UpdateRepos
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.magisk.view.Notifications
...
@@ -21,7 +22,7 @@ open class SplashActivity : AppCompatActivity() {
...
@@ -21,7 +22,7 @@ open class SplashActivity : AppCompatActivity() {
super
.
onCreate
(
savedInstanceState
)
super
.
onCreate
(
savedInstanceState
)
Shell
.
getShell
{
Shell
.
getShell
{
if
(
Config
.
magiskVersionCode
>
0
&&
Config
.
magiskVersionCode
<
Const
.
MagiskVersion
.
MIN_SUPPORT
)
{
if
(
Info
.
magiskVersionCode
>
0
&&
Info
.
magiskVersionCode
<
Const
.
MagiskVersion
.
MIN_SUPPORT
)
{
AlertDialog
.
Builder
(
this
)
AlertDialog
.
Builder
(
this
)
.
setTitle
(
R
.
string
.
unsupport_magisk_title
)
.
setTitle
(
R
.
string
.
unsupport_magisk_title
)
.
setMessage
(
R
.
string
.
unsupport_magisk_message
)
.
setMessage
(
R
.
string
.
unsupport_magisk_message
)
...
@@ -35,9 +36,9 @@ open class SplashActivity : AppCompatActivity() {
...
@@ -35,9 +36,9 @@ open class SplashActivity : AppCompatActivity() {
}
}
private
fun
initAndStart
()
{
private
fun
initAndStart
()
{
val
pkg
=
Config
.
get
<
String
>(
Config
.
Key
.
SU_MANAGER
)
val
pkg
=
Config
.
suManager
if
(
pkg
!=
null
&&
packageName
==
BuildConfig
.
APPLICATION_ID
)
{
if
(
Config
.
suManager
.
isNotEmpty
()
&&
packageName
==
BuildConfig
.
APPLICATION_ID
)
{
Config
.
remov
e
(
Config
.
Key
.
SU_MANAGER
)
get
<
SettingsDao
>().
delet
e
(
Config
.
Key
.
SU_MANAGER
)
Shell
.
su
(
"pm uninstall $pkg"
).
submit
()
Shell
.
su
(
"pm uninstall $pkg"
).
submit
()
}
}
if
(
TextUtils
.
equals
(
pkg
,
packageName
))
{
if
(
TextUtils
.
equals
(
pkg
,
packageName
))
{
...
@@ -56,15 +57,12 @@ open class SplashActivity : AppCompatActivity() {
...
@@ -56,15 +57,12 @@ open class SplashActivity : AppCompatActivity() {
// Schedule periodic update checks
// Schedule periodic update checks
Utils
.
scheduleUpdateCheck
()
Utils
.
scheduleUpdateCheck
()
//CheckUpdates.check()
// Setup shortcuts
// Setup shortcuts
Shortcuts
.
setup
(
this
)
Shortcuts
.
setup
(
this
)
// Magisk working as expected
// Magisk working as expected
if
(
Shell
.
rootAccess
()
&&
Config
.
magiskVersionCode
>
0
)
{
if
(
Shell
.
rootAccess
()
&&
Info
.
magiskVersionCode
>
0
)
{
// Load modules
//Utils.loadModules(false)
// Load repos
// Load repos
if
(
Networking
.
checkNetworkStatus
(
this
))
{
if
(
Networking
.
checkNetworkStatus
(
this
))
{
get
<
UpdateRepos
>().
exec
().
subscribeK
()
get
<
UpdateRepos
>().
exec
().
subscribeK
()
...
...
app/src/main/java/com/topjohnwu/magisk/ui/base/BasePreferenceFragment.kt
View file @
7756e107
...
@@ -12,8 +12,6 @@ import androidx.core.view.isVisible
...
@@ -12,8 +12,6 @@ import androidx.core.view.isVisible
import
androidx.preference.*
import
androidx.preference.*
import
androidx.recyclerview.widget.RecyclerView
import
androidx.recyclerview.widget.RecyclerView
import
com.topjohnwu.magisk.App
import
com.topjohnwu.magisk.App
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.KConfig
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
org.koin.android.ext.android.inject
import
org.koin.android.ext.android.inject
...
@@ -63,22 +61,6 @@ abstract class BasePreferenceFragment : PreferenceFragmentCompat(),
...
@@ -63,22 +61,6 @@ abstract class BasePreferenceFragment : PreferenceFragmentCompat(),
view
.
setPadding
(
0
,
view
.
paddingTop
,
view
.
paddingRight
,
view
.
paddingBottom
)
view
.
setPadding
(
0
,
view
.
paddingTop
,
view
.
paddingRight
,
view
.
paddingBottom
)
}
}
protected
fun
setCustomUpdateChannel
(
userRepo
:
String
)
{
KConfig
.
customUpdateChannel
=
userRepo
}
protected
fun
getChannelCompat
(
channel
:
Int
):
KConfig
.
UpdateChannel
{
return
when
(
channel
)
{
Config
.
Value
.
STABLE_CHANNEL
,
Config
.
Value
.
DEFAULT_CHANNEL
->
KConfig
.
UpdateChannel
.
STABLE
Config
.
Value
.
BETA_CHANNEL
->
KConfig
.
UpdateChannel
.
BETA
Config
.
Value
.
CANARY_CHANNEL
->
KConfig
.
UpdateChannel
.
CANARY
Config
.
Value
.
CANARY_DEBUG_CHANNEL
->
KConfig
.
UpdateChannel
.
CANARY_DEBUG
Config
.
Value
.
CUSTOM_CHANNEL
->
KConfig
.
UpdateChannel
.
CUSTOM
else
->
KConfig
.
updateChannel
}
}
protected
fun
<
T
:
Preference
>
findPref
(
key
:
CharSequence
):
T
{
protected
fun
<
T
:
Preference
>
findPref
(
key
:
CharSequence
):
T
{
return
findPreference
(
key
)
as
T
return
findPreference
(
key
)
as
T
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt
View file @
7756e107
...
@@ -51,14 +51,12 @@ abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBin
...
@@ -51,14 +51,12 @@ abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBin
get
()
=
navigationController
?.
let
{
it
.
currentStackIndex
!=
defaultPosition
}
?:
false
get
()
=
navigationController
?.
let
{
it
.
currentStackIndex
!=
defaultPosition
}
?:
false
init
{
init
{
val
isDarkTheme
=
Config
.
get
<
Boolean
>(
Config
.
Key
.
DARK_THEME
)
val
theme
=
if
(
Config
.
darkTheme
)
{
val
theme
=
if
(
isDarkTheme
)
{
AppCompatDelegate
.
MODE_NIGHT_YES
AppCompatDelegate
.
MODE_NIGHT_YES
}
else
{
}
else
{
AppCompatDelegate
.
MODE_NIGHT_NO
AppCompatDelegate
.
MODE_NIGHT_NO
}
}
AppCompatDelegate
.
setDefaultNightMode
(
theme
)
AppCompatDelegate
.
setDefaultNightMode
(
theme
)
AppCompatDelegate
.
setCompatVectorFromResourcesEnabled
(
true
)
}
}
override
fun
applyOverrideConfiguration
(
config
:
Configuration
?)
{
override
fun
applyOverrideConfiguration
(
config
:
Configuration
?)
{
...
...
app/src/main/java/com/topjohnwu/magisk/ui/hide/MagiskHideFragment.kt
View file @
7756e107
...
@@ -28,7 +28,7 @@ class MagiskHideFragment : MagiskFragment<HideViewModel, FragmentMagiskHideBindi
...
@@ -28,7 +28,7 @@ class MagiskHideFragment : MagiskFragment<HideViewModel, FragmentMagiskHideBindi
(
findItem
(
R
.
id
.
app_search
).
actionView
as
?
SearchView
)
(
findItem
(
R
.
id
.
app_search
).
actionView
as
?
SearchView
)
?.
setOnQueryTextListener
(
this
@MagiskHideFragment
)
?.
setOnQueryTextListener
(
this
@MagiskHideFragment
)
val
showSystem
=
Config
.
get
<
Boolean
>(
Config
.
Key
.
SHOW_SYSTEM_APP
)
val
showSystem
=
Config
.
showSystemApp
findItem
(
R
.
id
.
show_system
).
isChecked
=
showSystem
findItem
(
R
.
id
.
show_system
).
isChecked
=
showSystem
viewModel
.
isShowSystem
.
value
=
showSystem
viewModel
.
isShowSystem
.
value
=
showSystem
...
@@ -39,10 +39,8 @@ class MagiskHideFragment : MagiskFragment<HideViewModel, FragmentMagiskHideBindi
...
@@ -39,10 +39,8 @@ class MagiskHideFragment : MagiskFragment<HideViewModel, FragmentMagiskHideBindi
if
(
item
.
itemId
==
R
.
id
.
show_system
)
{
if
(
item
.
itemId
==
R
.
id
.
show_system
)
{
val
showSystem
=
!
item
.
isChecked
val
showSystem
=
!
item
.
isChecked
item
.
isChecked
=
showSystem
item
.
isChecked
=
showSystem
Config
.
s
et
(
Config
.
Key
.
SHOW_SYSTEM_APP
,
showSystem
)
Config
.
s
howSystemApp
=
showSystem
viewModel
.
isShowSystem
.
value
=
showSystem
viewModel
.
isShowSystem
.
value
=
showSystem
//adapter!!.setShowSystem(showSystem)
//adapter!!.filter(search!!.query.toString())
}
}
return
true
return
true
}
}
...
@@ -56,9 +54,4 @@ class MagiskHideFragment : MagiskFragment<HideViewModel, FragmentMagiskHideBindi
...
@@ -56,9 +54,4 @@ class MagiskHideFragment : MagiskFragment<HideViewModel, FragmentMagiskHideBindi
viewModel
.
query
.
value
=
query
.
orEmpty
()
viewModel
.
query
.
value
=
query
.
orEmpty
()
return
false
return
false
}
}
/*override fun onEvent(event: Int) {
//mSwipeRefreshLayout!!.isRefreshing = false
adapter!!.filter(search!!.query.toString())
}*/
}
}
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
View file @
7756e107
...
@@ -56,7 +56,7 @@ class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
...
@@ -56,7 +56,7 @@ class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
private
fun
installMagisk
()
{
private
fun
installMagisk
()
{
// Show Manager update first
// Show Manager update first
if
(
Config
.
remoteManagerVersionCode
>
BuildConfig
.
VERSION_CODE
)
{
if
(
Info
.
remoteManagerVersionCode
>
BuildConfig
.
VERSION_CODE
)
{
installManager
()
installManager
()
return
return
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
View file @
7756e107
...
@@ -4,10 +4,7 @@ import com.skoumal.teanity.extensions.addOnPropertyChangedCallback
...
@@ -4,10 +4,7 @@ import com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.skoumal.teanity.extensions.doOnSubscribeUi
import
com.skoumal.teanity.extensions.doOnSubscribeUi
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.util.KObservableField
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.*
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.model.observer.Observer
import
com.topjohnwu.magisk.model.observer.Observer
...
@@ -25,8 +22,8 @@ class HomeViewModel(
...
@@ -25,8 +22,8 @@ class HomeViewModel(
val
isAdvancedExpanded
=
KObservableField
(
false
)
val
isAdvancedExpanded
=
KObservableField
(
false
)
val
isForceEncryption
=
KObservableField
(
Config
.
keepEnc
)
val
isForceEncryption
=
KObservableField
(
Info
.
keepEnc
)
val
isKeepVerity
=
KObservableField
(
Config
.
keepVerity
)
val
isKeepVerity
=
KObservableField
(
Info
.
keepVerity
)
val
magiskState
=
KObservableField
(
MagiskState
.
LOADING
)
val
magiskState
=
KObservableField
(
MagiskState
.
LOADING
)
val
magiskStateText
=
Observer
(
magiskState
)
{
val
magiskStateText
=
Observer
(
magiskState
)
{
...
@@ -41,7 +38,7 @@ class HomeViewModel(
...
@@ -41,7 +38,7 @@ class HomeViewModel(
val
magiskCurrentVersion
=
KObservableField
(
""
)
val
magiskCurrentVersion
=
KObservableField
(
""
)
val
magiskLatestVersion
=
KObservableField
(
""
)
val
magiskLatestVersion
=
KObservableField
(
""
)
val
magiskAdditionalInfo
=
Observer
(
magiskState
)
{
val
magiskAdditionalInfo
=
Observer
(
magiskState
)
{
if
(
Config
.
get
<
Boolean
>(
Config
.
Key
.
COREONLY
)
)
if
(
Config
.
coreOnly
)
R
.
string
.
core_only_enabled
.
res
()
R
.
string
.
core_only_enabled
.
res
()
else
else
""
""
...
@@ -87,10 +84,10 @@ class HomeViewModel(
...
@@ -87,10 +84,10 @@ class HomeViewModel(
init
{
init
{
isForceEncryption
.
addOnPropertyChangedCallback
{
isForceEncryption
.
addOnPropertyChangedCallback
{
Config
.
keepEnc
=
it
?:
return
@addOnPropertyChangedCallback
Info
.
keepEnc
=
it
?:
return
@addOnPropertyChangedCallback
}
}
isKeepVerity
.
addOnPropertyChangedCallback
{
isKeepVerity
.
addOnPropertyChangedCallback
{
Config
.
keepVerity
=
it
?:
return
@addOnPropertyChangedCallback
Info
.
keepVerity
=
it
?:
return
@addOnPropertyChangedCallback
}
}
refresh
()
refresh
()
...
@@ -154,7 +151,7 @@ class HomeViewModel(
...
@@ -154,7 +151,7 @@ class HomeViewModel(
}
}
fun
refresh
()
{
fun
refresh
()
{
magiskRepo
.
fetch
Config
()
magiskRepo
.
fetch
Update
()
.
applyViewModel
(
this
)
.
applyViewModel
(
this
)
.
doOnSubscribeUi
{
.
doOnSubscribeUi
{
magiskState
.
value
=
MagiskState
.
LOADING
magiskState
.
value
=
MagiskState
.
LOADING
...
@@ -164,14 +161,6 @@ class HomeViewModel(
...
@@ -164,14 +161,6 @@ class HomeViewModel(
safetyNetTitle
.
value
=
R
.
string
.
safetyNet_check_text
safetyNetTitle
.
value
=
R
.
string
.
safetyNet_check_text
}
}
.
subscribeK
{
.
subscribeK
{
it
.
app
.
let
{
Config
.
remoteManagerVersionCode
=
it
.
versionCode
.
toIntOrNull
()
?:
-
1
Config
.
remoteManagerVersionString
=
it
.
version
}
it
.
magisk
.
let
{
Config
.
remoteMagiskVersionCode
=
it
.
versionCode
.
toIntOrNull
()
?:
-
1
Config
.
remoteMagiskVersionString
=
it
.
version
}
updateSelf
()
updateSelf
()
ensureEnv
()
ensureEnv
()
}
}
...
@@ -181,22 +170,22 @@ class HomeViewModel(
...
@@ -181,22 +170,22 @@ class HomeViewModel(
private
fun
updateSelf
()
{
private
fun
updateSelf
()
{
state
=
State
.
LOADED
state
=
State
.
LOADED
magiskState
.
value
=
when
(
Config
.
magiskVersionCode
)
{
magiskState
.
value
=
when
(
Info
.
magiskVersionCode
)
{
in
Int
.
MIN_VALUE
until
0
->
MagiskState
.
NOT_INSTALLED
in
Int
.
MIN_VALUE
until
0
->
MagiskState
.
NOT_INSTALLED
!
in
Config
.
remoteMagiskVersionCode
..
Int
.
MAX_VALUE
->
MagiskState
.
OBSOLETE
!
in
Info
.
remoteMagiskVersionCode
..
Int
.
MAX_VALUE
->
MagiskState
.
OBSOLETE
else
->
MagiskState
.
UP_TO_DATE
else
->
MagiskState
.
UP_TO_DATE
}
}
magiskCurrentVersion
.
value
=
if
(
magiskState
.
value
!=
MagiskState
.
NOT_INSTALLED
)
{
magiskCurrentVersion
.
value
=
if
(
magiskState
.
value
!=
MagiskState
.
NOT_INSTALLED
)
{
version
.
format
(
Config
.
magiskVersionString
,
Config
.
magiskVersionCode
)
version
.
format
(
Info
.
magiskVersionString
,
Info
.
magiskVersionCode
)
}
else
{
}
else
{
""
""
}
}
magiskLatestVersion
.
value
=
version
magiskLatestVersion
.
value
=
version
.
format
(
Config
.
remoteMagiskVersionString
,
Config
.
remoteMagiskVersionCode
)
.
format
(
Info
.
remoteMagiskVersionString
,
Info
.
remoteMagiskVersionCode
)
managerState
.
value
=
when
(
Config
.
remoteManagerVersionCode
)
{
managerState
.
value
=
when
(
Info
.
remoteManagerVersionCode
)
{
in
Int
.
MIN_VALUE
until
0
->
MagiskState
.
NOT_INSTALLED
//wrong update channel
in
Int
.
MIN_VALUE
until
0
->
MagiskState
.
NOT_INSTALLED
//wrong update channel
in
(
BuildConfig
.
VERSION_CODE
+
1
)
..
Int
.
MAX_VALUE
->
MagiskState
.
OBSOLETE
in
(
BuildConfig
.
VERSION_CODE
+
1
)
..
Int
.
MAX_VALUE
->
MagiskState
.
OBSOLETE
else
->
MagiskState
.
UP_TO_DATE
else
->
MagiskState
.
UP_TO_DATE
...
@@ -206,7 +195,7 @@ class HomeViewModel(
...
@@ -206,7 +195,7 @@ class HomeViewModel(
.
format
(
BuildConfig
.
VERSION_NAME
,
BuildConfig
.
VERSION_CODE
)
.
format
(
BuildConfig
.
VERSION_NAME
,
BuildConfig
.
VERSION_CODE
)
managerLatestVersion
.
value
=
version
managerLatestVersion
.
value
=
version
.
format
(
Config
.
remoteManagerVersionString
,
Config
.
remoteManagerVersionCode
)
.
format
(
Info
.
remoteManagerVersionString
,
Info
.
remoteManagerVersionCode
)
}
}
private
fun
ensureEnv
()
{
private
fun
ensureEnv
()
{
...
...
app/src/main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt
View file @
7756e107
...
@@ -53,9 +53,9 @@ class ReposFragment : MagiskFragment<ModuleViewModel, FragmentReposBinding>(),
...
@@ -53,9 +53,9 @@ class ReposFragment : MagiskFragment<ModuleViewModel, FragmentReposBinding>(),
.
setTitle
(
R
.
string
.
sorting_order
)
.
setTitle
(
R
.
string
.
sorting_order
)
.
setSingleChoiceItems
(
.
setSingleChoiceItems
(
R
.
array
.
sorting_orders
,
R
.
array
.
sorting_orders
,
Config
.
get
<
Int
>(
Config
.
Key
.
REPO_ORDER
)
!!
Config
.
repoOrder
)
{
d
,
which
->
)
{
d
,
which
->
Config
.
set
(
Config
.
Key
.
REPO_ORDER
,
which
)
Config
.
repoOrder
=
which
viewModel
.
refresh
(
false
)
viewModel
.
refresh
(
false
)
d
.
dismiss
()
d
.
dismiss
()
}.
show
()
}.
show
()
...
...
app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt
View file @
7756e107
...
@@ -13,10 +13,11 @@ import androidx.preference.Preference
...
@@ -13,10 +13,11 @@ import androidx.preference.Preference
import
androidx.preference.PreferenceCategory
import
androidx.preference.PreferenceCategory
import
androidx.preference.SwitchPreferenceCompat
import
androidx.preference.SwitchPreferenceCompat
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.extensions.subscribeK
import
com.topjohnwu.magisk.*
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.KConfig.UpdateChannel
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.database.RepoDatabaseHelper
import
com.topjohnwu.magisk.data.database.RepoDatabaseHelper
import
com.topjohnwu.magisk.data.repository.SettingRepository
import
com.topjohnwu.magisk.ui.base.BasePreferenceFragment
import
com.topjohnwu.magisk.ui.base.BasePreferenceFragment
import
com.topjohnwu.magisk.utils.*
import
com.topjohnwu.magisk.utils.*
import
com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
import
com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
...
@@ -27,7 +28,6 @@ import org.koin.android.ext.android.inject
...
@@ -27,7 +28,6 @@ import org.koin.android.ext.android.inject
class
SettingsFragment
:
BasePreferenceFragment
()
{
class
SettingsFragment
:
BasePreferenceFragment
()
{
private
val
repoDatabase
:
RepoDatabaseHelper
by
inject
()
private
val
repoDatabase
:
RepoDatabaseHelper
by
inject
()
private
val
settingRepo
:
SettingRepository
by
inject
()
private
lateinit
var
updateChannel
:
ListPreference
private
lateinit
var
updateChannel
:
ListPreference
private
lateinit
var
autoRes
:
ListPreference
private
lateinit
var
autoRes
:
ListPreference
...
@@ -53,7 +53,7 @@ class SettingsFragment : BasePreferenceFragment() {
...
@@ -53,7 +53,7 @@ class SettingsFragment : BasePreferenceFragment() {
requestTimeout
=
findPref
(
Config
.
Key
.
SU_REQUEST_TIMEOUT
)
requestTimeout
=
findPref
(
Config
.
Key
.
SU_REQUEST_TIMEOUT
)
suNotification
=
findPref
(
Config
.
Key
.
SU_NOTIFICATION
)
suNotification
=
findPref
(
Config
.
Key
.
SU_NOTIFICATION
)
multiuserConfig
=
findPref
(
Config
.
Key
.
SU_MULTIUSER_MODE
)
multiuserConfig
=
findPref
(
Config
.
Key
.
SU_MULTIUSER_MODE
)
nsConfig
=
findPref
(
Config
.
Key
.
SU_MNT_NS
)
as
ListPreference
nsConfig
=
findPref
(
Config
.
Key
.
SU_MNT_NS
)
val
reauth
=
findPreference
(
Config
.
Key
.
SU_REAUTH
)
as
SwitchPreferenceCompat
val
reauth
=
findPreference
(
Config
.
Key
.
SU_REAUTH
)
as
SwitchPreferenceCompat
val
fingerprint
=
findPreference
(
Config
.
Key
.
SU_FINGERPRINT
)
as
SwitchPreferenceCompat
val
fingerprint
=
findPreference
(
Config
.
Key
.
SU_FINGERPRINT
)
as
SwitchPreferenceCompat
val
generalCatagory
=
findPreference
(
"general"
)
as
PreferenceCategory
val
generalCatagory
=
findPreference
(
"general"
)
as
PreferenceCategory
...
@@ -70,7 +70,9 @@ class SettingsFragment : BasePreferenceFragment() {
...
@@ -70,7 +70,9 @@ class SettingsFragment : BasePreferenceFragment() {
true
true
}
}
findPreference
(
"clear"
).
setOnPreferenceClickListener
{
findPreference
(
"clear"
).
setOnPreferenceClickListener
{
prefs
.
edit
().
remove
(
Config
.
Key
.
ETAG_KEY
).
apply
()
prefs
.
edit
{
remove
(
Config
.
Key
.
ETAG_KEY
)
}
repoDatabase
.
clearRepo
()
repoDatabase
.
clearRepo
()
Utils
.
toast
(
R
.
string
.
repo_cache_cleared
,
Toast
.
LENGTH_SHORT
)
Utils
.
toast
(
R
.
string
.
repo_cache_cleared
,
Toast
.
LENGTH_SHORT
)
true
true
...
@@ -81,30 +83,23 @@ class SettingsFragment : BasePreferenceFragment() {
...
@@ -81,30 +83,23 @@ class SettingsFragment : BasePreferenceFragment() {
true
true
}
}
prefs
.
edit
{
putBoolean
(
Config
.
Key
.
SU_FINGERPRINT
,
FingerprintHelper
.
useFingerprint
())
}
updateChannel
.
setOnPreferenceChangeListener
{
_
,
value
->
updateChannel
.
setOnPreferenceChangeListener
{
_
,
value
->
val
channel
=
Integer
.
parseInt
(
value
as
String
)
val
channel
=
Integer
.
parseInt
(
value
as
String
)
val
previous
=
Config
.
updateChannel
val
previousUpdateChannel
=
KConfig
.
updateChannel
if
(
channel
==
Config
.
Value
.
CUSTOM_CHANNEL
)
{
val
updateChannel
=
getChannelCompat
(
channel
)
val
v
=
LayoutInflater
.
from
(
requireActivity
())
.
inflate
(
R
.
layout
.
custom_channel_dialog
,
null
)
KConfig
.
updateChannel
=
updateChannel
if
(
updateChannel
===
UpdateChannel
.
CUSTOM
)
{
val
v
=
LayoutInflater
.
from
(
requireActivity
()).
inflate
(
R
.
layout
.
custom_channel_dialog
,
null
)
val
url
=
v
.
findViewById
<
EditText
>(
R
.
id
.
custom_url
)
val
url
=
v
.
findViewById
<
EditText
>(
R
.
id
.
custom_url
)
url
.
setText
(
KConfig
.
customUpdateChanne
l
)
url
.
setText
(
Config
.
customChannelUr
l
)
AlertDialog
.
Builder
(
requireActivity
())
AlertDialog
.
Builder
(
requireActivity
())
.
setTitle
(
R
.
string
.
settings_update_custom
)
.
setTitle
(
R
.
string
.
settings_update_custom
)
.
setView
(
v
)
.
setView
(
v
)
.
setPositiveButton
(
R
.
string
.
ok
)
{
_
,
_
->
.
setPositiveButton
(
R
.
string
.
ok
)
{
_
,
_
->
setCustomUpdateChannel
(
url
.
text
.
toString
()
)
}
Config
.
customChannelUrl
=
url
.
text
.
toString
(
)
}
.
setNegativeButton
(
R
.
string
.
close
)
{
_
,
_
->
.
setNegativeButton
(
R
.
string
.
close
)
{
_
,
_
->
KConfig
.
updateChannel
=
previousUpdateChannel
}
Config
.
updateChannel
=
previous
}
.
setOnCancelListener
{
KConfig
.
updateChannel
=
previousUpdateChannel
}
.
setOnCancelListener
{
Config
.
updateChannel
=
previous
}
.
show
()
.
show
()
}
}
true
true
...
@@ -114,7 +109,7 @@ class SettingsFragment : BasePreferenceFragment() {
...
@@ -114,7 +109,7 @@ class SettingsFragment : BasePreferenceFragment() {
/* We only show canary channels if user is already on canary channel
/* We only show canary channels if user is already on canary channel
* or the user have already chosen canary channel */
* or the user have already chosen canary channel */
if
(!
Utils
.
isCanary
()
&&
Config
.
get
<
Int
>(
Config
.
Key
.
UPDATE_CHANNEL
)
<
Config
.
Value
.
CANARY_CHANNEL
)
{
if
(!
Utils
.
isCanary
&&
Config
.
updateChannel
<
Config
.
Value
.
CANARY_CHANNEL
)
{
// Remove the last 2 entries
// Remove the last 2 entries
val
entries
=
updateChannel
.
entries
val
entries
=
updateChannel
.
entries
updateChannel
.
entries
=
entries
.
copyOf
(
entries
.
size
-
2
)
updateChannel
.
entries
=
entries
.
copyOf
(
entries
.
size
-
2
)
...
@@ -168,8 +163,9 @@ class SettingsFragment : BasePreferenceFragment() {
...
@@ -168,8 +163,9 @@ class SettingsFragment : BasePreferenceFragment() {
override
fun
onSharedPreferenceChanged
(
prefs
:
SharedPreferences
,
key
:
String
)
{
override
fun
onSharedPreferenceChanged
(
prefs
:
SharedPreferences
,
key
:
String
)
{
when
(
key
)
{
when
(
key
)
{
Config
.
Key
.
ROOT_ACCESS
,
Config
.
Key
.
SU_MULTIUSER_MODE
,
Config
.
Key
.
SU_MNT_NS
->
Config
.
Key
.
ROOT_ACCESS
->
Config
.
rootMode
=
Utils
.
getPrefsInt
(
prefs
,
key
)
settingRepo
.
put
(
key
,
Utils
.
getPrefsInt
(
prefs
,
key
)).
subscribe
()
Config
.
Key
.
SU_MULTIUSER_MODE
->
Config
.
suMultiuserMode
=
Utils
.
getPrefsInt
(
prefs
,
key
)
Config
.
Key
.
SU_MNT_NS
->
Config
.
suMntNamespaceMode
=
Utils
.
getPrefsInt
(
prefs
,
key
)
Config
.
Key
.
DARK_THEME
->
requireActivity
().
recreate
()
Config
.
Key
.
DARK_THEME
->
requireActivity
().
recreate
()
Config
.
Key
.
COREONLY
->
{
Config
.
Key
.
COREONLY
->
{
if
(
prefs
.
getBoolean
(
key
,
false
))
{
if
(
prefs
.
getBoolean
(
key
,
false
))
{
...
@@ -196,14 +192,13 @@ class SettingsFragment : BasePreferenceFragment() {
...
@@ -196,14 +192,13 @@ class SettingsFragment : BasePreferenceFragment() {
}
}
override
fun
onPreferenceTreeClick
(
preference
:
Preference
):
Boolean
{
override
fun
onPreferenceTreeClick
(
preference
:
Preference
):
Boolean
{
val
key
=
preference
.
key
when
(
preference
.
key
)
{
when
(
key
)
{
Config
.
Key
.
SU_FINGERPRINT
->
{
Config
.
Key
.
SU_FINGERPRINT
->
{
val
checked
=
(
preference
as
SwitchPreferenceCompat
).
isChecked
val
checked
=
(
preference
as
SwitchPreferenceCompat
).
isChecked
preference
.
isChecked
=
!
checked
preference
.
isChecked
=
!
checked
FingerprintAuthDialog
(
requireActivity
())
{
FingerprintAuthDialog
(
requireActivity
())
{
preference
.
isChecked
=
checked
preference
.
isChecked
=
checked
Config
.
s
et
(
key
,
checked
)
Config
.
s
uFingerprint
=
checked
}.
show
()
}.
show
()
}
}
}
}
...
@@ -237,34 +232,34 @@ class SettingsFragment : BasePreferenceFragment() {
...
@@ -237,34 +232,34 @@ class SettingsFragment : BasePreferenceFragment() {
private
fun
setSummary
(
key
:
String
)
{
private
fun
setSummary
(
key
:
String
)
{
when
(
key
)
{
when
(
key
)
{
Config
.
Key
.
ROOT_ACCESS
->
rootConfig
.
summary
=
resources
.
getStringArray
(
R
.
array
.
su_access
)[
Config
.
rootMode
]
Config
.
Key
.
SU_MULTIUSER_MODE
->
multiuserConfig
.
summary
=
resources
.
getStringArray
(
R
.
array
.
multiuser_summary
)[
Config
.
suMultiuserMode
]
Config
.
Key
.
SU_MNT_NS
->
nsConfig
.
summary
=
resources
.
getStringArray
(
R
.
array
.
namespace_summary
)[
Config
.
suMntNamespaceMode
]
Config
.
Key
.
UPDATE_CHANNEL
->
{
Config
.
Key
.
UPDATE_CHANNEL
->
{
var
ch
=
Config
.
get
<
Int
>(
key
)
var
ch
=
Config
.
updateChannel
ch
=
if
(
ch
<
0
)
Config
.
Value
.
STABLE_CHANNEL
else
ch
ch
=
if
(
ch
<
0
)
Config
.
Value
.
STABLE_CHANNEL
else
ch
updateChannel
.
summary
=
resources
updateChannel
.
summary
=
resources
.
getStringArray
(
R
.
array
.
update_channel
)[
ch
]
.
getStringArray
(
R
.
array
.
update_channel
)[
ch
]
}
}
Config
.
Key
.
ROOT_ACCESS
->
rootConfig
.
summary
=
resources
.
getStringArray
(
R
.
array
.
su_access
)[
Config
.
get
<
Int
>(
key
)]
Config
.
Key
.
SU_AUTO_RESPONSE
->
autoRes
.
summary
=
resources
Config
.
Key
.
SU_AUTO_RESPONSE
->
autoRes
.
summary
=
resources
.
getStringArray
(
R
.
array
.
auto_response
)[
Config
.
get
<
Int
>(
key
)
]
.
getStringArray
(
R
.
array
.
auto_response
)[
Config
.
suAutoReponse
]
Config
.
Key
.
SU_NOTIFICATION
->
suNotification
.
summary
=
resources
Config
.
Key
.
SU_NOTIFICATION
->
suNotification
.
summary
=
resources
.
getStringArray
(
R
.
array
.
su_notification
)[
Config
.
get
<
Int
>(
key
)
]
.
getStringArray
(
R
.
array
.
su_notification
)[
Config
.
suNotification
]
Config
.
Key
.
SU_REQUEST_TIMEOUT
->
requestTimeout
.
summary
=
Config
.
Key
.
SU_REQUEST_TIMEOUT
->
requestTimeout
.
summary
=
getString
(
R
.
string
.
request_timeout_summary
,
Config
.
get
<
Int
>(
key
))
getString
(
R
.
string
.
request_timeout_summary
,
Config
.
suDefaultTimeout
)
Config
.
Key
.
SU_MULTIUSER_MODE
->
multiuserConfig
.
summary
=
resources
.
getStringArray
(
R
.
array
.
multiuser_summary
)[
Config
.
get
<
Int
>(
key
)]
Config
.
Key
.
SU_MNT_NS
->
nsConfig
.
summary
=
resources
.
getStringArray
(
R
.
array
.
namespace_summary
)[
Config
.
get
<
Int
>(
key
)]
}
}
}
}
private
fun
setSummary
()
{
private
fun
setSummary
()
{
setSummary
(
Config
.
Key
.
UPDATE_CHANNEL
)
setSummary
(
Config
.
Key
.
ROOT_ACCESS
)
setSummary
(
Config
.
Key
.
ROOT_ACCESS
)
setSummary
(
Config
.
Key
.
SU_MULTIUSER_MODE
)
setSummary
(
Config
.
Key
.
SU_MNT_NS
)
setSummary
(
Config
.
Key
.
UPDATE_CHANNEL
)
setSummary
(
Config
.
Key
.
SU_AUTO_RESPONSE
)
setSummary
(
Config
.
Key
.
SU_AUTO_RESPONSE
)
setSummary
(
Config
.
Key
.
SU_NOTIFICATION
)
setSummary
(
Config
.
Key
.
SU_NOTIFICATION
)
setSummary
(
Config
.
Key
.
SU_REQUEST_TIMEOUT
)
setSummary
(
Config
.
Key
.
SU_REQUEST_TIMEOUT
)
setSummary
(
Config
.
Key
.
SU_MULTIUSER_MODE
)
setSummary
(
Config
.
Key
.
SU_MNT_NS
)
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestViewModel.kt
View file @
7756e107
...
@@ -173,7 +173,7 @@ class SuRequestViewModel(
...
@@ -173,7 +173,7 @@ class SuRequestViewModel(
return
true
return
true
}
}
when
(
Config
.
get
<
Int
>(
Config
.
Key
.
SU_AUTO_RESPONSE
)
)
{
when
(
Config
.
suAutoReponse
)
{
Config
.
Value
.
SU_AUTO_DENY
->
{
Config
.
Value
.
SU_AUTO_DENY
->
{
handler
?.
handleAction
(
Policy
.
DENY
,
0
)
handler
?.
handleAction
(
Policy
.
DENY
,
0
)
return
true
return
true
...
@@ -190,8 +190,7 @@ class SuRequestViewModel(
...
@@ -190,8 +190,7 @@ class SuRequestViewModel(
@SuppressLint
(
"ClickableViewAccessibility"
)
@SuppressLint
(
"ClickableViewAccessibility"
)
private
fun
showUI
()
{
private
fun
showUI
()
{
val
seconds
=
Config
.
get
<
Int
>(
Config
.
Key
.
SU_REQUEST_TIMEOUT
).
toLong
()
val
millis
=
SECONDS
.
toMillis
(
Config
.
suDefaultTimeout
.
toLong
())
val
millis
=
SECONDS
.
toMillis
(
seconds
)
timer
=
object
:
CountDownTimer
(
millis
,
1000
)
{
timer
=
object
:
CountDownTimer
(
millis
,
1000
)
{
override
fun
onTick
(
remains
:
Long
)
{
override
fun
onTick
(
remains
:
Long
)
{
denyText
.
value
=
"%s (%d)"
denyText
.
value
=
"%s (%d)"
...
...
app/src/main/java/com/topjohnwu/magisk/utils/DownloadApp.java
View file @
7756e107
...
@@ -6,6 +6,7 @@ import com.topjohnwu.magisk.App;
...
@@ -6,6 +6,7 @@ import com.topjohnwu.magisk.App;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Info
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.ui.SplashActivity
;
import
com.topjohnwu.magisk.ui.SplashActivity
;
import
com.topjohnwu.magisk.view.ProgressNotification
;
import
com.topjohnwu.magisk.view.ProgressNotification
;
...
@@ -24,8 +25,8 @@ public class DownloadApp {
...
@@ -24,8 +25,8 @@ public class DownloadApp {
}
}
public
static
void
restore
()
{
public
static
void
restore
()
{
String
name
=
Utils
.
fmt
(
"MagiskManager v%s(%d)"
,
String
name
=
Utils
.
INSTANCE
.
fmt
(
"MagiskManager v%s(%d)"
,
Config
.
remoteManagerVersionString
,
Config
.
remoteManagerVersionCode
);
Info
.
remoteManagerVersionString
,
Info
.
remoteManagerVersionCode
);
dlInstall
(
name
,
new
RestoreManager
());
dlInstall
(
name
,
new
RestoreManager
());
}
}
...
@@ -33,7 +34,7 @@ public class DownloadApp {
...
@@ -33,7 +34,7 @@ public class DownloadApp {
File
apk
=
new
File
(
App
.
self
.
getCacheDir
(),
"manager.apk"
);
File
apk
=
new
File
(
App
.
self
.
getCacheDir
(),
"manager.apk"
);
ProgressNotification
progress
=
new
ProgressNotification
(
name
);
ProgressNotification
progress
=
new
ProgressNotification
(
name
);
listener
.
progress
=
progress
;
listener
.
progress
=
progress
;
Networking
.
get
(
Config
.
managerLink
)
Networking
.
get
(
Info
.
managerLink
)
.
setExecutor
(
App
.
THREAD_POOL
)
.
setExecutor
(
App
.
THREAD_POOL
)
.
setDownloadProgressListener
(
progress
)
.
setDownloadProgressListener
(
progress
)
.
setErrorHandler
((
conn
,
e
)
->
progress
.
dlFail
())
.
setErrorHandler
((
conn
,
e
)
->
progress
.
dlFail
())
...
...
app/src/main/java/com/topjohnwu/magisk/utils/FingerprintHelper.java
deleted
100644 → 0
View file @
3e58d502
package
com
.
topjohnwu
.
magisk
.
utils
;
import
android.annotation.TargetApi
;
import
android.app.KeyguardManager
;
import
android.hardware.fingerprint.FingerprintManager
;
import
android.os.Build
;
import
android.os.CancellationSignal
;
import
android.security.keystore.KeyGenParameterSpec
;
import
android.security.keystore.KeyPermanentlyInvalidatedException
;
import
android.security.keystore.KeyProperties
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Const
;
import
java.security.KeyStore
;
import
javax.crypto.Cipher
;
import
javax.crypto.KeyGenerator
;
import
javax.crypto.SecretKey
;
@TargetApi
(
Build
.
VERSION_CODES
.
M
)
public
abstract
class
FingerprintHelper
{
private
FingerprintManager
manager
;
private
Cipher
cipher
;
private
CancellationSignal
cancel
;
private
static
final
String
SU_KEYSTORE_KEY
=
"su_key"
;
public
static
boolean
useFingerprint
()
{
boolean
fp
=
Config
.
get
(
Config
.
Key
.
SU_FINGERPRINT
);
if
(
fp
&&
!
canUseFingerprint
())
{
Config
.
set
(
Config
.
Key
.
SU_FINGERPRINT
,
false
);
fp
=
false
;
}
return
fp
;
}
public
static
boolean
canUseFingerprint
()
{
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
M
)
return
false
;
KeyguardManager
km
=
App
.
self
.
getSystemService
(
KeyguardManager
.
class
);
FingerprintManager
fm
=
App
.
self
.
getSystemService
(
FingerprintManager
.
class
);
return
km
.
isKeyguardSecure
()
&&
fm
!=
null
&&
fm
.
isHardwareDetected
()
&&
fm
.
hasEnrolledFingerprints
();
}
protected
FingerprintHelper
()
throws
Exception
{
KeyStore
keyStore
=
KeyStore
.
getInstance
(
"AndroidKeyStore"
);
manager
=
App
.
self
.
getSystemService
(
FingerprintManager
.
class
);
cipher
=
Cipher
.
getInstance
(
KeyProperties
.
KEY_ALGORITHM_AES
+
"/"
+
KeyProperties
.
BLOCK_MODE_CBC
+
"/"
+
KeyProperties
.
ENCRYPTION_PADDING_PKCS7
);
keyStore
.
load
(
null
);
SecretKey
key
=
(
SecretKey
)
keyStore
.
getKey
(
SU_KEYSTORE_KEY
,
null
);
if
(
key
==
null
)
{
key
=
generateKey
();
}
try
{
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
);
}
catch
(
KeyPermanentlyInvalidatedException
e
)
{
// Only happens on Marshmallow
key
=
generateKey
();
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
);
}
}
public
abstract
void
onAuthenticationError
(
int
errorCode
,
CharSequence
errString
);
public
abstract
void
onAuthenticationHelp
(
int
helpCode
,
CharSequence
helpString
);
public
abstract
void
onAuthenticationSucceeded
(
FingerprintManager
.
AuthenticationResult
result
);
public
abstract
void
onAuthenticationFailed
();
public
void
authenticate
()
{
cancel
=
new
CancellationSignal
();
FingerprintManager
.
CryptoObject
cryptoObject
=
new
FingerprintManager
.
CryptoObject
(
cipher
);
manager
.
authenticate
(
cryptoObject
,
cancel
,
0
,
new
Callback
(),
null
);
}
public
void
cancel
()
{
if
(
cancel
!=
null
)
cancel
.
cancel
();
}
private
SecretKey
generateKey
()
throws
Exception
{
KeyGenerator
keygen
=
KeyGenerator
.
getInstance
(
KeyProperties
.
KEY_ALGORITHM_AES
,
"AndroidKeyStore"
);
KeyGenParameterSpec
.
Builder
builder
=
new
KeyGenParameterSpec
.
Builder
(
SU_KEYSTORE_KEY
,
KeyProperties
.
PURPOSE_ENCRYPT
|
KeyProperties
.
PURPOSE_DECRYPT
)
.
setBlockModes
(
KeyProperties
.
BLOCK_MODE_CBC
)
.
setUserAuthenticationRequired
(
true
)
.
setEncryptionPaddings
(
KeyProperties
.
ENCRYPTION_PADDING_PKCS7
);
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
N
)
{
builder
.
setInvalidatedByBiometricEnrollment
(
false
);
}
keygen
.
init
(
builder
.
build
());
return
keygen
.
generateKey
();
}
private
class
Callback
extends
FingerprintManager
.
AuthenticationCallback
{
@Override
public
void
onAuthenticationError
(
int
errorCode
,
CharSequence
errString
)
{
FingerprintHelper
.
this
.
onAuthenticationError
(
errorCode
,
errString
);
}
@Override
public
void
onAuthenticationHelp
(
int
helpCode
,
CharSequence
helpString
)
{
FingerprintHelper
.
this
.
onAuthenticationHelp
(
helpCode
,
helpString
);
}
@Override
public
void
onAuthenticationSucceeded
(
FingerprintManager
.
AuthenticationResult
result
)
{
FingerprintHelper
.
this
.
onAuthenticationSucceeded
(
result
);
}
@Override
public
void
onAuthenticationFailed
()
{
FingerprintHelper
.
this
.
onAuthenticationFailed
();
}
}
}
app/src/main/java/com/topjohnwu/magisk/utils/FingerprintHelper.kt
0 → 100644
View file @
7756e107
package
com.topjohnwu.magisk.utils
import
android.annotation.TargetApi
import
android.app.KeyguardManager
import
android.content.Context
import
android.hardware.fingerprint.FingerprintManager
import
android.os.Build
import
android.os.CancellationSignal
import
android.security.keystore.KeyGenParameterSpec
import
android.security.keystore.KeyProperties
import
com.topjohnwu.magisk.Config
import
java.security.KeyStore
import
javax.crypto.Cipher
import
javax.crypto.KeyGenerator
import
javax.crypto.SecretKey
@TargetApi
(
Build
.
VERSION_CODES
.
M
)
abstract
class
FingerprintHelper
@Throws
(
Exception
::
class
)
protected
constructor
()
{
private
val
manager
:
FingerprintManager
?
private
val
cipher
:
Cipher
private
var
cancel
:
CancellationSignal
?
=
null
private
val
context
:
Context
by
inject
()
init
{
val
keyStore
=
KeyStore
.
getInstance
(
"AndroidKeyStore"
)
manager
=
context
.
getSystemService
(
FingerprintManager
::
class
.
java
)
cipher
=
Cipher
.
getInstance
(
KeyProperties
.
KEY_ALGORITHM_AES
+
"/"
+
KeyProperties
.
BLOCK_MODE_CBC
+
"/"
+
KeyProperties
.
ENCRYPTION_PADDING_PKCS7
)
keyStore
.
load
(
null
)
var
key
=
keyStore
.
getKey
(
SU_KEYSTORE_KEY
,
null
)
as
SecretKey
?
?:
generateKey
()
runCatching
{
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
)
}.
onFailure
{
// Only happens on Marshmallow
key
=
generateKey
()
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
)
}
}
abstract
fun
onAuthenticationError
(
errorCode
:
Int
,
errString
:
CharSequence
)
abstract
fun
onAuthenticationHelp
(
helpCode
:
Int
,
helpString
:
CharSequence
)
abstract
fun
onAuthenticationSucceeded
(
result
:
FingerprintManager
.
AuthenticationResult
)
abstract
fun
onAuthenticationFailed
()
fun
authenticate
()
{
cancel
=
CancellationSignal
()
val
cryptoObject
=
FingerprintManager
.
CryptoObject
(
cipher
)
manager
!!
.
authenticate
(
cryptoObject
,
cancel
,
0
,
Callback
(),
null
)
}
fun
cancel
()
{
if
(
cancel
!=
null
)
cancel
!!
.
cancel
()
}
@Throws
(
Exception
::
class
)
private
fun
generateKey
():
SecretKey
{
val
keygen
=
KeyGenerator
.
getInstance
(
KeyProperties
.
KEY_ALGORITHM_AES
,
"AndroidKeyStore"
)
val
builder
=
KeyGenParameterSpec
.
Builder
(
SU_KEYSTORE_KEY
,
KeyProperties
.
PURPOSE_ENCRYPT
or
KeyProperties
.
PURPOSE_DECRYPT
)
.
setBlockModes
(
KeyProperties
.
BLOCK_MODE_CBC
)
.
setUserAuthenticationRequired
(
true
)
.
setEncryptionPaddings
(
KeyProperties
.
ENCRYPTION_PADDING_PKCS7
)
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
N
)
{
builder
.
setInvalidatedByBiometricEnrollment
(
false
)
}
keygen
.
init
(
builder
.
build
())
return
keygen
.
generateKey
()
}
private
inner
class
Callback
:
FingerprintManager
.
AuthenticationCallback
()
{
override
fun
onAuthenticationError
(
errorCode
:
Int
,
errString
:
CharSequence
)
{
this
@FingerprintHelper
.
onAuthenticationError
(
errorCode
,
errString
)
}
override
fun
onAuthenticationHelp
(
helpCode
:
Int
,
helpString
:
CharSequence
)
{
this
@FingerprintHelper
.
onAuthenticationHelp
(
helpCode
,
helpString
)
}
override
fun
onAuthenticationSucceeded
(
result
:
FingerprintManager
.
AuthenticationResult
)
{
this
@FingerprintHelper
.
onAuthenticationSucceeded
(
result
)
}
override
fun
onAuthenticationFailed
()
{
this
@FingerprintHelper
.
onAuthenticationFailed
()
}
}
companion
object
{
private
const
val
SU_KEYSTORE_KEY
=
"su_key"
fun
useFingerprint
():
Boolean
{
var
fp
=
Config
.
suFingerprint
if
(
fp
&&
!
canUseFingerprint
())
{
Config
.
suFingerprint
=
false
fp
=
false
}
return
fp
}
fun
canUseFingerprint
(
context
:
Context
=
get
()):
Boolean
{
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
M
)
return
false
val
km
=
context
.
getSystemService
(
KeyguardManager
::
class
.
java
)
val
fm
=
context
.
getSystemService
(
FingerprintManager
::
class
.
java
)
return
km
?.
isKeyguardSecure
?:
false
&&
fm
!=
null
&&
fm
.
isHardwareDetected
&&
fm
.
hasEnrolledFingerprints
()
}
}
}
app/src/main/java/com/topjohnwu/magisk/utils/LocaleManager.kt
View file @
7756e107
...
@@ -107,9 +107,9 @@ object LocaleManager {
...
@@ -107,9 +107,9 @@ object LocaleManager {
@JvmStatic
@JvmStatic
fun
setLocale
(
wrapper
:
ContextWrapper
)
{
fun
setLocale
(
wrapper
:
ContextWrapper
)
{
val
localeConfig
=
Config
.
get
<
String
>(
Config
.
Key
.
LOCALE
)
val
localeConfig
=
Config
.
locale
locale
=
when
{
locale
=
when
{
localeConfig
.
is
NullOr
Empty
()
->
defaultLocale
localeConfig
.
isEmpty
()
->
defaultLocale
else
->
forLanguageTag
(
localeConfig
)
else
->
forLanguageTag
(
localeConfig
)
}
}
Locale
.
setDefault
(
locale
)
Locale
.
setDefault
(
locale
)
...
...
app/src/main/java/com/topjohnwu/magisk/utils/Logger.java
View file @
7756e107
...
@@ -13,7 +13,7 @@ public class Logger {
...
@@ -13,7 +13,7 @@ public class Logger {
}
}
public
static
void
debug
(
String
fmt
,
Object
...
args
)
{
public
static
void
debug
(
String
fmt
,
Object
...
args
)
{
debug
(
Utils
.
fmt
(
fmt
,
args
));
debug
(
Utils
.
INSTANCE
.
fmt
(
fmt
,
args
));
}
}
public
static
void
error
(
String
line
)
{
public
static
void
error
(
String
line
)
{
...
@@ -21,6 +21,6 @@ public class Logger {
...
@@ -21,6 +21,6 @@ public class Logger {
}
}
public
static
void
error
(
String
fmt
,
Object
...
args
)
{
public
static
void
error
(
String
fmt
,
Object
...
args
)
{
error
(
Utils
.
fmt
(
fmt
,
args
));
error
(
Utils
.
INSTANCE
.
fmt
(
fmt
,
args
));
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/utils/PatchAPK.java
View file @
7756e107
...
@@ -3,6 +3,8 @@ package com.topjohnwu.magisk.utils;
...
@@ -3,6 +3,8 @@ package com.topjohnwu.magisk.utils;
import
android.content.ComponentName
;
import
android.content.ComponentName
;
import
android.widget.Toast
;
import
android.widget.Toast
;
import
androidx.core.app.NotificationCompat
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.ClassMap
;
...
@@ -27,8 +29,6 @@ import java.util.ArrayList;
...
@@ -27,8 +29,6 @@ import java.util.ArrayList;
import
java.util.List
;
import
java.util.List
;
import
java.util.jar.JarEntry
;
import
java.util.jar.JarEntry
;
import
androidx.core.app.NotificationCompat
;
public
class
PatchAPK
{
public
class
PatchAPK
{
public
static
final
String
LOWERALPHA
=
"abcdefghijklmnopqrstuvwxyz"
;
public
static
final
String
LOWERALPHA
=
"abcdefghijklmnopqrstuvwxyz"
;
...
@@ -110,7 +110,7 @@ public class PatchAPK {
...
@@ -110,7 +110,7 @@ public class PatchAPK {
if
(!
Shell
.
su
(
"pm install "
+
repack
).
exec
().
isSuccess
())
if
(!
Shell
.
su
(
"pm install "
+
repack
).
exec
().
isSuccess
())
return
false
;
return
false
;
Config
.
set
(
Config
.
Key
.
SU_MANAGER
,
pkg
);
Config
.
set
SuManager
(
pkg
);
Config
.
export
();
Config
.
export
();
RootUtils
.
rmAndLaunch
(
BuildConfig
.
APPLICATION_ID
,
RootUtils
.
rmAndLaunch
(
BuildConfig
.
APPLICATION_ID
,
new
ComponentName
(
pkg
,
ClassMap
.
get
(
SplashActivity
.
class
).
getName
()));
new
ComponentName
(
pkg
,
ClassMap
.
get
(
SplashActivity
.
class
).
getName
()));
...
@@ -145,7 +145,7 @@ public class PatchAPK {
...
@@ -145,7 +145,7 @@ public class PatchAPK {
Notifications
.
progress
(
app
.
getString
(
R
.
string
.
hide_manager_title
));
Notifications
.
progress
(
app
.
getString
(
R
.
string
.
hide_manager_title
));
Notifications
.
mgr
.
notify
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
,
progress
.
build
());
Notifications
.
mgr
.
notify
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
,
progress
.
build
());
if
(!
patchAndHide
())
if
(!
patchAndHide
())
Utils
.
toast
(
R
.
string
.
hide_manager_fail_toast
,
Toast
.
LENGTH_LONG
);
Utils
.
INSTANCE
.
toast
(
R
.
string
.
hide_manager_fail_toast
,
Toast
.
LENGTH_LONG
);
Notifications
.
mgr
.
cancel
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
);
Notifications
.
mgr
.
cancel
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
);
});
});
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/utils/RootUtils.kt
View file @
7756e107
...
@@ -4,8 +4,8 @@ import android.content.ComponentName
...
@@ -4,8 +4,8 @@ import android.content.ComponentName
import
android.content.Context
import
android.content.Context
import
android.content.Intent
import
android.content.Intent
import
android.net.Uri
import
android.net.Uri
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.Info
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.ShellUtils
import
com.topjohnwu.superuser.ShellUtils
...
@@ -132,7 +132,7 @@ class RootUtils : Shell.Initializer() {
...
@@ -132,7 +132,7 @@ class RootUtils : Shell.Initializer() {
job
.
add
(
context
.
rawResource
(
R
.
raw
.
util_functions
))
job
.
add
(
context
.
rawResource
(
R
.
raw
.
util_functions
))
.
add
(
context
.
rawResource
(
R
.
raw
.
utils
))
.
add
(
context
.
rawResource
(
R
.
raw
.
utils
))
Const
.
MAGISK_DISABLE_FILE
=
SuFile
(
"/cache/.disable_magisk"
)
Const
.
MAGISK_DISABLE_FILE
=
SuFile
(
"/cache/.disable_magisk"
)
Config
.
loadMagiskInfo
()
Info
.
loadMagiskInfo
()
}
else
{
}
else
{
job
.
add
(
context
.
rawResource
(
R
.
raw
.
nonroot_utils
))
job
.
add
(
context
.
rawResource
(
R
.
raw
.
nonroot_utils
))
}
}
...
@@ -143,9 +143,9 @@ class RootUtils : Shell.Initializer() {
...
@@ -143,9 +143,9 @@ class RootUtils : Shell.Initializer() {
"export BOOTMODE=true"
)
"export BOOTMODE=true"
)
.
exec
()
.
exec
()
Config
.
keepVerity
=
ShellUtils
.
fastCmd
(
"echo \$KEEPVERITY"
).
toBoolean
()
Info
.
keepVerity
=
ShellUtils
.
fastCmd
(
"echo \$KEEPVERITY"
).
toBoolean
()
Config
.
keepEnc
=
ShellUtils
.
fastCmd
(
"echo \$KEEPFORCEENCRYPT"
).
toBoolean
()
Info
.
keepEnc
=
ShellUtils
.
fastCmd
(
"echo \$KEEPFORCEENCRYPT"
).
toBoolean
()
Config
.
recovery
=
ShellUtils
.
fastCmd
(
"echo \$RECOVERYMODE"
).
toBoolean
()
Info
.
recovery
=
ShellUtils
.
fastCmd
(
"echo \$RECOVERYMODE"
).
toBoolean
()
return
true
return
true
}
}
...
@@ -158,7 +158,7 @@ class RootUtils : Shell.Initializer() {
...
@@ -158,7 +158,7 @@ class RootUtils : Shell.Initializer() {
@JvmStatic
@JvmStatic
fun
reboot
()
{
fun
reboot
()
{
Shell
.
su
(
"/system/bin/reboot ${if (
Config
.recovery) "
recovery
" else ""}"
).
submit
()
Shell
.
su
(
"/system/bin/reboot ${if (
Info
.recovery) "
recovery
" else ""}"
).
submit
()
}
}
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/utils/SuLogger.kt
View file @
7756e107
package
com.topjohnwu.magisk.utils
package
com.topjohnwu.magisk.utils
import
android.content.Context
import
android.content.Intent
import
android.content.Intent
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager
import
android.os.Process
import
android.os.Process
import
android.widget.Toast
import
android.widget.Toast
import
com.topjohnwu.magisk.App
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.repository.AppRepository
import
com.topjohnwu.magisk.data.repository.AppRepository
...
@@ -17,6 +17,8 @@ import java.util.*
...
@@ -17,6 +17,8 @@ import java.util.*
object
SuLogger
{
object
SuLogger
{
private
val
context
:
Context
by
inject
()
@JvmStatic
@JvmStatic
fun
handleLogs
(
intent
:
Intent
)
{
fun
handleLogs
(
intent
:
Intent
)
{
...
@@ -66,9 +68,9 @@ object SuLogger {
...
@@ -66,9 +68,9 @@ object SuLogger {
}
}
private
fun
handleNotify
(
policy
:
MagiskPolicy
)
{
private
fun
handleNotify
(
policy
:
MagiskPolicy
)
{
if
(
policy
.
notification
&&
Config
.
get
<
Any
>(
Config
.
Key
.
SU_NOTIFICATION
)
as
Int
==
Config
.
Value
.
NOTIFICATION_TOAST
)
{
if
(
policy
.
notification
&&
Config
.
suNotification
==
Config
.
Value
.
NOTIFICATION_TOAST
)
{
Utils
.
toast
(
Utils
.
toast
(
App
.
self
.
getString
(
context
.
getString
(
if
(
policy
.
policy
==
Policy
.
ALLOW
)
if
(
policy
.
policy
==
Policy
.
ALLOW
)
R
.
string
.
su_allow_toast
R
.
string
.
su_allow_toast
else
else
...
...
app/src/main/java/com/topjohnwu/magisk/utils/Utils.java
deleted
100644 → 0
View file @
3e58d502
package
com
.
topjohnwu
.
magisk
.
utils
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.SharedPreferences
;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.PackageManager
;
import
android.content.res.Configuration
;
import
android.content.res.Resources
;
import
android.net.Uri
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.model.entity.OldModule
;
import
com.topjohnwu.magisk.model.update.UpdateCheckService
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.internal.UiThreadHandler
;
import
com.topjohnwu.superuser.io.SuFile
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
androidx.annotation.WorkerThread
;
import
androidx.work.Constraints
;
import
androidx.work.ExistingPeriodicWorkPolicy
;
import
androidx.work.ListenableWorker
;
import
androidx.work.NetworkType
;
import
androidx.work.PeriodicWorkRequest
;
import
androidx.work.WorkManager
;
public
class
Utils
{
public
static
void
toast
(
CharSequence
msg
,
int
duration
)
{
UiThreadHandler
.
run
(()
->
Toast
.
makeText
(
App
.
self
,
msg
,
duration
).
show
());
}
public
static
void
toast
(
int
resId
,
int
duration
)
{
UiThreadHandler
.
run
(()
->
Toast
.
makeText
(
App
.
self
,
resId
,
duration
).
show
());
}
public
static
String
dlString
(
String
url
)
{
String
s
=
Networking
.
get
(
url
).
execForString
().
getResult
();
return
s
==
null
?
""
:
s
;
}
public
static
int
getPrefsInt
(
SharedPreferences
prefs
,
String
key
,
int
def
)
{
return
Integer
.
parseInt
(
prefs
.
getString
(
key
,
String
.
valueOf
(
def
)));
}
public
static
int
getPrefsInt
(
SharedPreferences
prefs
,
String
key
)
{
return
getPrefsInt
(
prefs
,
key
,
0
);
}
public
static
int
dpInPx
(
int
dp
)
{
float
scale
=
App
.
self
.
getResources
().
getDisplayMetrics
().
density
;
return
(
int
)
(
dp
*
scale
+
0.5
);
}
public
static
String
fmt
(
String
fmt
,
Object
...
args
)
{
return
String
.
format
(
Locale
.
US
,
fmt
,
args
);
}
public
static
String
getAppLabel
(
ApplicationInfo
info
,
PackageManager
pm
)
{
try
{
if
(
info
.
labelRes
>
0
)
{
Resources
res
=
pm
.
getResourcesForApplication
(
info
);
Configuration
config
=
new
Configuration
();
config
.
setLocale
(
LocaleManager
.
getLocale
());
res
.
updateConfiguration
(
config
,
res
.
getDisplayMetrics
());
return
res
.
getString
(
info
.
labelRes
);
}
}
catch
(
Exception
ignored
)
{}
return
info
.
loadLabel
(
pm
).
toString
();
}
public
static
String
getLegalFilename
(
CharSequence
filename
)
{
return
filename
.
toString
().
replace
(
" "
,
"_"
).
replace
(
"'"
,
""
).
replace
(
"\""
,
""
)
.
replace
(
"$"
,
""
).
replace
(
"`"
,
""
).
replace
(
"*"
,
""
).
replace
(
"/"
,
"_"
)
.
replace
(
"#"
,
""
).
replace
(
"@"
,
""
).
replace
(
"\\"
,
"_"
);
}
@WorkerThread
public
static
Map
<
String
,
OldModule
>
loadModulesLeanback
()
{
final
Map
<
String
,
OldModule
>
moduleMap
=
new
ValueSortedMap
<>();
final
SuFile
path
=
new
SuFile
(
Const
.
MAGISK_PATH
);
final
SuFile
[]
modules
=
path
.
listFiles
((
file
,
name
)
->
!
name
.
equals
(
"lost+found"
)
&&
!
name
.
equals
(
".core"
)
);
for
(
SuFile
file
:
modules
)
{
if
(
file
.
isFile
())
continue
;
OldModule
module
=
new
OldModule
(
Const
.
MAGISK_PATH
+
"/"
+
file
.
getName
());
moduleMap
.
put
(
module
.
getId
(),
module
);
}
return
moduleMap
;
}
public
static
boolean
showSuperUser
()
{
return
Shell
.
rootAccess
()
&&
(
Const
.
USER_ID
==
0
||
(
int
)
Config
.
get
(
Config
.
Key
.
SU_MULTIUSER_MODE
)
!=
Config
.
Value
.
MULTIUSER_MODE_OWNER_MANAGED
);
}
public
static
boolean
isCanary
()
{
return
BuildConfig
.
VERSION_NAME
.
contains
(
"-"
);
}
public
static
void
scheduleUpdateCheck
()
{
if
(
Config
.
get
(
Config
.
Key
.
CHECK_UPDATES
))
{
Constraints
constraints
=
new
Constraints
.
Builder
()
.
setRequiredNetworkType
(
NetworkType
.
CONNECTED
)
.
setRequiresDeviceIdle
(
true
)
.
build
();
PeriodicWorkRequest
request
=
new
PeriodicWorkRequest
.
Builder
(
ClassMap
.
get
(
UpdateCheckService
.
class
),
12
,
TimeUnit
.
HOURS
)
.
setConstraints
(
constraints
)
.
build
();
WorkManager
.
getInstance
().
enqueueUniquePeriodicWork
(
Const
.
ID
.
CHECK_MAGISK_UPDATE_WORKER_ID
,
ExistingPeriodicWorkPolicy
.
REPLACE
,
request
);
}
else
{
WorkManager
.
getInstance
().
cancelUniqueWork
(
Const
.
ID
.
CHECK_MAGISK_UPDATE_WORKER_ID
);
}
}
public
static
void
openLink
(
Context
context
,
Uri
link
)
{
Intent
intent
=
new
Intent
(
Intent
.
ACTION_VIEW
,
link
);
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
);
if
(
intent
.
resolveActivity
(
context
.
getPackageManager
())
!=
null
)
{
context
.
startActivity
(
intent
);
}
else
{
toast
(
R
.
string
.
open_link_failed_toast
,
Toast
.
LENGTH_SHORT
);
}
}
}
app/src/main/java/com/topjohnwu/magisk/utils/Utils.kt
0 → 100644
View file @
7756e107
package
com.topjohnwu.magisk.utils
import
android.content.Context
import
android.content.Intent
import
android.content.SharedPreferences
import
android.content.pm.ApplicationInfo
import
android.content.pm.PackageManager
import
android.content.res.Configuration
import
android.content.res.Resources
import
android.net.Uri
import
android.widget.Toast
import
androidx.annotation.WorkerThread
import
androidx.work.*
import
com.topjohnwu.magisk.*
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.model.entity.OldModule
import
com.topjohnwu.magisk.model.update.UpdateCheckService
import
com.topjohnwu.net.Networking
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.internal.UiThreadHandler
import
com.topjohnwu.superuser.io.SuFile
import
java.util.*
import
java.util.concurrent.TimeUnit
object
Utils
{
val
isCanary
:
Boolean
get
()
=
BuildConfig
.
VERSION_NAME
.
contains
(
"-"
)
fun
toast
(
msg
:
CharSequence
,
duration
:
Int
)
{
UiThreadHandler
.
run
{
Toast
.
makeText
(
get
(),
msg
,
duration
).
show
()
}
}
fun
toast
(
resId
:
Int
,
duration
:
Int
)
{
UiThreadHandler
.
run
{
Toast
.
makeText
(
get
(),
resId
,
duration
).
show
()
}
}
fun
dlString
(
url
:
String
):
String
{
val
s
=
Networking
.
get
(
url
).
execForString
().
result
return
s
?:
""
}
fun
getPrefsInt
(
prefs
:
SharedPreferences
,
key
:
String
,
def
:
Int
=
0
):
Int
{
return
prefs
.
getString
(
key
,
def
.
toString
())
!!
.
toInt
()
}
fun
dpInPx
(
dp
:
Int
):
Int
{
val
scale
=
get
<
Resources
>().
displayMetrics
.
density
return
(
dp
*
scale
+
0.5
).
toInt
()
}
fun
fmt
(
fmt
:
String
,
vararg
args
:
Any
):
String
{
return
String
.
format
(
Locale
.
US
,
fmt
,
*
args
)
}
fun
getAppLabel
(
info
:
ApplicationInfo
,
pm
:
PackageManager
):
String
{
try
{
if
(
info
.
labelRes
>
0
)
{
val
res
=
pm
.
getResourcesForApplication
(
info
)
val
config
=
Configuration
()
config
.
setLocale
(
LocaleManager
.
locale
)
res
.
updateConfiguration
(
config
,
res
.
displayMetrics
)
return
res
.
getString
(
info
.
labelRes
)
}
}
catch
(
ignored
:
Exception
)
{
}
return
info
.
loadLabel
(
pm
).
toString
()
}
fun
getLegalFilename
(
filename
:
CharSequence
):
String
{
return
filename
.
toString
().
replace
(
" "
,
"_"
).
replace
(
"'"
,
""
).
replace
(
"\""
,
""
)
.
replace
(
"$"
,
""
).
replace
(
"`"
,
""
).
replace
(
"*"
,
""
).
replace
(
"/"
,
"_"
)
.
replace
(
"#"
,
""
).
replace
(
"@"
,
""
).
replace
(
"\\"
,
"_"
)
}
@WorkerThread
fun
loadModulesLeanback
():
Map
<
String
,
OldModule
>
{
val
moduleMap
=
ValueSortedMap
<
String
,
OldModule
>()
val
path
=
SuFile
(
Const
.
MAGISK_PATH
)
val
modules
=
path
.
listFiles
{
_
,
name
->
name
!=
"lost+found"
&&
name
!=
".core"
}
for
(
file
in
modules
!!
)
{
if
(
file
.
isFile
)
continue
val
module
=
OldModule
(
Const
.
MAGISK_PATH
+
"/"
+
file
.
name
)
moduleMap
[
module
.
id
]
=
module
}
return
moduleMap
}
fun
showSuperUser
():
Boolean
{
return
Shell
.
rootAccess
()
&&
(
Const
.
USER_ID
==
0
||
Config
.
suMultiuserMode
!=
Config
.
Value
.
MULTIUSER_MODE_OWNER_MANAGED
)
}
fun
scheduleUpdateCheck
()
{
if
(
Config
.
checkUpdate
)
{
val
constraints
=
Constraints
.
Builder
()
.
setRequiredNetworkType
(
NetworkType
.
CONNECTED
)
.
setRequiresDeviceIdle
(
true
)
.
build
()
val
request
=
PeriodicWorkRequest
.
Builder
(
ClassMap
[
UpdateCheckService
::
class
.
java
],
12
,
TimeUnit
.
HOURS
)
.
setConstraints
(
constraints
)
.
build
()
WorkManager
.
getInstance
().
enqueueUniquePeriodicWork
(
Const
.
ID
.
CHECK_MAGISK_UPDATE_WORKER_ID
,
ExistingPeriodicWorkPolicy
.
REPLACE
,
request
)
}
else
{
WorkManager
.
getInstance
().
cancelUniqueWork
(
Const
.
ID
.
CHECK_MAGISK_UPDATE_WORKER_ID
)
}
}
fun
openLink
(
context
:
Context
,
link
:
Uri
)
{
val
intent
=
Intent
(
Intent
.
ACTION_VIEW
,
link
)
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
)
if
(
intent
.
resolveActivity
(
context
.
packageManager
)
!=
null
)
{
context
.
startActivity
(
intent
)
}
else
{
toast
(
R
.
string
.
open_link_failed_toast
,
Toast
.
LENGTH_SHORT
)
}
}
}
app/src/main/java/com/topjohnwu/magisk/utils/XNetwork.kt
View file @
7756e107
package
com.topjohnwu.magisk.utils
package
com.topjohnwu.magisk.utils
import
android.content.Context
import
android.content.Context
import
android.content.Intent
import
androidx.browser.customtabs.CustomTabsIntent
import
androidx.core.content.ContextCompat
import
androidx.core.net.toUri
import
com.topjohnwu.magisk.KConfig
import
com.topjohnwu.magisk.R
import
okhttp3.ResponseBody
import
okhttp3.ResponseBody
import
java.io.File
import
java.io.File
...
@@ -19,36 +13,3 @@ fun ResponseBody.writeToFile(context: Context, fileName: String): File {
...
@@ -19,36 +13,3 @@ fun ResponseBody.writeToFile(context: Context, fileName: String): File {
}
}
fun
ResponseBody
.
writeToString
()
=
string
()
fun
ResponseBody
.
writeToString
()
=
string
()
fun
String
.
launch
()
=
if
(
KConfig
.
useCustomTabs
)
{
launchWithCustomTabs
()
}
else
{
launchWithIntent
()
}
private
fun
String
.
launchWithCustomTabs
()
{
val
context
:
Context
by
inject
()
val
primaryColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorPrimary
)
val
secondaryColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorSecondary
)
CustomTabsIntent
.
Builder
()
.
enableUrlBarHiding
()
.
setShowTitle
(
true
)
.
setToolbarColor
(
primaryColor
)
.
setSecondaryToolbarColor
(
secondaryColor
)
.
build
()
.
apply
{
intent
.
flags
=
Intent
.
FLAG_ACTIVITY_NEW_TASK
}
.
launchUrl
(
context
,
this
.
toUri
())
}
private
fun
String
.
launchWithIntent
()
{
val
context
:
Context
by
inject
()
Intent
(
Intent
.
ACTION_VIEW
)
.
apply
{
data
=
toUri
()
flags
=
Intent
.
FLAG_ACTIVITY_NEW_TASK
}
.
startActivity
(
context
)
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/view/MarkDownWindow.java
View file @
7756e107
...
@@ -5,6 +5,8 @@ import android.view.LayoutInflater;
...
@@ -5,6 +5,8 @@ import android.view.LayoutInflater;
import
android.view.View
;
import
android.view.View
;
import
android.widget.TextView
;
import
android.widget.TextView
;
import
androidx.appcompat.app.AlertDialog
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.net.ResponseListener
;
import
com.topjohnwu.net.ResponseListener
;
...
@@ -12,7 +14,6 @@ import com.topjohnwu.net.ResponseListener;
...
@@ -12,7 +14,6 @@ import com.topjohnwu.net.ResponseListener;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.util.Scanner
;
import
java.util.Scanner
;
import
androidx.appcompat.app.AlertDialog
;
import
ru.noties.markwon.Markwon
;
import
ru.noties.markwon.Markwon
;
import
ru.noties.markwon.html.HtmlPlugin
;
import
ru.noties.markwon.html.HtmlPlugin
;
import
ru.noties.markwon.image.ImagesPlugin
;
import
ru.noties.markwon.image.ImagesPlugin
;
...
...
app/src/main/java/com/topjohnwu/magisk/view/Notifications.java
View file @
7756e107
...
@@ -7,19 +7,19 @@ import android.content.Context;
...
@@ -7,19 +7,19 @@ import android.content.Context;
import
android.content.Intent
;
import
android.content.Intent
;
import
android.os.Build
;
import
android.os.Build
;
import
androidx.core.app.NotificationCompat
;
import
androidx.core.app.NotificationManagerCompat
;
import
androidx.core.app.TaskStackBuilder
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Info
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.model.receiver.GeneralReceiver
;
import
com.topjohnwu.magisk.model.receiver.GeneralReceiver
;
import
com.topjohnwu.magisk.ui.SplashActivity
;
import
com.topjohnwu.magisk.ui.SplashActivity
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.Utils
;
import
androidx.core.app.NotificationCompat
;
import
androidx.core.app.NotificationManagerCompat
;
import
androidx.core.app.TaskStackBuilder
;
public
class
Notifications
{
public
class
Notifications
{
public
static
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
App
.
self
);
public
static
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
App
.
self
);
...
@@ -62,12 +62,12 @@ public class Notifications {
...
@@ -62,12 +62,12 @@ public class Notifications {
public
static
void
managerUpdate
()
{
public
static
void
managerUpdate
()
{
App
app
=
App
.
self
;
App
app
=
App
.
self
;
String
name
=
Utils
.
fmt
(
"MagiskManager v%s(%d)"
,
String
name
=
Utils
.
INSTANCE
.
fmt
(
"MagiskManager v%s(%d)"
,
Config
.
remoteManagerVersionString
,
Config
.
remoteManagerVersionCode
);
Info
.
remoteManagerVersionString
,
Info
.
remoteManagerVersionCode
);
Intent
intent
=
new
Intent
(
app
,
ClassMap
.
get
(
GeneralReceiver
.
class
));
Intent
intent
=
new
Intent
(
app
,
ClassMap
.
get
(
GeneralReceiver
.
class
));
intent
.
setAction
(
Const
.
Key
.
BROADCAST_MANAGER_UPDATE
);
intent
.
setAction
(
Const
.
Key
.
BROADCAST_MANAGER_UPDATE
);
intent
.
putExtra
(
Const
.
Key
.
INTENT_SET_LINK
,
Config
.
managerLink
);
intent
.
putExtra
(
Const
.
Key
.
INTENT_SET_LINK
,
Info
.
managerLink
);
intent
.
putExtra
(
Const
.
Key
.
INTENT_SET_NAME
,
name
);
intent
.
putExtra
(
Const
.
Key
.
INTENT_SET_NAME
,
name
);
PendingIntent
pendingIntent
=
PendingIntent
.
getBroadcast
(
app
,
PendingIntent
pendingIntent
=
PendingIntent
.
getBroadcast
(
app
,
Const
.
ID
.
APK_UPDATE_NOTIFICATION_ID
,
intent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
Const
.
ID
.
APK_UPDATE_NOTIFICATION_ID
,
intent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
...
...
app/src/main/java/com/topjohnwu/magisk/view/ProgressNotification.java
View file @
7756e107
...
@@ -5,13 +5,13 @@ import android.app.PendingIntent;
...
@@ -5,13 +5,13 @@ import android.app.PendingIntent;
import
android.content.Intent
;
import
android.content.Intent
;
import
android.widget.Toast
;
import
android.widget.Toast
;
import
androidx.core.app.NotificationCompat
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.App
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.net.DownloadProgressListener
;
import
com.topjohnwu.net.DownloadProgressListener
;
import
androidx.core.app.NotificationCompat
;
public
class
ProgressNotification
implements
DownloadProgressListener
{
public
class
ProgressNotification
implements
DownloadProgressListener
{
private
NotificationCompat
.
Builder
builder
;
private
NotificationCompat
.
Builder
builder
;
...
@@ -22,7 +22,7 @@ public class ProgressNotification implements DownloadProgressListener {
...
@@ -22,7 +22,7 @@ public class ProgressNotification implements DownloadProgressListener {
builder
=
Notifications
.
progress
(
title
);
builder
=
Notifications
.
progress
(
title
);
prevTime
=
System
.
currentTimeMillis
();
prevTime
=
System
.
currentTimeMillis
();
update
();
update
();
Utils
.
toast
(
App
.
self
.
getString
(
R
.
string
.
downloading_toast
,
title
),
Toast
.
LENGTH_SHORT
);
Utils
.
INSTANCE
.
toast
(
App
.
self
.
getString
(
R
.
string
.
downloading_toast
,
title
),
Toast
.
LENGTH_SHORT
);
}
}
@Override
@Override
...
...
app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.
java
→
app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.
kt
View file @
7756e107
package
com
.
topjohnwu
.
magisk
.
view
;
package
com.topjohnwu.magisk.view
import
android.content.Context
;
import
android.content.Context
import
android.content.Intent
;
import
android.content.Intent
import
android.content.pm.ShortcutInfo
;
import
android.content.pm.ShortcutInfo
import
android.content.pm.ShortcutManager
;
import
android.content.pm.ShortcutManager
import
android.graphics.drawable.Icon
;
import
android.graphics.drawable.Icon
import
android.os.Build
;
import
android.os.Build
import
androidx.annotation.RequiresApi
import
com.topjohnwu.magisk.*
import
com.topjohnwu.magisk.ui.SplashActivity
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.magisk.ClassMap
;
object
Shortcuts
{
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.ui.SplashActivity
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
java.util.ArrayList
;
fun
setup
(
context
:
Context
)
{
import
androidx.annotation.RequiresApi
;
public
class
Shortcuts
{
public
static
void
setup
(
Context
context
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
N_MR1
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
N_MR1
)
{
ShortcutManager
manager
=
context
.
getSystemService
(
ShortcutManager
.
class
);
val
manager
=
context
.
getSystemService
(
ShortcutManager
::
class
.
java
)
manager
.
setDynamicShortcuts
(
getShortCuts
(
context
));
manager
?.
dynamicShortcuts
=
getShortCuts
(
context
)
}
}
}
}
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
N_MR1
)
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
N_MR1
)
private
static
ArrayList
<
ShortcutInfo
>
getShortCuts
(
Context
context
)
{
private
fun
getShortCuts
(
context
:
Context
):
List
<
ShortcutInfo
>
{
ArrayList
<
ShortcutInfo
>
shortCuts
=
new
ArrayList
<>();
val
shortCuts
=
mutableListOf
<
ShortcutInfo
>()
boolean
root
=
Shell
.
rootAccess
();
val
root
=
Shell
.
rootAccess
()
if
(
Utils
.
showSuperUser
())
{
if
(
Utils
.
showSuperUser
())
{
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
context
,
"superuser"
)
shortCuts
.
add
(
ShortcutInfo
.
Builder
(
context
,
"superuser"
)
.
setShortLabel
(
context
.
getString
(
R
.
string
.
superuser
))
.
setShortLabel
(
context
.
getString
(
R
.
string
.
superuser
))
.
setIntent
(
new
Intent
(
context
,
ClassMap
.
get
(
SplashActivity
.
class
)
)
.
setIntent
(
Intent
(
context
,
ClassMap
[
SplashActivity
::
class
.
java
]
)
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"superuser"
)
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"superuser"
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
setIcon
(
Icon
.
createWithResource
(
context
,
R
.
drawable
.
sc_superuser
))
.
setIcon
(
Icon
.
createWithResource
(
context
,
R
.
drawable
.
sc_superuser
))
.
setRank
(
0
)
.
setRank
(
0
)
.
build
())
;
.
build
())
}
}
if
(
root
&&
(
boolean
)
Config
.
get
(
Config
.
Key
.
MAGISKHIDE
)
)
{
if
(
root
&&
Config
.
magiskHide
)
{
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
context
,
"magiskhide"
)
shortCuts
.
add
(
ShortcutInfo
.
Builder
(
context
,
"magiskhide"
)
.
setShortLabel
(
context
.
getString
(
R
.
string
.
magiskhide
))
.
setShortLabel
(
context
.
getString
(
R
.
string
.
magiskhide
))
.
setIntent
(
new
Intent
(
context
,
ClassMap
.
get
(
SplashActivity
.
class
)
)
.
setIntent
(
Intent
(
context
,
ClassMap
[
SplashActivity
::
class
.
java
]
)
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"magiskhide"
)
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"magiskhide"
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
setIcon
(
Icon
.
createWithResource
(
context
,
R
.
drawable
.
sc_magiskhide
))
.
setIcon
(
Icon
.
createWithResource
(
context
,
R
.
drawable
.
sc_magiskhide
))
.
setRank
(
1
)
.
setRank
(
1
)
.
build
())
;
.
build
())
}
}
if
(!
(
boolean
)
Config
.
get
(
Config
.
Key
.
COREONLY
)
&&
root
&&
Config
.
magiskVersionCode
>=
0
)
{
if
(!
Config
.
coreOnly
&&
root
&&
Info
.
magiskVersionCode
>=
0
)
{
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
context
,
"modules"
)
shortCuts
.
add
(
ShortcutInfo
.
Builder
(
context
,
"modules"
)
.
setShortLabel
(
context
.
getString
(
R
.
string
.
modules
))
.
setShortLabel
(
context
.
getString
(
R
.
string
.
modules
))
.
setIntent
(
new
Intent
(
context
,
ClassMap
.
get
(
SplashActivity
.
class
)
)
.
setIntent
(
Intent
(
context
,
ClassMap
[
SplashActivity
::
class
.
java
]
)
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"modules"
)
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"modules"
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
setIcon
(
Icon
.
createWithResource
(
context
,
R
.
drawable
.
sc_extension
))
.
setIcon
(
Icon
.
createWithResource
(
context
,
R
.
drawable
.
sc_extension
))
.
setRank
(
3
)
.
setRank
(
3
)
.
build
())
;
.
build
())
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
context
,
"downloads"
)
shortCuts
.
add
(
ShortcutInfo
.
Builder
(
context
,
"downloads"
)
.
setShortLabel
(
context
.
getString
(
R
.
string
.
downloads
))
.
setShortLabel
(
context
.
getString
(
R
.
string
.
downloads
))
.
setIntent
(
new
Intent
(
context
,
ClassMap
.
get
(
SplashActivity
.
class
)
)
.
setIntent
(
Intent
(
context
,
ClassMap
[
SplashActivity
::
class
.
java
]
)
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"downloads"
)
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"downloads"
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
setIcon
(
Icon
.
createWithResource
(
context
,
R
.
drawable
.
sc_cloud_download
))
.
setIcon
(
Icon
.
createWithResource
(
context
,
R
.
drawable
.
sc_cloud_download
))
.
setRank
(
2
)
.
setRank
(
2
)
.
build
())
;
.
build
())
}
}
return
shortCuts
;
return
shortCuts
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/view/dialogs/EnvFixDialog.java
View file @
7756e107
...
@@ -4,6 +4,8 @@ import android.app.Activity;
...
@@ -4,6 +4,8 @@ import android.app.Activity;
import
android.app.ProgressDialog
;
import
android.app.ProgressDialog
;
import
android.widget.Toast
;
import
android.widget.Toast
;
import
androidx.annotation.NonNull
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.tasks.MagiskInstaller
;
import
com.topjohnwu.magisk.tasks.MagiskInstaller
;
import
com.topjohnwu.magisk.utils.RootUtils
;
import
com.topjohnwu.magisk.utils.RootUtils
;
...
@@ -12,8 +14,6 @@ import com.topjohnwu.superuser.Shell;
...
@@ -12,8 +14,6 @@ import com.topjohnwu.superuser.Shell;
import
com.topjohnwu.superuser.internal.UiThreadHandler
;
import
com.topjohnwu.superuser.internal.UiThreadHandler
;
import
com.topjohnwu.superuser.io.SuFile
;
import
com.topjohnwu.superuser.io.SuFile
;
import
androidx.annotation.NonNull
;
public
class
EnvFixDialog
extends
CustomAlertDialog
{
public
class
EnvFixDialog
extends
CustomAlertDialog
{
public
EnvFixDialog
(
@NonNull
Activity
activity
)
{
public
EnvFixDialog
(
@NonNull
Activity
activity
)
{
...
@@ -36,7 +36,7 @@ public class EnvFixDialog extends CustomAlertDialog {
...
@@ -36,7 +36,7 @@ public class EnvFixDialog extends CustomAlertDialog {
@Override
@Override
protected
void
onResult
(
boolean
success
)
{
protected
void
onResult
(
boolean
success
)
{
pd
.
dismiss
();
pd
.
dismiss
();
Utils
.
toast
(
success
?
R
.
string
.
reboot_delay_toast
:
R
.
string
.
setup_fail
,
Toast
.
LENGTH_LONG
);
Utils
.
INSTANCE
.
toast
(
success
?
R
.
string
.
reboot_delay_toast
:
R
.
string
.
setup_fail
,
Toast
.
LENGTH_LONG
);
if
(
success
)
if
(
success
)
UiThreadHandler
.
handler
.
postDelayed
(
RootUtils:
:
reboot
,
5000
);
UiThreadHandler
.
handler
.
postDelayed
(
RootUtils:
:
reboot
,
5000
);
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/view/dialogs/FingerprintAuthDialog.java
View file @
7756e107
...
@@ -11,14 +11,14 @@ import android.os.Build;
...
@@ -11,14 +11,14 @@ import android.os.Build;
import
android.view.Gravity
;
import
android.view.Gravity
;
import
android.widget.Toast
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.FingerprintHelper
;
import
com.topjohnwu.magisk.utils.Utils
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
androidx.appcompat.app.AlertDialog
;
import
androidx.appcompat.app.AlertDialog
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.FingerprintHelper
;
import
com.topjohnwu.magisk.utils.Utils
;
@TargetApi
(
Build
.
VERSION_CODES
.
M
)
@TargetApi
(
Build
.
VERSION_CODES
.
M
)
public
class
FingerprintAuthDialog
extends
CustomAlertDialog
{
public
class
FingerprintAuthDialog
extends
CustomAlertDialog
{
...
@@ -31,13 +31,13 @@ public class FingerprintAuthDialog extends CustomAlertDialog {
...
@@ -31,13 +31,13 @@ public class FingerprintAuthDialog extends CustomAlertDialog {
super
(
activity
);
super
(
activity
);
callback
=
onSuccess
;
callback
=
onSuccess
;
Drawable
fingerprint
=
activity
.
getResources
().
getDrawable
(
R
.
drawable
.
ic_fingerprint
);
Drawable
fingerprint
=
activity
.
getResources
().
getDrawable
(
R
.
drawable
.
ic_fingerprint
);
fingerprint
.
setBounds
(
0
,
0
,
Utils
.
dpInPx
(
50
),
Utils
.
dpInPx
(
50
));
fingerprint
.
setBounds
(
0
,
0
,
Utils
.
INSTANCE
.
dpInPx
(
50
),
Utils
.
INSTANCE
.
dpInPx
(
50
));
Resources
.
Theme
theme
=
activity
.
getTheme
();
Resources
.
Theme
theme
=
activity
.
getTheme
();
TypedArray
ta
=
theme
.
obtainStyledAttributes
(
new
int
[]
{
R
.
attr
.
imageColorTint
});
TypedArray
ta
=
theme
.
obtainStyledAttributes
(
new
int
[]
{
R
.
attr
.
imageColorTint
});
fingerprint
.
setTint
(
ta
.
getColor
(
0
,
Color
.
GRAY
));
fingerprint
.
setTint
(
ta
.
getColor
(
0
,
Color
.
GRAY
));
ta
.
recycle
();
ta
.
recycle
();
binding
.
message
.
setCompoundDrawables
(
null
,
null
,
null
,
fingerprint
);
binding
.
message
.
setCompoundDrawables
(
null
,
null
,
null
,
fingerprint
);
binding
.
message
.
setCompoundDrawablePadding
(
Utils
.
dpInPx
(
20
));
binding
.
message
.
setCompoundDrawablePadding
(
Utils
.
INSTANCE
.
dpInPx
(
20
));
binding
.
message
.
setGravity
(
Gravity
.
CENTER
);
binding
.
message
.
setGravity
(
Gravity
.
CENTER
);
setMessage
(
R
.
string
.
auth_fingerprint
);
setMessage
(
R
.
string
.
auth_fingerprint
);
setNegativeButton
(
R
.
string
.
close
,
(
d
,
w
)
->
{
setNegativeButton
(
R
.
string
.
close
,
(
d
,
w
)
->
{
...
@@ -54,7 +54,9 @@ public class FingerprintAuthDialog extends CustomAlertDialog {
...
@@ -54,7 +54,9 @@ public class FingerprintAuthDialog extends CustomAlertDialog {
});
});
try
{
try
{
helper
=
new
DialogFingerprintHelper
();
helper
=
new
DialogFingerprintHelper
();
}
catch
(
Exception
ignored
)
{}
}
catch
(
Exception
ignored
)
{
ignored
.
printStackTrace
();
}
}
}
public
FingerprintAuthDialog
(
@NonNull
Activity
activity
,
@NonNull
Runnable
onSuccess
,
@NonNull
Runnable
onFailure
)
{
public
FingerprintAuthDialog
(
@NonNull
Activity
activity
,
@NonNull
Runnable
onSuccess
,
@NonNull
Runnable
onFailure
)
{
...
@@ -67,7 +69,7 @@ public class FingerprintAuthDialog extends CustomAlertDialog {
...
@@ -67,7 +69,7 @@ public class FingerprintAuthDialog extends CustomAlertDialog {
create
();
create
();
if
(
helper
==
null
)
{
if
(
helper
==
null
)
{
dialog
.
dismiss
();
dialog
.
dismiss
();
Utils
.
toast
(
R
.
string
.
auth_fail
,
Toast
.
LENGTH_SHORT
);
Utils
.
INSTANCE
.
toast
(
R
.
string
.
auth_fail
,
Toast
.
LENGTH_SHORT
);
}
else
{
}
else
{
helper
.
authenticate
();
helper
.
authenticate
();
dialog
.
show
();
dialog
.
show
();
...
...
app/src/main/java/com/topjohnwu/magisk/view/dialogs/InstallMethodDialog.java
View file @
7756e107
...
@@ -4,10 +4,12 @@ import android.app.Activity;
...
@@ -4,10 +4,12 @@ import android.app.Activity;
import
android.content.Intent
;
import
android.content.Intent
;
import
android.widget.Toast
;
import
android.widget.Toast
;
import
androidx.appcompat.app.AlertDialog
;
import
com.google.android.material.snackbar.Snackbar
;
import
com.google.android.material.snackbar.Snackbar
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Info
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.ui.base.IBaseLeanback
;
import
com.topjohnwu.magisk.ui.base.IBaseLeanback
;
import
com.topjohnwu.magisk.ui.flash.FlashActivity
;
import
com.topjohnwu.magisk.ui.flash.FlashActivity
;
...
@@ -19,8 +21,6 @@ import com.topjohnwu.net.Networking;
...
@@ -19,8 +21,6 @@ import com.topjohnwu.net.Networking;
import
java.io.File
;
import
java.io.File
;
import
java.util.List
;
import
java.util.List
;
import
androidx.appcompat.app.AlertDialog
;
class
InstallMethodDialog
extends
AlertDialog
.
Builder
{
class
InstallMethodDialog
extends
AlertDialog
.
Builder
{
<
Ctxt
extends
Activity
&
IBaseLeanback
>
InstallMethodDialog
(
Ctxt
activity
,
List
<
String
>
options
)
{
<
Ctxt
extends
Activity
&
IBaseLeanback
>
InstallMethodDialog
(
Ctxt
activity
,
List
<
String
>
options
)
{
...
@@ -50,7 +50,7 @@ class InstallMethodDialog extends AlertDialog.Builder {
...
@@ -50,7 +50,7 @@ class InstallMethodDialog extends AlertDialog.Builder {
private
<
Ctxt
extends
Activity
&
IBaseLeanback
>
void
patchBoot
(
Ctxt
activity
)
{
private
<
Ctxt
extends
Activity
&
IBaseLeanback
>
void
patchBoot
(
Ctxt
activity
)
{
activity
.
runWithExternalRW
(()
->
{
activity
.
runWithExternalRW
(()
->
{
Utils
.
toast
(
R
.
string
.
patch_file_msg
,
Toast
.
LENGTH_LONG
);
Utils
.
INSTANCE
.
toast
(
R
.
string
.
patch_file_msg
,
Toast
.
LENGTH_LONG
);
Intent
intent
=
new
Intent
(
Intent
.
ACTION_GET_CONTENT
)
Intent
intent
=
new
Intent
(
Intent
.
ACTION_GET_CONTENT
)
.
setType
(
"*/*"
)
.
setType
(
"*/*"
)
.
addCategory
(
Intent
.
CATEGORY_OPENABLE
);
.
addCategory
(
Intent
.
CATEGORY_OPENABLE
);
...
@@ -68,11 +68,11 @@ class InstallMethodDialog extends AlertDialog.Builder {
...
@@ -68,11 +68,11 @@ class InstallMethodDialog extends AlertDialog.Builder {
private
<
Ctxt
extends
Activity
&
IBaseLeanback
>
void
downloadOnly
(
Ctxt
activity
)
{
private
<
Ctxt
extends
Activity
&
IBaseLeanback
>
void
downloadOnly
(
Ctxt
activity
)
{
activity
.
runWithExternalRW
(()
->
{
activity
.
runWithExternalRW
(()
->
{
String
filename
=
Utils
.
fmt
(
"Magisk-v%s(%d).zip"
,
String
filename
=
Utils
.
INSTANCE
.
fmt
(
"Magisk-v%s(%d).zip"
,
Config
.
remoteMagiskVersionString
,
Config
.
remoteMagiskVersionCode
);
Info
.
remoteMagiskVersionString
,
Info
.
remoteMagiskVersionCode
);
File
zip
=
new
File
(
Const
.
EXTERNAL_PATH
,
filename
);
File
zip
=
new
File
(
Const
.
EXTERNAL_PATH
,
filename
);
ProgressNotification
progress
=
new
ProgressNotification
(
filename
);
ProgressNotification
progress
=
new
ProgressNotification
(
filename
);
Networking
.
get
(
Config
.
magiskLink
)
Networking
.
get
(
Info
.
magiskLink
)
.
setDownloadProgressListener
(
progress
)
.
setDownloadProgressListener
(
progress
)
.
setErrorHandler
((
conn
,
e
)
->
progress
.
dlFail
())
.
setErrorHandler
((
conn
,
e
)
->
progress
.
dlFail
())
.
getAsFile
(
zip
,
f
->
{
.
getAsFile
(
zip
,
f
->
{
...
...
app/src/main/java/com/topjohnwu/magisk/view/dialogs/MagiskInstallDialog.java
View file @
7756e107
...
@@ -4,7 +4,7 @@ import android.app.Activity;
...
@@ -4,7 +4,7 @@ import android.app.Activity;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.text.TextUtils
;
import
android.text.TextUtils
;
import
com.topjohnwu.magisk.
Config
;
import
com.topjohnwu.magisk.
Info
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.ui.base.IBaseLeanback
;
import
com.topjohnwu.magisk.ui.base.IBaseLeanback
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.Utils
;
...
@@ -18,8 +18,8 @@ import java.util.List;
...
@@ -18,8 +18,8 @@ import java.util.List;
public
class
MagiskInstallDialog
extends
CustomAlertDialog
{
public
class
MagiskInstallDialog
extends
CustomAlertDialog
{
public
<
Ctxt
extends
Activity
&
IBaseLeanback
>
MagiskInstallDialog
(
Ctxt
a
)
{
public
<
Ctxt
extends
Activity
&
IBaseLeanback
>
MagiskInstallDialog
(
Ctxt
a
)
{
super
(
a
);
super
(
a
);
String
filename
=
Utils
.
fmt
(
"Magisk-v%s(%d).zip"
,
String
filename
=
Utils
.
INSTANCE
.
fmt
(
"Magisk-v%s(%d).zip"
,
Config
.
remoteMagiskVersionString
,
Config
.
remoteMagiskVersionCode
);
Info
.
remoteMagiskVersionString
,
Info
.
remoteMagiskVersionCode
);
setTitle
(
a
.
getString
(
R
.
string
.
repo_install_title
,
a
.
getString
(
R
.
string
.
magisk
)));
setTitle
(
a
.
getString
(
R
.
string
.
repo_install_title
,
a
.
getString
(
R
.
string
.
magisk
)));
setMessage
(
a
.
getString
(
R
.
string
.
repo_install_msg
,
filename
));
setMessage
(
a
.
getString
(
R
.
string
.
repo_install_msg
,
filename
));
setCancelable
(
true
);
setCancelable
(
true
);
...
@@ -36,13 +36,13 @@ public class MagiskInstallDialog extends CustomAlertDialog {
...
@@ -36,13 +36,13 @@ public class MagiskInstallDialog extends CustomAlertDialog {
}
}
new
InstallMethodDialog
(
a
,
options
).
show
();
new
InstallMethodDialog
(
a
,
options
).
show
();
});
});
if
(!
TextUtils
.
isEmpty
(
Config
.
magiskNoteLink
))
{
if
(!
TextUtils
.
isEmpty
(
Info
.
magiskNoteLink
))
{
setNeutralButton
(
R
.
string
.
release_notes
,
(
d
,
i
)
->
{
setNeutralButton
(
R
.
string
.
release_notes
,
(
d
,
i
)
->
{
if
(
Config
.
magiskNoteLink
.
contains
(
"forum.xda-developers"
))
{
if
(
Info
.
magiskNoteLink
.
contains
(
"forum.xda-developers"
))
{
// Open forum links in browser
// Open forum links in browser
Utils
.
openLink
(
a
,
Uri
.
parse
(
Config
.
magiskNoteLink
));
Utils
.
INSTANCE
.
openLink
(
a
,
Uri
.
parse
(
Info
.
magiskNoteLink
));
}
else
{
}
else
{
MarkDownWindow
.
show
(
a
,
null
,
Config
.
magiskNoteLink
);
MarkDownWindow
.
show
(
a
,
null
,
Info
.
magiskNoteLink
);
}
}
});
});
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/view/dialogs/ManagerInstallDialog.java
View file @
7756e107
...
@@ -5,7 +5,7 @@ import android.text.TextUtils;
...
@@ -5,7 +5,7 @@ import android.text.TextUtils;
import
androidx.annotation.NonNull
;
import
androidx.annotation.NonNull
;
import
com.topjohnwu.magisk.
Config
;
import
com.topjohnwu.magisk.
Info
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.DownloadApp
;
import
com.topjohnwu.magisk.utils.DownloadApp
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.Utils
;
...
@@ -15,14 +15,14 @@ public class ManagerInstallDialog extends CustomAlertDialog {
...
@@ -15,14 +15,14 @@ public class ManagerInstallDialog extends CustomAlertDialog {
public
ManagerInstallDialog
(
@NonNull
Activity
a
)
{
public
ManagerInstallDialog
(
@NonNull
Activity
a
)
{
super
(
a
);
super
(
a
);
String
name
=
Utils
.
fmt
(
"MagiskManager v%s(%d)"
,
String
name
=
Utils
.
INSTANCE
.
fmt
(
"MagiskManager v%s(%d)"
,
Config
.
remoteManagerVersionString
,
Config
.
remoteManagerVersionCode
);
Info
.
remoteManagerVersionString
,
Info
.
remoteManagerVersionCode
);
setTitle
(
a
.
getString
(
R
.
string
.
repo_install_title
,
a
.
getString
(
R
.
string
.
app_name
)));
setTitle
(
a
.
getString
(
R
.
string
.
repo_install_title
,
a
.
getString
(
R
.
string
.
app_name
)));
setMessage
(
a
.
getString
(
R
.
string
.
repo_install_msg
,
name
));
setMessage
(
a
.
getString
(
R
.
string
.
repo_install_msg
,
name
));
setCancelable
(
true
);
setCancelable
(
true
);
setPositiveButton
(
R
.
string
.
install
,
(
d
,
i
)
->
DownloadApp
.
upgrade
(
name
));
setPositiveButton
(
R
.
string
.
install
,
(
d
,
i
)
->
DownloadApp
.
upgrade
(
name
));
if
(!
TextUtils
.
isEmpty
(
Config
.
managerNoteLink
))
{
if
(!
TextUtils
.
isEmpty
(
Info
.
managerNoteLink
))
{
setNeutralButton
(
R
.
string
.
app_changelog
,
(
d
,
i
)
->
MarkDownWindow
.
show
(
a
,
null
,
Config
.
managerNoteLink
));
setNeutralButton
(
R
.
string
.
app_changelog
,
(
d
,
i
)
->
MarkDownWindow
.
show
(
a
,
null
,
Info
.
managerNoteLink
));
}
}
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/view/dialogs/UninstallDialog.java
View file @
7756e107
...
@@ -7,9 +7,11 @@ import android.net.Uri;
...
@@ -7,9 +7,11 @@ import android.net.Uri;
import
android.text.TextUtils
;
import
android.text.TextUtils
;
import
android.widget.Toast
;
import
android.widget.Toast
;
import
androidx.annotation.NonNull
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.Config
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Info
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.ui.flash.FlashActivity
;
import
com.topjohnwu.magisk.ui.flash.FlashActivity
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.Utils
;
...
@@ -19,8 +21,6 @@ import com.topjohnwu.superuser.Shell;
...
@@ -19,8 +21,6 @@ import com.topjohnwu.superuser.Shell;
import
java.io.File
;
import
java.io.File
;
import
androidx.annotation.NonNull
;
public
class
UninstallDialog
extends
CustomAlertDialog
{
public
class
UninstallDialog
extends
CustomAlertDialog
{
public
UninstallDialog
(
@NonNull
Activity
activity
)
{
public
UninstallDialog
(
@NonNull
Activity
activity
)
{
...
@@ -34,17 +34,17 @@ public class UninstallDialog extends CustomAlertDialog {
...
@@ -34,17 +34,17 @@ public class UninstallDialog extends CustomAlertDialog {
Shell
.
su
(
"restore_imgs"
).
submit
(
result
->
{
Shell
.
su
(
"restore_imgs"
).
submit
(
result
->
{
dialog
.
cancel
();
dialog
.
cancel
();
if
(
result
.
isSuccess
())
{
if
(
result
.
isSuccess
())
{
Utils
.
toast
(
R
.
string
.
restore_done
,
Toast
.
LENGTH_SHORT
);
Utils
.
INSTANCE
.
toast
(
R
.
string
.
restore_done
,
Toast
.
LENGTH_SHORT
);
}
else
{
}
else
{
Utils
.
toast
(
R
.
string
.
restore_fail
,
Toast
.
LENGTH_LONG
);
Utils
.
INSTANCE
.
toast
(
R
.
string
.
restore_fail
,
Toast
.
LENGTH_LONG
);
}
}
});
});
});
});
if
(!
TextUtils
.
isEmpty
(
Config
.
uninstallerLink
))
{
if
(!
TextUtils
.
isEmpty
(
Info
.
uninstallerLink
))
{
setPositiveButton
(
R
.
string
.
complete_uninstall
,
(
d
,
i
)
->
{
setPositiveButton
(
R
.
string
.
complete_uninstall
,
(
d
,
i
)
->
{
File
zip
=
new
File
(
activity
.
getFilesDir
(),
"uninstaller.zip"
);
File
zip
=
new
File
(
activity
.
getFilesDir
(),
"uninstaller.zip"
);
ProgressNotification
progress
=
new
ProgressNotification
(
zip
.
getName
());
ProgressNotification
progress
=
new
ProgressNotification
(
zip
.
getName
());
Networking
.
get
(
Config
.
uninstallerLink
)
Networking
.
get
(
Info
.
uninstallerLink
)
.
setDownloadProgressListener
(
progress
)
.
setDownloadProgressListener
(
progress
)
.
setErrorHandler
(((
conn
,
e
)
->
progress
.
dlFail
()))
.
setErrorHandler
(((
conn
,
e
)
->
progress
.
dlFail
()))
.
getAsFile
(
zip
,
f
->
{
.
getAsFile
(
zip
,
f
->
{
...
...
app/src/main/res/xml/app_settings.xml
View file @
7756e107
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
<SwitchPreferenceCompat
<SwitchPreferenceCompat
android:key=
"dark_theme"
android:key=
"dark_theme"
android:defaultValue=
"true"
android:title=
"@string/settings_dark_theme_title"
android:title=
"@string/settings_dark_theme_title"
android:summary=
"@string/settings_dark_theme_summary"
/>
android:summary=
"@string/settings_dark_theme_summary"
/>
...
@@ -95,28 +96,33 @@
...
@@ -95,28 +96,33 @@
<ListPreference
<ListPreference
android:key=
"su_auto_response"
android:key=
"su_auto_response"
android:title=
"@string/auto_response"
android:title=
"@string/auto_response"
android:defaultValue=
"0"
android:entries=
"@array/auto_response"
android:entries=
"@array/auto_response"
android:entryValues=
"@array/value_array"
/>
android:entryValues=
"@array/value_array"
/>
<ListPreference
<ListPreference
android:key=
"su_request_timeout"
android:key=
"su_request_timeout"
android:title=
"@string/request_timeout"
android:title=
"@string/request_timeout"
android:defaultValue=
"10"
android:entries=
"@array/request_timeout"
android:entries=
"@array/request_timeout"
android:entryValues=
"@array/request_timeout_value"
/>
android:entryValues=
"@array/request_timeout_value"
/>
<ListPreference
<ListPreference
android:key=
"su_notification"
android:key=
"su_notification"
android:title=
"@string/superuser_notification"
android:title=
"@string/superuser_notification"
android:defaultValue=
"1"
android:entries=
"@array/su_notification"
android:entries=
"@array/su_notification"
android:entryValues=
"@array/value_array"
/>
android:entryValues=
"@array/value_array"
/>
<SwitchPreferenceCompat
<SwitchPreferenceCompat
android:key=
"su_fingerprint"
android:key=
"su_fingerprint"
android:defaultValue=
"false"
android:title=
"@string/settings_su_fingerprint_title"
android:title=
"@string/settings_su_fingerprint_title"
android:summary=
"@string/settings_su_fingerprint_summary"
/>
android:summary=
"@string/settings_su_fingerprint_summary"
/>
<SwitchPreferenceCompat
<SwitchPreferenceCompat
android:key=
"su_reauth"
android:key=
"su_reauth"
android:defaultValue=
"false"
android:title=
"@string/settings_su_reauth_title"
android:title=
"@string/settings_su_reauth_title"
android:summary=
"@string/settings_su_reauth_summary"
/>
android:summary=
"@string/settings_su_reauth_summary"
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment