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
8647ba47
Commit
8647ba47
authored
Jul 09, 2020
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove more RxJava
parent
4631077c
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
349 additions
and
395 deletions
+349
-395
build.gradle.kts
app/build.gradle.kts
+3
-2
GeneralReceiver.kt
...rc/main/java/com/topjohnwu/magisk/core/GeneralReceiver.kt
+8
-2
UpdateCheckService.kt
...main/java/com/topjohnwu/magisk/core/UpdateCheckService.kt
+14
-12
BaseDao.kt
...c/main/java/com/topjohnwu/magisk/core/magiskdb/BaseDao.kt
+1
-17
PolicyDao.kt
...main/java/com/topjohnwu/magisk/core/magiskdb/PolicyDao.kt
+21
-18
Query.kt
...src/main/java/com/topjohnwu/magisk/core/magiskdb/Query.kt
+24
-0
SettingsDao.kt
...in/java/com/topjohnwu/magisk/core/magiskdb/SettingsDao.kt
+8
-6
StringDao.kt
...main/java/com/topjohnwu/magisk/core/magiskdb/StringDao.kt
+8
-6
SuCallbackHandler.kt
...in/java/com/topjohnwu/magisk/core/su/SuCallbackHandler.kt
+5
-2
SuRequestHandler.kt
...ain/java/com/topjohnwu/magisk/core/su/SuRequestHandler.kt
+2
-2
SuLogDao.kt
.../main/java/com/topjohnwu/magisk/data/database/SuLogDao.kt
+12
-11
GithubServices.kt
.../java/com/topjohnwu/magisk/data/network/GithubServices.kt
+4
-4
DBConfig.kt
...ain/java/com/topjohnwu/magisk/data/repository/DBConfig.kt
+25
-15
LogRepository.kt
...ava/com/topjohnwu/magisk/data/repository/LogRepository.kt
+9
-11
MagiskRepository.kt
.../com/topjohnwu/magisk/data/repository/MagiskRepository.kt
+37
-34
ApplicationModule.kt
...rc/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt
+0
-2
XSU.kt
app/src/main/java/com/topjohnwu/magisk/extensions/XSU.kt
+4
-0
HideTarget.kt
...main/java/com/topjohnwu/magisk/model/entity/HideTarget.kt
+8
-4
BaseViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/base/BaseViewModel.kt
+7
-82
FlashViewModel.kt
...main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt
+16
-17
HideViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt
+15
-13
HomeViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
+39
-38
LogViewModel.kt
...src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
+29
-42
ModuleViewModel.kt
...in/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt
+1
-1
SuperuserViewModel.kt
...a/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt
+48
-53
build.gradle.kts
build.gradle.kts
+1
-1
No files found.
app/build.gradle.kts
View file @
8647ba47
...
@@ -126,7 +126,7 @@ dependencies {
...
@@ -126,7 +126,7 @@ dependencies {
val
vRoom
=
"2.2.5"
val
vRoom
=
"2.2.5"
implementation
(
"androidx.room:room-runtime:${vRoom}"
)
implementation
(
"androidx.room:room-runtime:${vRoom}"
)
implementation
(
"androidx.room:room-
rxjava2
:${vRoom}"
)
implementation
(
"androidx.room:room-
ktx
:${vRoom}"
)
kapt
(
"androidx.room:room-compiler:${vRoom}"
)
kapt
(
"androidx.room:room-compiler:${vRoom}"
)
implementation
(
"androidx.navigation:navigation-fragment-ktx:${Deps.vNav}"
)
implementation
(
"androidx.navigation:navigation-fragment-ktx:${Deps.vNav}"
)
...
@@ -139,9 +139,10 @@ dependencies {
...
@@ -139,9 +139,10 @@ dependencies {
implementation
(
"androidx.preference:preference:1.1.1"
)
implementation
(
"androidx.preference:preference:1.1.1"
)
implementation
(
"androidx.recyclerview:recyclerview:1.1.0"
)
implementation
(
"androidx.recyclerview:recyclerview:1.1.0"
)
implementation
(
"androidx.fragment:fragment-ktx:1.2.5"
)
implementation
(
"androidx.fragment:fragment-ktx:1.2.5"
)
implementation
(
"androidx.work:work-runtime:2.3.4"
)
implementation
(
"androidx.work:work-runtime
-ktx
:2.3.4"
)
implementation
(
"androidx.transition:transition:1.3.1"
)
implementation
(
"androidx.transition:transition:1.3.1"
)
implementation
(
"androidx.multidex:multidex:2.0.1"
)
implementation
(
"androidx.multidex:multidex:2.0.1"
)
implementation
(
"androidx.core:core-ktx:1.3.0"
)
implementation
(
"androidx.core:core-ktx:1.3.0"
)
implementation
(
"androidx.localbroadcastmanager:localbroadcastmanager:1.0.0"
)
implementation
(
"com.google.android.material:material:1.2.0-beta01"
)
implementation
(
"com.google.android.material:material:1.2.0-beta01"
)
}
}
app/src/main/java/com/topjohnwu/magisk/core/GeneralReceiver.kt
View file @
8647ba47
...
@@ -12,6 +12,8 @@ import com.topjohnwu.magisk.extensions.reboot
...
@@ -12,6 +12,8 @@ import com.topjohnwu.magisk.extensions.reboot
import
com.topjohnwu.magisk.model.entity.internal.Configuration
import
com.topjohnwu.magisk.model.entity.internal.Configuration
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
org.koin.core.inject
import
org.koin.core.inject
open
class
GeneralReceiver
:
BaseReceiver
()
{
open
class
GeneralReceiver
:
BaseReceiver
()
{
...
@@ -25,6 +27,10 @@ open class GeneralReceiver : BaseReceiver() {
...
@@ -25,6 +27,10 @@ open class GeneralReceiver : BaseReceiver() {
override
fun
onReceive
(
context
:
ContextWrapper
,
intent
:
Intent
?)
{
override
fun
onReceive
(
context
:
ContextWrapper
,
intent
:
Intent
?)
{
intent
?:
return
intent
?:
return
fun
rmPolicy
(
pkg
:
String
)
=
GlobalScope
.
launch
{
policyDB
.
delete
(
pkg
)
}
when
(
intent
.
action
?:
return
)
{
when
(
intent
.
action
?:
return
)
{
Intent
.
ACTION_REBOOT
->
{
Intent
.
ACTION_REBOOT
->
{
SuCallbackHandler
(
context
,
intent
.
getStringExtra
(
"action"
),
intent
.
extras
)
SuCallbackHandler
(
context
,
intent
.
getStringExtra
(
"action"
),
intent
.
extras
)
...
@@ -32,11 +38,11 @@ open class GeneralReceiver : BaseReceiver() {
...
@@ -32,11 +38,11 @@ open class GeneralReceiver : BaseReceiver() {
Intent
.
ACTION_PACKAGE_REPLACED
->
{
Intent
.
ACTION_PACKAGE_REPLACED
->
{
// This will only work pre-O
// This will only work pre-O
if
(
Config
.
suReAuth
)
if
(
Config
.
suReAuth
)
policyDB
.
delete
(
getPkg
(
intent
)).
blockingGet
(
)
rmPolicy
(
getPkg
(
intent
)
)
}
}
Intent
.
ACTION_PACKAGE_FULLY_REMOVED
->
{
Intent
.
ACTION_PACKAGE_FULLY_REMOVED
->
{
val
pkg
=
getPkg
(
intent
)
val
pkg
=
getPkg
(
intent
)
policyDB
.
delete
(
pkg
).
blockingGet
(
)
rmPolicy
(
pkg
)
Shell
.
su
(
"magiskhide --rm $pkg"
).
submit
()
Shell
.
su
(
"magiskhide --rm $pkg"
).
submit
()
}
}
Intent
.
ACTION_LOCALE_CHANGED
->
Shortcuts
.
setup
(
context
)
Intent
.
ACTION_LOCALE_CHANGED
->
Shortcuts
.
setup
(
context
)
...
...
app/src/main/java/com/topjohnwu/magisk/core/UpdateCheckService.kt
View file @
8647ba47
package
com.topjohnwu.magisk.core
package
com.topjohnwu.magisk.core
import
android.content.Context
import
android.content.Context
import
androidx.work.Worker
import
androidx.work.
Coroutine
Worker
import
androidx.work.WorkerParameters
import
androidx.work.WorkerParameters
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.core.view.Notifications
import
com.topjohnwu.magisk.core.view.Notifications
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.extensions.inject
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
org.koin.core.KoinComponent
import
org.koin.core.inject
class
UpdateCheckService
(
context
:
Context
,
workerParams
:
WorkerParameters
)
class
UpdateCheckService
(
context
:
Context
,
workerParams
:
WorkerParameters
)
:
Worker
(
context
,
workerParams
)
{
:
CoroutineWorker
(
context
,
workerParams
),
KoinComponent
{
private
val
magiskRepo
:
MagiskRepository
by
inject
()
private
val
magiskRepo
:
MagiskRepository
by
inject
()
override
fun
doWork
():
Result
{
override
suspend
fun
doWork
():
Result
{
// Make sure shell initializer was ran
// Make sure shell initializer was ran
Shell
.
getShell
()
withContext
(
Dispatchers
.
IO
)
{
return
runCatching
{
Shell
.
getShell
()
magiskRepo
.
fetchUpdate
().
blockingGet
()
}
if
(
BuildConfig
.
VERSION_CODE
<
Info
.
remote
.
app
.
versionCode
)
return
magiskRepo
.
fetchUpdate
()
?.
let
{
if
(
BuildConfig
.
VERSION_CODE
<
it
.
app
.
versionCode
)
Notifications
.
managerUpdate
(
applicationContext
)
Notifications
.
managerUpdate
(
applicationContext
)
else
if
(
Info
.
env
.
isActive
&&
Info
.
env
.
magiskVersionCode
<
Info
.
remote
.
magisk
.
versionCode
)
else
if
(
Info
.
env
.
isActive
&&
Info
.
env
.
magiskVersionCode
<
it
.
magisk
.
versionCode
)
Notifications
.
magiskUpdate
(
applicationContext
)
Notifications
.
magiskUpdate
(
applicationContext
)
Result
.
success
()
Result
.
success
()
}.
getOrElse
{
}
?:
Result
.
failure
()
Result
.
failure
()
}
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/core/magiskdb/BaseDao.kt
View file @
8647ba47
package
com.topjohnwu.magisk.core.magiskdb
package
com.topjohnwu.magisk.core.magiskdb
import
androidx.annotation.StringDef
import
androidx.annotation.StringDef
import
com.topjohnwu.superuser.Shell
import
io.reactivex.Single
abstract
class
BaseDao
{
abstract
class
BaseDao
{
...
@@ -20,25 +18,11 @@ abstract class BaseDao {
...
@@ -20,25 +18,11 @@ abstract class BaseDao {
@TableStrict
@TableStrict
abstract
val
table
:
String
abstract
val
table
:
String
inline
fun
<
reified
Builder
:
Query
.
Builder
>
q
uery
(
builder
:
Builder
.()
->
Unit
=
{})
=
inline
fun
<
reified
Builder
:
Query
.
Builder
>
buildQ
uery
(
builder
:
Builder
.()
->
Unit
=
{})
=
Builder
::
class
.
java
.
newInstance
()
Builder
::
class
.
java
.
newInstance
()
.
apply
{
table
=
this
@BaseDao
.
table
}
.
apply
{
table
=
this
@BaseDao
.
table
}
.
apply
(
builder
)
.
apply
(
builder
)
.
toString
()
.
toString
()
.
let
{
Query
(
it
)
}
.
let
{
Query
(
it
)
}
.
query
()
}
}
fun
Query
.
query
()
=
query
.
su
()
private
fun
String
.
suRaw
()
=
Single
.
fromCallable
{
Shell
.
su
(
this
).
exec
().
out
}
private
fun
String
.
su
()
=
suRaw
().
map
{
it
.
toMap
()
}
private
fun
List
<
String
>.
toMap
()
=
map
{
it
.
split
(
Regex
(
"\\|"
))
}
.
map
{
it
.
toMapInternal
()
}
private
fun
List
<
String
>.
toMapInternal
()
=
map
{
it
.
split
(
"="
,
limit
=
2
)
}
.
filter
{
it
.
size
==
2
}
.
map
{
Pair
(
it
[
0
],
it
[
1
])
}
.
toMap
()
app/src/main/java/com/topjohnwu/magisk/core/magiskdb/PolicyDao.kt
View file @
8647ba47
...
@@ -7,6 +7,8 @@ import com.topjohnwu.magisk.core.model.MagiskPolicy
...
@@ -7,6 +7,8 @@ import com.topjohnwu.magisk.core.model.MagiskPolicy
import
com.topjohnwu.magisk.core.model.toMap
import
com.topjohnwu.magisk.core.model.toMap
import
com.topjohnwu.magisk.core.model.toPolicy
import
com.topjohnwu.magisk.core.model.toPolicy
import
com.topjohnwu.magisk.extensions.now
import
com.topjohnwu.magisk.extensions.now
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
timber.log.Timber
import
java.util.concurrent.TimeUnit
import
java.util.concurrent.TimeUnit
...
@@ -17,55 +19,56 @@ class PolicyDao(
...
@@ -17,55 +19,56 @@ class PolicyDao(
override
val
table
:
String
=
Table
.
POLICY
override
val
table
:
String
=
Table
.
POLICY
fun
deleteOutdated
(
suspend
fun
deleteOutdated
()
=
buildQuery
<
Delete
>
{
nowSeconds
:
Long
=
TimeUnit
.
MILLISECONDS
.
toSeconds
(
now
)
)
=
query
<
Delete
>
{
condition
{
condition
{
greaterThan
(
"until"
,
"0"
)
greaterThan
(
"until"
,
"0"
)
and
{
and
{
lessThan
(
"until"
,
nowSeconds
.
toString
())
lessThan
(
"until"
,
TimeUnit
.
MILLISECONDS
.
toSeconds
(
now
)
.
toString
())
}
}
or
{
or
{
lessThan
(
"until"
,
"0"
)
lessThan
(
"until"
,
"0"
)
}
}
}
}
}.
ignoreElemen
t
()
}.
commi
t
()
fun
delete
(
packageName
:
String
)
=
q
uery
<
Delete
>
{
suspend
fun
delete
(
packageName
:
String
)
=
buildQ
uery
<
Delete
>
{
condition
{
condition
{
equals
(
"package_name"
,
packageName
)
equals
(
"package_name"
,
packageName
)
}
}
}.
ignoreElemen
t
()
}.
commi
t
()
fun
delete
(
uid
:
Int
)
=
q
uery
<
Delete
>
{
suspend
fun
delete
(
uid
:
Int
)
=
buildQ
uery
<
Delete
>
{
condition
{
condition
{
equals
(
"uid"
,
uid
)
equals
(
"uid"
,
uid
)
}
}
}.
ignoreElemen
t
()
}.
commi
t
()
fun
fetch
(
uid
:
Int
)
=
q
uery
<
Select
>
{
suspend
fun
fetch
(
uid
:
Int
)
=
buildQ
uery
<
Select
>
{
condition
{
condition
{
equals
(
"uid"
,
uid
)
equals
(
"uid"
,
uid
)
}
}
}.
map
{
it
.
first
().
toPolicySafe
()
}
}.
query
().
first
().
toPolicyOrNull
()
fun
update
(
policy
:
MagiskPolicy
)
=
q
uery
<
Replace
>
{
suspend
fun
update
(
policy
:
MagiskPolicy
)
=
buildQ
uery
<
Replace
>
{
values
(
policy
.
toMap
())
values
(
policy
.
toMap
())
}.
ignoreElemen
t
()
}.
commi
t
()
fun
fetchAll
()
=
q
uery
<
Select
>
{
suspend
fun
<
R
:
Any
>
fetchAll
(
mapper
:
(
MagiskPolicy
)
->
R
)
=
buildQ
uery
<
Select
>
{
condition
{
condition
{
equals
(
"uid/100000"
,
Const
.
USER_ID
)
equals
(
"uid/100000"
,
Const
.
USER_ID
)
}
}
}.
map
{
it
.
mapNotNull
{
it
.
toPolicySafe
()
}
}
}.
query
{
it
.
toPolicyOrNull
()
?.
let
(
mapper
)
}
private
fun
Map
<
String
,
String
>.
toPolicy
Safe
():
MagiskPolicy
?
{
private
fun
Map
<
String
,
String
>.
toPolicy
OrNull
():
MagiskPolicy
?
{
return
runCatching
{
toPolicy
(
context
.
packageManager
)
}.
getOrElse
{
return
runCatching
{
toPolicy
(
context
.
packageManager
)
}.
getOrElse
{
Timber
.
e
(
it
)
Timber
.
e
(
it
)
if
(
it
is
PackageManager
.
NameNotFoundException
)
{
if
(
it
is
PackageManager
.
NameNotFoundException
)
{
val
uid
=
getOrElse
(
"uid"
)
{
null
}
?:
return
null
val
uid
=
getOrElse
(
"uid"
)
{
null
}
?:
return
null
delete
(
uid
).
subscribe
()
GlobalScope
.
launch
{
delete
(
uid
.
toInt
())
}
}
}
null
null
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/core/magiskdb/Query.kt
View file @
8647ba47
package
com.topjohnwu.magisk.core.magiskdb
package
com.topjohnwu.magisk.core.magiskdb
import
androidx.annotation.StringDef
import
androidx.annotation.StringDef
import
com.topjohnwu.magisk.extensions.await
import
com.topjohnwu.superuser.Shell
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.async
import
kotlinx.coroutines.awaitAll
import
kotlinx.coroutines.withContext
class
Query
(
private
val
_query
:
String
)
{
class
Query
(
private
val
_query
:
String
)
{
val
query
get
()
=
"magisk --sqlite '$_query'"
val
query
get
()
=
"magisk --sqlite '$_query'"
...
@@ -9,6 +15,24 @@ class Query(private val _query: String) {
...
@@ -9,6 +15,24 @@ class Query(private val _query: String) {
val
requestType
:
String
val
requestType
:
String
var
table
:
String
var
table
:
String
}
}
suspend
inline
fun
<
R
:
Any
>
query
(
crossinline
mapper
:
(
Map
<
String
,
String
>)
->
R
?):
List
<
R
>
=
withContext
(
Dispatchers
.
Default
)
{
Shell
.
su
(
query
).
await
().
out
.
map
{
line
->
async
{
line
.
split
(
"\\|"
.
toRegex
())
.
map
{
it
.
split
(
"="
,
limit
=
2
)
}
.
filter
{
it
.
size
==
2
}
.
map
{
it
[
0
]
to
it
[
1
]
}
.
toMap
()
.
let
(
mapper
)
}
}.
awaitAll
().
filterNotNull
()
}
suspend
inline
fun
query
()
=
query
{
it
}
suspend
inline
fun
commit
()
=
Shell
.
su
(
query
).
to
(
null
).
await
()
}
}
class
Delete
:
Query
.
Builder
{
class
Delete
:
Query
.
Builder
{
...
...
app/src/main/java/com/topjohnwu/magisk/core/magiskdb/SettingsDao.kt
View file @
8647ba47
...
@@ -4,17 +4,19 @@ class SettingsDao : BaseDao() {
...
@@ -4,17 +4,19 @@ class SettingsDao : BaseDao() {
override
val
table
=
Table
.
SETTINGS
override
val
table
=
Table
.
SETTINGS
fun
delete
(
key
:
String
)
=
q
uery
<
Delete
>
{
suspend
fun
delete
(
key
:
String
)
=
buildQ
uery
<
Delete
>
{
condition
{
equals
(
"key"
,
key
)
}
condition
{
equals
(
"key"
,
key
)
}
}.
ignoreElemen
t
()
}.
commi
t
()
fun
put
(
key
:
String
,
value
:
Int
)
=
q
uery
<
Replace
>
{
suspend
fun
put
(
key
:
String
,
value
:
Int
)
=
buildQ
uery
<
Replace
>
{
values
(
"key"
to
key
,
"value"
to
value
)
values
(
"key"
to
key
,
"value"
to
value
)
}.
ignoreElemen
t
()
}.
commi
t
()
fun
fetch
(
key
:
String
,
default
:
Int
=
-
1
)
=
q
uery
<
Select
>
{
suspend
fun
fetch
(
key
:
String
,
default
:
Int
=
-
1
)
=
buildQ
uery
<
Select
>
{
fields
(
"value"
)
fields
(
"value"
)
condition
{
equals
(
"key"
,
key
)
}
condition
{
equals
(
"key"
,
key
)
}
}.
map
{
it
.
firstOrNull
()
?.
values
?.
firstOrNull
()
?.
toIntOrNull
()
?:
default
}
}.
query
{
it
[
"value"
]
?.
toIntOrNull
()
}.
firstOrNull
()
?:
default
}
}
app/src/main/java/com/topjohnwu/magisk/core/magiskdb/StringDao.kt
View file @
8647ba47
...
@@ -4,17 +4,19 @@ class StringDao : BaseDao() {
...
@@ -4,17 +4,19 @@ class StringDao : BaseDao() {
override
val
table
=
Table
.
STRINGS
override
val
table
=
Table
.
STRINGS
fun
delete
(
key
:
String
)
=
q
uery
<
Delete
>
{
suspend
fun
delete
(
key
:
String
)
=
buildQ
uery
<
Delete
>
{
condition
{
equals
(
"key"
,
key
)
}
condition
{
equals
(
"key"
,
key
)
}
}.
ignoreElemen
t
()
}.
commi
t
()
fun
put
(
key
:
String
,
value
:
String
)
=
q
uery
<
Replace
>
{
suspend
fun
put
(
key
:
String
,
value
:
String
)
=
buildQ
uery
<
Replace
>
{
values
(
"key"
to
key
,
"value"
to
value
)
values
(
"key"
to
key
,
"value"
to
value
)
}.
ignoreElemen
t
()
}.
commi
t
()
fun
fetch
(
key
:
String
,
default
:
String
=
""
)
=
q
uery
<
Select
>
{
suspend
fun
fetch
(
key
:
String
,
default
:
String
=
""
)
=
buildQ
uery
<
Select
>
{
fields
(
"value"
)
fields
(
"value"
)
condition
{
equals
(
"key"
,
key
)
}
condition
{
equals
(
"key"
,
key
)
}
}.
map
{
it
.
firstOrNull
()
?.
values
?.
firstOrNull
()
?:
default
}
}.
query
{
it
[
"value"
]
}.
firstOrNull
()
?:
default
}
}
app/src/main/java/com/topjohnwu/magisk/core/su/SuCallbackHandler.kt
View file @
8647ba47
...
@@ -19,10 +19,11 @@ import com.topjohnwu.magisk.data.repository.LogRepository
...
@@ -19,10 +19,11 @@ import com.topjohnwu.magisk.data.repository.LogRepository
import
com.topjohnwu.magisk.extensions.get
import
com.topjohnwu.magisk.extensions.get
import
com.topjohnwu.magisk.extensions.startActivity
import
com.topjohnwu.magisk.extensions.startActivity
import
com.topjohnwu.magisk.extensions.startActivityWithRoot
import
com.topjohnwu.magisk.extensions.startActivityWithRoot
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.model.entity.toLog
import
com.topjohnwu.magisk.model.entity.toLog
import
com.topjohnwu.magisk.ui.surequest.SuRequestActivity
import
com.topjohnwu.magisk.ui.surequest.SuRequestActivity
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
timber.log.Timber
object
SuCallbackHandler
:
ProviderCallHandler
{
object
SuCallbackHandler
:
ProviderCallHandler
{
...
@@ -111,7 +112,9 @@ object SuCallbackHandler : ProviderCallHandler {
...
@@ -111,7 +112,9 @@ object SuCallbackHandler : ProviderCallHandler {
)
)
val
logRepo
=
get
<
LogRepository
>()
val
logRepo
=
get
<
LogRepository
>()
logRepo
.
insert
(
log
).
subscribeK
(
onError
=
{
Timber
.
e
(
it
)
})
GlobalScope
.
launch
{
logRepo
.
insert
(
log
)
}
}
}
private
fun
handleNotify
(
context
:
Context
,
data
:
Bundle
)
{
private
fun
handleNotify
(
context
:
Context
,
data
:
Bundle
)
{
...
...
app/src/main/java/com/topjohnwu/magisk/core/su/SuRequestHandler.kt
View file @
8647ba47
...
@@ -111,13 +111,13 @@ abstract class SuRequestHandler(
...
@@ -111,13 +111,13 @@ abstract class SuRequestHandler(
}
catch
(
e
:
IOException
)
{
}
catch
(
e
:
IOException
)
{
Timber
.
e
(
e
)
Timber
.
e
(
e
)
}
finally
{
}
finally
{
if
(
until
>=
0
)
policyDB
.
update
(
policy
).
blockingAwait
()
runCatching
{
runCatching
{
input
.
close
()
input
.
close
()
output
.
close
()
output
.
close
()
socket
.
close
()
socket
.
close
()
}
}
if
(
until
>=
0
)
policyDB
.
update
(
policy
)
}
}
}
}
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/data/database/SuLogDao.kt
View file @
8647ba47
...
@@ -2,8 +2,8 @@ package com.topjohnwu.magisk.data.database
...
@@ -2,8 +2,8 @@ package com.topjohnwu.magisk.data.database
import
androidx.room.*
import
androidx.room.*
import
com.topjohnwu.magisk.model.entity.MagiskLog
import
com.topjohnwu.magisk.model.entity.MagiskLog
import
io.reactivex.Completable
import
kotlinx.coroutines.Dispatchers
import
io.reactivex.Single
import
kotlinx.coroutines.withContext
import
java.util.*
import
java.util.*
@Database
(
version
=
1
,
entities
=
[
MagiskLog
::
class
],
exportSchema
=
false
)
@Database
(
version
=
1
,
entities
=
[
MagiskLog
::
class
],
exportSchema
=
false
)
...
@@ -18,19 +18,20 @@ abstract class SuLogDao(private val db: SuLogDatabase) {
...
@@ -18,19 +18,20 @@ abstract class SuLogDao(private val db: SuLogDatabase) {
private
val
twoWeeksAgo
=
private
val
twoWeeksAgo
=
Calendar
.
getInstance
().
apply
{
add
(
Calendar
.
WEEK_OF_YEAR
,
-
2
)
}.
timeInMillis
Calendar
.
getInstance
().
apply
{
add
(
Calendar
.
WEEK_OF_YEAR
,
-
2
)
}.
timeInMillis
fun
deleteAll
()
=
Completable
.
fromAction
{
db
.
clearAllTables
()
}
suspend
fun
deleteAll
()
=
withContext
(
Dispatchers
.
IO
)
{
db
.
clearAllTables
()
}
fun
fetchAll
()
=
deleteOutdated
().
andThen
(
fetch
())
suspend
fun
fetchAll
():
MutableList
<
MagiskLog
>
{
deleteOutdated
()
return
fetch
()
}
@Query
(
"SELECT * FROM logs ORDER BY time DESC"
)
@Query
(
"SELECT * FROM logs ORDER BY time DESC"
)
protected
abstract
fun
fetch
():
Single
<
MutableList
<
MagiskLog
>>
protected
abstract
suspend
fun
fetch
():
MutableList
<
MagiskLog
>
@Insert
abstract
fun
insert
(
log
:
MagiskLog
):
Completable
@Query
(
"DELETE FROM logs WHERE time < :timeout"
)
@Query
(
"DELETE FROM logs WHERE time < :timeout"
)
protected
abstract
fun
deleteOutdated
(
protected
abstract
suspend
fun
deleteOutdated
(
timeout
:
Long
=
twoWeeksAgo
)
timeout
:
Long
=
twoWeeksAgo
):
Completable
@Insert
abstract
suspend
fun
insert
(
log
:
MagiskLog
)
}
}
app/src/main/java/com/topjohnwu/magisk/data/network/GithubServices.kt
View file @
8647ba47
...
@@ -13,16 +13,16 @@ interface GithubRawServices {
...
@@ -13,16 +13,16 @@ interface GithubRawServices {
//region topjohnwu/magisk_files
//region topjohnwu/magisk_files
@GET
(
"$MAGISK_FILES/master/stable.json"
)
@GET
(
"$MAGISK_FILES/master/stable.json"
)
fun
fetchStableUpdate
():
Single
<
UpdateInfo
>
suspend
fun
fetchStableUpdate
():
UpdateInfo
@GET
(
"$MAGISK_FILES/master/beta.json"
)
@GET
(
"$MAGISK_FILES/master/beta.json"
)
fun
fetchBetaUpdate
():
Single
<
UpdateInfo
>
suspend
fun
fetchBetaUpdate
():
UpdateInfo
@GET
(
"$MAGISK_FILES/canary/debug.json"
)
@GET
(
"$MAGISK_FILES/canary/debug.json"
)
fun
fetchCanaryUpdate
():
Single
<
UpdateInfo
>
suspend
fun
fetchCanaryUpdate
():
UpdateInfo
@GET
@GET
fun
fetchCustomUpdate
(
@Url
url
:
String
):
Single
<
UpdateInfo
>
suspend
fun
fetchCustomUpdate
(
@Url
url
:
String
):
UpdateInfo
@GET
(
"$MAGISK_FILES/{$REVISION}/snet.jar"
)
@GET
(
"$MAGISK_FILES/{$REVISION}/snet.jar"
)
@Streaming
@Streaming
...
...
app/src/main/java/com/topjohnwu/magisk/data/repository/DBConfig.kt
View file @
8647ba47
...
@@ -2,7 +2,9 @@ package com.topjohnwu.magisk.data.repository
...
@@ -2,7 +2,9 @@ package com.topjohnwu.magisk.data.repository
import
com.topjohnwu.magisk.core.magiskdb.SettingsDao
import
com.topjohnwu.magisk.core.magiskdb.SettingsDao
import
com.topjohnwu.magisk.core.magiskdb.StringDao
import
com.topjohnwu.magisk.core.magiskdb.StringDao
import
io.reactivex.schedulers.Schedulers
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.runBlocking
import
kotlin.properties.ReadWriteProperty
import
kotlin.properties.ReadWriteProperty
import
kotlin.reflect.KProperty
import
kotlin.reflect.KProperty
...
@@ -38,17 +40,19 @@ class DBSettingsValue(
...
@@ -38,17 +40,19 @@ class DBSettingsValue(
@Synchronized
@Synchronized
override
fun
getValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>):
Int
{
override
fun
getValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>):
Int
{
if
(
value
==
null
)
if
(
value
==
null
)
value
=
thisRef
.
settingsDao
.
fetch
(
name
,
default
).
blockingGet
()
value
=
runBlocking
{
return
value
!!
thisRef
.
settingsDao
.
fetch
(
name
,
default
)
}
return
value
as
Int
}
}
override
fun
setValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>,
value
:
Int
)
{
override
fun
setValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>,
value
:
Int
)
{
synchronized
(
this
)
{
synchronized
(
this
)
{
this
.
value
=
value
this
.
value
=
value
}
}
thisRef
.
settingsDao
.
put
(
name
,
value
)
GlobalScope
.
launch
{
.
subscribeOn
(
Schedulers
.
io
()
)
thisRef
.
settingsDao
.
put
(
name
,
value
)
.
subscribe
()
}
}
}
}
}
...
@@ -77,7 +81,9 @@ class DBStringsValue(
...
@@ -77,7 +81,9 @@ class DBStringsValue(
@Synchronized
@Synchronized
override
fun
getValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>):
String
{
override
fun
getValue
(
thisRef
:
DBConfig
,
property
:
KProperty
<
*
>):
String
{
if
(
value
==
null
)
if
(
value
==
null
)
value
=
thisRef
.
stringDao
.
fetch
(
name
,
default
).
blockingGet
()
value
=
runBlocking
{
thisRef
.
stringDao
.
fetch
(
name
,
default
)
}
return
value
!!
return
value
!!
}
}
...
@@ -87,19 +93,23 @@ class DBStringsValue(
...
@@ -87,19 +93,23 @@ class DBStringsValue(
}
}
if
(
value
.
isEmpty
())
{
if
(
value
.
isEmpty
())
{
if
(
sync
)
{
if
(
sync
)
{
thisRef
.
stringDao
.
delete
(
name
).
blockingAwait
()
runBlocking
{
thisRef
.
stringDao
.
delete
(
name
)
}
}
else
{
}
else
{
thisRef
.
stringDao
.
delete
(
name
)
GlobalScope
.
launch
{
.
subscribeOn
(
Schedulers
.
io
()
)
thisRef
.
stringDao
.
delete
(
name
)
.
subscribe
()
}
}
}
}
else
{
}
else
{
if
(
sync
)
{
if
(
sync
)
{
thisRef
.
stringDao
.
put
(
name
,
value
).
blockingAwait
()
runBlocking
{
thisRef
.
stringDao
.
put
(
name
,
value
)
}
}
else
{
}
else
{
thisRef
.
stringDao
.
put
(
name
,
value
)
GlobalScope
.
launch
{
.
subscribeOn
(
Schedulers
.
io
()
)
thisRef
.
stringDao
.
put
(
name
,
value
)
.
subscribe
()
}
}
}
}
}
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/data/repository/LogRepository.kt
View file @
8647ba47
...
@@ -2,19 +2,18 @@ package com.topjohnwu.magisk.data.repository
...
@@ -2,19 +2,18 @@ package com.topjohnwu.magisk.data.repository
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.data.database.SuLogDao
import
com.topjohnwu.magisk.data.database.SuLogDao
import
com.topjohnwu.magisk.extensions.await
import
com.topjohnwu.magisk.model.entity.MagiskLog
import
com.topjohnwu.magisk.model.entity.MagiskLog
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
io.reactivex.Completable
import
io.reactivex.Single
class
LogRepository
(
class
LogRepository
(
private
val
logDao
:
SuLogDao
private
val
logDao
:
SuLogDao
)
{
)
{
fun
fetch
Logs
()
=
logDao
.
fetchAll
()
suspend
fun
fetchSu
Logs
()
=
logDao
.
fetchAll
()
fun
fetchMagiskLogs
()
=
Single
.
fromCallable
{
suspend
fun
fetchMagiskLogs
():
String
{
val
list
=
object
:
AbstractMutableList
<
String
>()
{
val
list
=
object
:
AbstractMutableList
<
String
>()
{
val
buf
=
StringBuilder
()
val
buf
=
StringBuilder
()
override
val
size
get
()
=
0
override
val
size
get
()
=
0
...
@@ -28,16 +27,15 @@ class LogRepository(
...
@@ -28,16 +27,15 @@ class LogRepository(
}
}
}
}
}
}
Shell
.
su
(
"cat ${Const.MAGISK_LOG}"
).
to
(
list
).
exec
()
Shell
.
su
(
"cat ${Const.MAGISK_LOG}"
).
to
(
list
).
await
()
list
.
buf
.
toString
()
return
list
.
buf
.
toString
()
}
}
fun
clearLogs
()
=
logDao
.
deleteAll
()
suspend
fun
clearLogs
()
=
logDao
.
deleteAll
()
fun
clearMagiskLogs
()
=
Completable
.
fromAction
{
fun
clearMagiskLogs
(
cb
:
(
Shell
.
Result
)
->
Unit
)
=
Shell
.
su
(
"echo -n > ${Const.MAGISK_LOG}"
).
exec
()
Shell
.
su
(
"echo -n > ${Const.MAGISK_LOG}"
).
submit
(
cb
)
}
fun
insert
(
log
:
MagiskLog
)
=
logDao
.
insert
(
log
)
suspend
fun
insert
(
log
:
MagiskLog
)
=
logDao
.
insert
(
log
)
}
}
app/src/main/java/com/topjohnwu/magisk/data/repository/MagiskRepository.kt
View file @
8647ba47
...
@@ -4,55 +4,58 @@ import android.content.pm.PackageManager
...
@@ -4,55 +4,58 @@ import android.content.pm.PackageManager
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.data.network.GithubRawServices
import
com.topjohnwu.magisk.data.network.GithubRawServices
import
com.topjohnwu.magisk.extensions.await
import
com.topjohnwu.magisk.extensions.getLabel
import
com.topjohnwu.magisk.extensions.getLabel
import
com.topjohnwu.magisk.extensions.packageName
import
com.topjohnwu.magisk.extensions.packageName
import
com.topjohnwu.magisk.extensions.toSingle
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.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
io.reactivex.Single
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
timber.log.Timber
import
java.io.IOException
class
MagiskRepository
(
class
MagiskRepository
(
private
val
apiRaw
:
GithubRawServices
,
private
val
apiRaw
:
GithubRawServices
,
private
val
packageManager
:
PackageManager
private
val
packageManager
:
PackageManager
)
{
)
{
fun
fetchSafetynet
()
=
apiRaw
.
fetchSafetynet
()
fun
fetchSafetynet
()
=
apiRaw
.
fetchSafetynet
()
fun
fetchUpdate
()
=
when
(
Config
.
updateChannel
)
{
suspend
fun
fetchUpdate
()
=
try
{
Config
.
Value
.
DEFAULT_CHANNEL
,
Config
.
Value
.
STABLE_CHANNEL
->
apiRaw
.
fetchStableUpdate
()
var
info
=
when
(
Config
.
updateChannel
)
{
Config
.
Value
.
BETA_CHANNEL
->
apiRaw
.
fetchBeta
Update
()
Config
.
Value
.
DEFAULT_CHANNEL
,
Config
.
Value
.
STABLE_CHANNEL
->
apiRaw
.
fetchStable
Update
()
Config
.
Value
.
CANARY_CHANNEL
->
apiRaw
.
fetchCanary
Update
()
Config
.
Value
.
BETA_CHANNEL
->
apiRaw
.
fetchBeta
Update
()
Config
.
Value
.
CUSTOM_CHANNEL
->
apiRaw
.
fetchCustomUpdate
(
Config
.
customChannelUrl
)
Config
.
Value
.
CANARY_CHANNEL
->
apiRaw
.
fetchCanaryUpdate
(
)
else
->
throw
IllegalArgumentException
(
)
Config
.
Value
.
CUSTOM_CHANNEL
->
apiRaw
.
fetchCustomUpdate
(
Config
.
customChannelUrl
)
}.
flatMap
{
else
->
throw
IllegalArgumentException
()
// If remote version is lower than current installed, try switching to beta
}
if
(
i
t
.
magisk
.
versionCode
<
Info
.
env
.
magiskVersionCode
if
(
i
nfo
.
magisk
.
versionCode
<
Info
.
env
.
magiskVersionCode
&&
&&
Config
.
updateChannel
==
Config
.
Value
.
DEFAULT_CHANNEL
)
{
Config
.
updateChannel
==
Config
.
Value
.
DEFAULT_CHANNEL
)
{
Config
.
updateChannel
=
Config
.
Value
.
BETA_CHANNEL
Config
.
updateChannel
=
Config
.
Value
.
BETA_CHANNEL
apiRaw
.
fetchBetaUpdate
()
info
=
apiRaw
.
fetchBetaUpdate
()
}
else
{
Single
.
just
(
it
)
}
}
}.
doOnSuccess
{
Info
.
remote
=
it
}
Info
.
remote
=
info
info
}
catch
(
e
:
IOException
)
{
Timber
.
e
(
e
)
null
}
fun
fetchApps
()
=
suspend
fun
fetchApps
()
=
withContext
(
Dispatchers
.
Default
)
{
Single
.
fromCallable
{
packageManager
.
getInstalledApplications
(
0
)
}
packageManager
.
getInstalledApplications
(
0
).
filter
{
.
flattenAsFlowable
{
it
}
it
.
enabled
&&
!
blacklist
.
contains
(
it
.
packageName
)
.
filter
{
it
.
enabled
&&
!
blacklist
.
contains
(
it
.
packageName
)
}
}.
map
{
.
map
{
val
label
=
it
.
getLabel
(
packageManager
)
val
label
=
it
.
getLabel
(
packageManager
)
val
icon
=
it
.
loadIcon
(
packageManager
)
val
icon
=
it
.
loadIcon
(
packageManager
)
HideAppInfo
(
it
,
label
,
icon
)
HideAppInfo
(
it
,
label
,
icon
)
}.
filter
{
it
.
processes
.
isNotEmpty
()
}
}
}
.
filter
{
it
.
processes
.
isNotEmpty
()
}
.
toList
()
fun
fetchHideTargets
()
=
Shell
.
su
(
"magiskhide --ls"
).
toSingle
()
suspend
fun
fetchHideTargets
()
=
.
map
{
it
.
exec
().
out
}
Shell
.
su
(
"\"magiskhide --ls\""
).
await
().
out
.
map
{
.
flattenAsFlowable
{
it
}
HideTarget
(
it
)
.
map
{
HideTarget
(
it
)
}
}
.
toList
()
fun
toggleHide
(
isEnabled
:
Boolean
,
packageName
:
String
,
process
:
String
)
=
fun
toggleHide
(
isEnabled
:
Boolean
,
packageName
:
String
,
process
:
String
)
=
Shell
.
su
(
"magiskhide --${isEnabled.state} $packageName $process"
).
submit
()
Shell
.
su
(
"magiskhide --${isEnabled.state} $packageName $process"
).
submit
()
...
...
app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt
View file @
8647ba47
...
@@ -2,7 +2,6 @@ package com.topjohnwu.magisk.di
...
@@ -2,7 +2,6 @@ package com.topjohnwu.magisk.di
import
android.content.Context
import
android.content.Context
import
android.os.Build
import
android.os.Build
import
androidx.localbroadcastmanager.content.LocalBroadcastManager
import
androidx.preference.PreferenceManager
import
androidx.preference.PreferenceManager
import
com.topjohnwu.magisk.core.ResMgr
import
com.topjohnwu.magisk.core.ResMgr
import
com.topjohnwu.magisk.utils.RxBus
import
com.topjohnwu.magisk.utils.RxBus
...
@@ -19,7 +18,6 @@ val applicationModule = module {
...
@@ -19,7 +18,6 @@ val applicationModule = module {
factory
(
Protected
)
{
createDEContext
(
get
())
}
factory
(
Protected
)
{
createDEContext
(
get
())
}
single
(
SUTimeout
)
{
get
<
Context
>(
Protected
).
getSharedPreferences
(
"su_timeout"
,
0
)
}
single
(
SUTimeout
)
{
get
<
Context
>(
Protected
).
getSharedPreferences
(
"su_timeout"
,
0
)
}
single
{
PreferenceManager
.
getDefaultSharedPreferences
(
get
<
Context
>(
Protected
))
}
single
{
PreferenceManager
.
getDefaultSharedPreferences
(
get
<
Context
>(
Protected
))
}
single
{
LocalBroadcastManager
.
getInstance
(
get
())
}
}
}
private
fun
createDEContext
(
context
:
Context
):
Context
{
private
fun
createDEContext
(
context
:
Context
):
Context
{
...
...
app/src/main/java/com/topjohnwu/magisk/extensions/XSU.kt
View file @
8647ba47
...
@@ -4,6 +4,8 @@ import com.topjohnwu.magisk.core.Info
...
@@ -4,6 +4,8 @@ import com.topjohnwu.magisk.core.Info
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.io.SuFileInputStream
import
com.topjohnwu.superuser.io.SuFileInputStream
import
com.topjohnwu.superuser.io.SuFileOutputStream
import
com.topjohnwu.superuser.io.SuFileOutputStream
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
java.io.File
import
java.io.File
fun
reboot
(
reason
:
String
=
if
(
Info
.
recovery
)
"recovery"
else
""
)
{
fun
reboot
(
reason
:
String
=
if
(
Info
.
recovery
)
"recovery"
else
""
)
{
...
@@ -14,3 +16,5 @@ fun File.suOutputStream() = SuFileOutputStream(this)
...
@@ -14,3 +16,5 @@ fun File.suOutputStream() = SuFileOutputStream(this)
fun
File
.
suInputStream
()
=
SuFileInputStream
(
this
)
fun
File
.
suInputStream
()
=
SuFileInputStream
(
this
)
val
hasRoot
get
()
=
Shell
.
rootAccess
()
val
hasRoot
get
()
=
Shell
.
rootAccess
()
suspend
fun
Shell
.
Job
.
await
()
=
withContext
(
Dispatchers
.
IO
)
{
exec
()
}
app/src/main/java/com/topjohnwu/magisk/model/entity/HideTarget.kt
View file @
8647ba47
...
@@ -2,9 +2,13 @@ package com.topjohnwu.magisk.model.entity
...
@@ -2,9 +2,13 @@ package com.topjohnwu.magisk.model.entity
class
HideTarget
(
line
:
String
)
{
class
HideTarget
(
line
:
String
)
{
private
val
split
=
line
.
split
(
Regex
(
"\\|"
),
2
)
val
packageName
:
String
val
process
:
String
val
packageName
=
split
[
0
]
init
{
val
process
=
split
.
getOrElse
(
1
)
{
packageName
}
val
split
=
line
.
split
(
Regex
(
"\\|"
),
2
)
packageName
=
split
[
0
]
process
=
split
.
getOrElse
(
1
)
{
packageName
}
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/ui/base/BaseViewModel.kt
View file @
8647ba47
...
@@ -4,6 +4,7 @@ import android.Manifest
...
@@ -4,6 +4,7 @@ import android.Manifest
import
androidx.annotation.CallSuper
import
androidx.annotation.CallSuper
import
androidx.core.graphics.Insets
import
androidx.core.graphics.Insets
import
androidx.databinding.Bindable
import
androidx.databinding.Bindable
import
androidx.databinding.Observable
import
androidx.databinding.ObservableField
import
androidx.databinding.ObservableField
import
androidx.databinding.PropertyChangeRegistry
import
androidx.databinding.PropertyChangeRegistry
import
androidx.lifecycle.LiveData
import
androidx.lifecycle.LiveData
...
@@ -13,23 +14,18 @@ import androidx.navigation.NavDirections
...
@@ -13,23 +14,18 @@ import androidx.navigation.NavDirections
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.base.BaseActivity
import
com.topjohnwu.magisk.core.base.BaseActivity
import
com.topjohnwu.magisk.extensions.doOnSubscribeUi
import
com.topjohnwu.magisk.extensions.value
import
com.topjohnwu.magisk.extensions.value
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.model.navigation.NavigationWrapper
import
com.topjohnwu.magisk.model.navigation.NavigationWrapper
import
com.topjohnwu.magisk.model.observer.Observer
import
com.topjohnwu.magisk.model.observer.Observer
import
io.reactivex.*
import
io.reactivex.disposables.CompositeDisposable
import
io.reactivex.disposables.CompositeDisposable
import
io.reactivex.disposables.Disposable
import
io.reactivex.disposables.Disposable
import
io.reactivex.subjects.PublishSubject
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.Job
import
org.koin.core.KoinComponent
import
org.koin.core.KoinComponent
import
androidx.databinding.Observable
as
BindingObservable
abstract
class
BaseViewModel
(
abstract
class
BaseViewModel
(
initialState
:
State
=
State
.
LOADING
,
initialState
:
State
=
State
.
LOADING
val
useRx
:
Boolean
=
true
)
:
ViewModel
(),
Observable
,
KoinComponent
{
)
:
ViewModel
(),
BindingObservable
,
KoinComponent
{
enum
class
State
{
enum
class
State
{
LOADED
,
LOADING
,
LOADING_FAILED
LOADED
,
LOADING
,
LOADING_FAILED
...
@@ -53,8 +49,8 @@ abstract class BaseViewModel(
...
@@ -53,8 +49,8 @@ abstract class BaseViewModel(
private
val
_viewEvents
=
MutableLiveData
<
ViewEvent
>()
private
val
_viewEvents
=
MutableLiveData
<
ViewEvent
>()
private
var
runningTask
:
Disposable
?
=
null
private
var
runningTask
:
Disposable
?
=
null
private
var
runningJob
:
Job
?
=
null
private
var
runningJob
:
Job
?
=
null
private
val
refreshCallback
=
object
:
androidx
.
databinding
.
Observable
.
OnPropertyChangedCallback
()
{
private
val
refreshCallback
=
object
:
Observable
.
OnPropertyChangedCallback
()
{
override
fun
onPropertyChanged
(
sender
:
androidx
.
databinding
.
Observable
?,
propertyId
:
Int
)
{
override
fun
onPropertyChanged
(
sender
:
Observable
?,
propertyId
:
Int
)
{
requestRefresh
()
requestRefresh
()
}
}
}
}
...
@@ -66,13 +62,6 @@ abstract class BaseViewModel(
...
@@ -66,13 +62,6 @@ abstract class BaseViewModel(
/** This should probably never be called manually, it's called manually via delegate. */
/** This should probably never be called manually, it's called manually via delegate. */
@Synchronized
@Synchronized
fun
requestRefresh
()
{
fun
requestRefresh
()
{
if
(
useRx
)
{
if
(
runningTask
?.
isDisposed
?.
not
()
==
true
)
{
return
}
runningTask
=
rxRefresh
()
return
}
if
(
runningJob
?.
isActive
==
true
)
{
if
(
runningJob
?.
isActive
==
true
)
{
return
return
}
}
...
@@ -100,11 +89,6 @@ abstract class BaseViewModel(
...
@@ -100,11 +89,6 @@ abstract class BaseViewModel(
ViewActionEvent
(
action
).
publish
()
ViewActionEvent
(
action
).
publish
()
}
}
fun
withPermissions
(
vararg
permissions
:
String
):
Observable
<
Boolean
>
{
val
subject
=
PublishSubject
.
create
<
Boolean
>()
return
subject
.
doOnSubscribeUi
{
RxPermissionEvent
(
permissions
.
toList
(),
subject
).
publish
()
}
}
fun
withPermissions
(
vararg
permissions
:
String
,
callback
:
(
Boolean
)
->
Unit
)
{
fun
withPermissions
(
vararg
permissions
:
String
,
callback
:
(
Boolean
)
->
Unit
)
{
PermissionEvent
(
permissions
.
toList
(),
callback
).
publish
()
PermissionEvent
(
permissions
.
toList
(),
callback
).
publish
()
}
}
...
@@ -137,7 +121,7 @@ abstract class BaseViewModel(
...
@@ -137,7 +121,7 @@ abstract class BaseViewModel(
private
var
callbacks
:
PropertyChangeRegistry
?
=
null
private
var
callbacks
:
PropertyChangeRegistry
?
=
null
@Synchronized
@Synchronized
override
fun
addOnPropertyChangedCallback
(
callback
:
Binding
Observable
.
OnPropertyChangedCallback
)
{
override
fun
addOnPropertyChangedCallback
(
callback
:
Observable
.
OnPropertyChangedCallback
)
{
if
(
callbacks
==
null
)
{
if
(
callbacks
==
null
)
{
callbacks
=
PropertyChangeRegistry
()
callbacks
=
PropertyChangeRegistry
()
}
}
...
@@ -145,7 +129,7 @@ abstract class BaseViewModel(
...
@@ -145,7 +129,7 @@ abstract class BaseViewModel(
}
}
@Synchronized
@Synchronized
override
fun
removeOnPropertyChangedCallback
(
callback
:
Binding
Observable
.
OnPropertyChangedCallback
)
{
override
fun
removeOnPropertyChangedCallback
(
callback
:
Observable
.
OnPropertyChangedCallback
)
{
callbacks
?.
remove
(
callback
)
callbacks
?.
remove
(
callback
)
}
}
...
@@ -168,63 +152,4 @@ abstract class BaseViewModel(
...
@@ -168,63 +152,4 @@ abstract class BaseViewModel(
callbacks
?.
notifyCallbacks
(
this
,
fieldId
,
null
)
callbacks
?.
notifyCallbacks
(
this
,
fieldId
,
null
)
}
}
//region Rx
protected
fun
<
T
>
Observable
<
T
>.
applyViewModel
(
viewModel
:
BaseViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnNext
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
protected
fun
<
T
>
Single
<
T
>.
applyViewModel
(
viewModel
:
BaseViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnSuccess
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
protected
fun
<
T
>
Maybe
<
T
>.
applyViewModel
(
viewModel
:
BaseViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnComplete
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
.
doOnSuccess
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
protected
fun
<
T
>
Flowable
<
T
>.
applyViewModel
(
viewModel
:
BaseViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnNext
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
protected
fun
Completable
.
applyViewModel
(
viewModel
:
BaseViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnComplete
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
//endregion
}
}
app/src/main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt
View file @
8647ba47
package
com.topjohnwu.magisk.ui.flash
package
com.topjohnwu.magisk.ui.flash
import
android.Manifest
import
android.content.res.Resources
import
android.content.res.Resources
import
android.net.Uri
import
android.net.Uri
import
android.view.MenuItem
import
android.view.MenuItem
...
@@ -21,7 +20,9 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
...
@@ -21,7 +20,9 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
import
com.topjohnwu.magisk.ui.base.diffListOf
import
com.topjohnwu.magisk.ui.base.diffListOf
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
java.io.File
import
java.io.File
import
java.util.*
import
java.util.*
...
@@ -96,25 +97,23 @@ class FlashViewModel(
...
@@ -96,25 +97,23 @@ class FlashViewModel(
return
true
return
true
}
}
private
fun
savePressed
()
=
withPermissions
(
private
fun
savePressed
()
=
withExternalRW
{
Manifest
.
permission
.
READ_EXTERNAL_STORAGE
,
if
(!
it
)
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
return
@withExternalRW
)
viewModelScope
.
launch
{
.
map
{
now
}
val
name
=
Const
.
MAGISK_INSTALL_LOG_FILENAME
.
format
(
now
.
toTime
(
timeFormatStandard
))
.
map
{
it
.
toTime
(
timeFormatStandard
)
}
val
file
=
File
(
Config
.
downloadDirectory
,
name
)
.
map
{
Const
.
MAGISK_INSTALL_LOG_FILENAME
.
format
(
it
)
}
withContext
(
Dispatchers
.
IO
)
{
.
map
{
File
(
Config
.
downloadDirectory
,
it
)
}
file
.
bufferedWriter
().
use
{
writer
->
.
map
{
file
->
logItems
.
forEach
{
file
.
bufferedWriter
().
use
{
writer
->
writer
.
write
(
it
)
logItems
.
forEach
{
writer
.
newLine
()
writer
.
write
(
it
)
}
writer
.
newLine
()
}
}
}
}
file
.
path
SnackbarEvent
(
file
.
path
).
publish
()
}
}
.
subscribeK
{
SnackbarEvent
(
it
).
publish
()
}
}
.
add
()
fun
restartPressed
()
=
reboot
()
fun
restartPressed
()
=
reboot
()
}
}
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt
View file @
8647ba47
...
@@ -3,10 +3,10 @@ package com.topjohnwu.magisk.ui.hide
...
@@ -3,10 +3,10 @@ package com.topjohnwu.magisk.ui.hide
import
android.content.pm.ApplicationInfo
import
android.content.pm.ApplicationInfo
import
androidx.databinding.Bindable
import
androidx.databinding.Bindable
import
androidx.databinding.ObservableField
import
androidx.databinding.ObservableField
import
androidx.lifecycle.viewModelScope
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.core.utils.currentLocale
import
com.topjohnwu.magisk.core.utils.currentLocale
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.value
import
com.topjohnwu.magisk.extensions.value
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
...
@@ -18,6 +18,9 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
...
@@ -18,6 +18,9 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
import
com.topjohnwu.magisk.ui.base.Queryable
import
com.topjohnwu.magisk.ui.base.Queryable
import
com.topjohnwu.magisk.ui.base.filterableListOf
import
com.topjohnwu.magisk.ui.base.filterableListOf
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
class
HideViewModel
(
class
HideViewModel
(
private
val
magiskRepo
:
MagiskRepository
private
val
magiskRepo
:
MagiskRepository
...
@@ -50,19 +53,18 @@ class HideViewModel(
...
@@ -50,19 +53,18 @@ class HideViewModel(
val
isFilterExpanded
=
ObservableField
(
false
)
val
isFilterExpanded
=
ObservableField
(
false
)
override
fun
rxRefresh
()
=
magiskRepo
.
fetchApps
()
override
fun
refresh
()
=
viewModelScope
.
launch
{
.
map
{
it
to
magiskRepo
.
fetchHideTargets
().
blockingGet
()
}
state
=
State
.
LOADING
.
map
{
pair
->
pair
.
first
.
map
{
mergeAppTargets
(
it
,
pair
.
second
)
}
}
val
apps
=
magiskRepo
.
fetchApps
()
.
flattenAsFlowable
{
it
}
val
hides
=
magiskRepo
.
fetchHideTargets
()
.
map
{
HideItem
(
it
)
}
val
(
hidden
,
diff
)
=
withContext
(
Dispatchers
.
Default
)
{
.
toList
()
val
hidden
=
apps
.
map
{
mergeAppTargets
(
it
,
hides
)
}.
map
{
HideItem
(
it
)
}.
sort
()
.
map
{
it
.
sort
()
}
hidden
to
items
.
calculateDiff
(
hidden
)
.
map
{
it
to
items
.
calculateDiff
(
it
)
}
.
applyViewModel
(
this
)
.
subscribeK
{
items
.
update
(
it
.
first
,
it
.
second
)
submitQuery
()
}
}
items
.
update
(
hidden
,
diff
)
submitQuery
()
state
=
State
.
LOADED
}
// ---
// ---
...
...
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
View file @
8647ba47
package
com.topjohnwu.magisk.ui.home
package
com.topjohnwu.magisk.ui.home
import
android.Manifest
import
android.os.Build
import
android.os.Build
import
androidx.databinding.ObservableField
import
androidx.databinding.ObservableField
import
androidx.lifecycle.viewModelScope
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Config
...
@@ -11,9 +11,11 @@ import com.topjohnwu.magisk.core.base.BaseActivity
...
@@ -11,9 +11,11 @@ import com.topjohnwu.magisk.core.base.BaseActivity
import
com.topjohnwu.magisk.core.download.RemoteFileService
import
com.topjohnwu.magisk.core.download.RemoteFileService
import
com.topjohnwu.magisk.core.model.MagiskJson
import
com.topjohnwu.magisk.core.model.MagiskJson
import
com.topjohnwu.magisk.core.model.ManagerJson
import
com.topjohnwu.magisk.core.model.ManagerJson
import
com.topjohnwu.magisk.core.model.UpdateInfo
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.extensions.*
import
com.topjohnwu.magisk.extensions.await
import
com.topjohnwu.magisk.extensions.packageName
import
com.topjohnwu.magisk.extensions.res
import
com.topjohnwu.magisk.extensions.value
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject.Manager
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject.Manager
import
com.topjohnwu.magisk.model.entity.recycler.DeveloperItem
import
com.topjohnwu.magisk.model.entity.recycler.DeveloperItem
import
com.topjohnwu.magisk.model.entity.recycler.HomeItem
import
com.topjohnwu.magisk.model.entity.recycler.HomeItem
...
@@ -26,6 +28,7 @@ import com.topjohnwu.magisk.model.events.dialog.UninstallDialog
...
@@ -26,6 +28,7 @@ import com.topjohnwu.magisk.model.events.dialog.UninstallDialog
import
com.topjohnwu.magisk.ui.base.BaseViewModel
import
com.topjohnwu.magisk.ui.base.BaseViewModel
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
kotlinx.coroutines.launch
import
me.tatarka.bindingcollectionadapter2.BR
import
me.tatarka.bindingcollectionadapter2.BR
import
kotlin.math.roundToInt
import
kotlin.math.roundToInt
...
@@ -72,27 +75,29 @@ class HomeViewModel(
...
@@ -72,27 +75,29 @@ class HomeViewModel(
}
}
}
}
override
fun
rxRefresh
()
=
repoMagisk
.
fetchUpdate
()
override
fun
refresh
()
=
viewModelScope
.
launch
{
.
onErrorReturn
{
null
}
repoMagisk
.
fetchUpdate
()
?.
apply
{
.
subscribeK
{
it
?.
updateUI
()
}
stateMagisk
.
value
=
when
{
!
Info
.
env
.
isActive
->
MagiskState
.
NOT_INSTALLED
private
fun
UpdateInfo
.
updateUI
()
{
magisk
.
isObsolete
->
MagiskState
.
OBSOLETE
stateMagisk
.
value
=
when
{
else
->
MagiskState
.
UP_TO_DATE
!
Info
.
env
.
isActive
->
MagiskState
.
NOT_INSTALLED
}
magisk
.
isObsolete
->
MagiskState
.
OBSOLETE
else
->
MagiskState
.
UP_TO_DATE
}
stateManager
.
value
=
when
{
stateManager
.
value
=
when
{
!
app
.
isUpdateChannelCorrect
&&
isConnected
.
value
->
MagiskState
.
NOT_INSTALLED
!
app
.
isUpdateChannelCorrect
&&
isConnected
.
value
->
MagiskState
.
NOT_INSTALLED
app
.
isObsolete
->
MagiskState
.
OBSOLETE
app
.
isObsolete
->
MagiskState
.
OBSOLETE
else
->
MagiskState
.
UP_TO_DATE
else
->
MagiskState
.
UP_TO_DATE
}
}
stateMagiskRemoteVersion
.
value
=
"${magisk.version} (${magisk.versionCode})"
stateMagiskRemoteVersion
.
value
=
stateManagerRemoteVersion
.
value
=
"${app.version} (${app.versionCode}) (${stub.versionCode})"
"${magisk.version} (${magisk.versionCode})"
stateManagerRemoteVersion
.
value
=
"${app.version} (${app.versionCode}) (${stub.versionCode})"
ensureEnv
()
launch
{
ensureEnv
()
}
}
}
}
val
showTest
=
false
val
showTest
=
false
...
@@ -109,19 +114,18 @@ class HomeViewModel(
...
@@ -109,19 +114,18 @@ class HomeViewModel(
fun
onManagerPressed
()
=
ManagerInstallDialog
().
publish
()
fun
onManagerPressed
()
=
ManagerInstallDialog
().
publish
()
fun
onMagiskPressed
()
=
withPermissions
(
fun
onMagiskPressed
()
=
withExternalRW
{
Manifest
.
permission
.
READ_EXTERNAL_STORAGE
,
if
(
it
)
{
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
HomeFragmentDirections
.
actionHomeFragmentToInstallFragment
().
publish
()
).
map
{
check
(
it
);
it
}
}
.
subscribeK
{
HomeFragmentDirections
.
actionHomeFragmentToInstallFragment
().
publish
()
}
}
.
add
()
fun
hideNotice
()
{
fun
hideNotice
()
{
Config
.
safetyNotice
=
false
Config
.
safetyNotice
=
false
isNoticeVisible
.
value
=
false
isNoticeVisible
.
value
=
false
}
}
private
fun
ensureEnv
()
{
private
suspend
fun
ensureEnv
()
{
val
invalidStates
=
listOf
(
val
invalidStates
=
listOf
(
MagiskState
.
NOT_INSTALLED
,
MagiskState
.
NOT_INSTALLED
,
MagiskState
.
LOADING
MagiskState
.
LOADING
...
@@ -138,21 +142,18 @@ class HomeViewModel(
...
@@ -138,21 +142,18 @@ class HomeViewModel(
return
return
}
}
Shell
.
su
(
"env_check"
)
val
result
=
Shell
.
su
(
"env_check"
).
await
()
.
toSingle
()
if
(!
result
.
isSuccess
)
{
.
map
{
it
.
exec
()
}
shownDialog
=
true
.
filter
{
!
it
.
isSuccess
}
EnvFixDialog
().
publish
()
.
subscribeK
{
}
shownDialog
=
true
EnvFixDialog
().
publish
()
}
}
}
private
val
MagiskJson
.
isObsolete
private
val
MagiskJson
.
isObsolete
get
()
=
Info
.
env
.
isActive
&&
Info
.
env
.
magiskVersionCode
<
versionCode
get
()
=
Info
.
env
.
isActive
&&
Info
.
env
.
magiskVersionCode
<
versionCode
val
ManagerJson
.
isUpdateChannelCorrect
private
val
ManagerJson
.
isUpdateChannelCorrect
get
()
=
versionCode
>
0
get
()
=
versionCode
>
0
val
ManagerJson
.
isObsolete
private
val
ManagerJson
.
isObsolete
get
()
=
BuildConfig
.
VERSION_CODE
<
versionCode
get
()
=
BuildConfig
.
VERSION_CODE
<
versionCode
}
}
app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
View file @
8647ba47
package
com.topjohnwu.magisk.ui.log
package
com.topjohnwu.magisk.ui.log
import
androidx.databinding.ObservableField
import
androidx.databinding.ObservableField
import
androidx.lifecycle.viewModelScope
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.data.repository.LogRepository
import
com.topjohnwu.magisk.data.repository.LogRepository
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.value
import
com.topjohnwu.magisk.extensions.value
import
com.topjohnwu.magisk.model.entity.recycler.LogItem
import
com.topjohnwu.magisk.model.entity.recycler.LogItem
import
com.topjohnwu.magisk.model.entity.recycler.TextItem
import
com.topjohnwu.magisk.model.entity.recycler.TextItem
...
@@ -15,12 +15,10 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
...
@@ -15,12 +15,10 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
import
com.topjohnwu.magisk.ui.base.diffListOf
import
com.topjohnwu.magisk.ui.base.diffListOf
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
io.reactivex.Completable
import
kotlinx.coroutines.*
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.disposables.Disposable
import
io.reactivex.schedulers.Schedulers
import
timber.log.Timber
import
timber.log.Timber
import
java.io.File
import
java.io.File
import
java.io.IOException
import
java.util.*
import
java.util.*
class
LogViewModel
(
class
LogViewModel
(
...
@@ -43,28 +41,21 @@ class LogViewModel(
...
@@ -43,28 +41,21 @@ class LogViewModel(
val
consoleText
=
ObservableField
(
" "
)
val
consoleText
=
ObservableField
(
" "
)
override
fun
rxRefresh
():
Disposable
{
override
fun
refresh
()
=
viewModelScope
.
launch
{
val
logs
=
repo
.
fetchLogs
()
consoleText
.
value
=
repo
.
fetchMagiskLogs
()
.
map
{
it
.
map
{
LogItem
(
it
)
}
}
val
deferred
=
withContext
(
Dispatchers
.
Default
)
{
.
observeOn
(
Schedulers
.
computation
())
async
{
.
map
{
it
to
items
.
calculateDiff
(
it
)
}
val
suLogs
=
repo
.
fetchSuLogs
().
map
{
LogItem
(
it
)
}
.
observeOn
(
AndroidSchedulers
.
mainThread
())
suLogs
to
items
.
calculateDiff
(
suLogs
)
.
doOnSuccess
{
items
.
firstOrNull
()
?.
isTop
=
false
items
.
lastOrNull
()
?.
isBottom
=
false
items
.
update
(
it
.
first
,
it
.
second
)
items
.
firstOrNull
()
?.
isTop
=
true
items
.
lastOrNull
()
?.
isBottom
=
true
}
}
.
ignoreElement
()
}
delay
(
500
)
val
console
=
repo
.
fetchMagiskLogs
()
val
(
suLogs
,
diff
)
=
deferred
.
await
()
.
doOnSuccess
{
consoleText
.
value
=
it
}
items
.
firstOrNull
()
?.
isTop
=
false
.
ignoreElement
()
items
.
lastOrNull
()
?.
isBottom
=
false
items
.
update
(
suLogs
,
diff
)
return
Completable
.
merge
(
listOf
(
logs
,
console
)).
subscribeK
()
items
.
firstOrNull
()
?.
isTop
=
true
items
.
lastOrNull
()
?.
isBottom
=
true
}
}
fun
saveMagiskLog
()
{
fun
saveMagiskLog
()
{
...
@@ -76,10 +67,10 @@ class LogViewModel(
...
@@ -76,10 +67,10 @@ class LogViewModel(
)
)
val
logFile
=
File
(
Config
.
downloadDirectory
,
filename
)
val
logFile
=
File
(
Config
.
downloadDirectory
,
filename
)
runCatching
{
try
{
logFile
.
createNewFile
()
logFile
.
createNewFile
()
}
.
onFailure
{
}
catch
(
e
:
IOException
)
{
Timber
.
e
(
it
)
Timber
.
e
(
e
)
return
return
}
}
...
@@ -88,18 +79,14 @@ class LogViewModel(
...
@@ -88,18 +79,14 @@ class LogViewModel(
}
}
}
}
fun
clearMagiskLog
()
=
repo
.
clearMagiskLogs
()
fun
clearMagiskLog
()
=
repo
.
clearMagiskLogs
{
.
subscribeK
{
SnackbarEvent
(
R
.
string
.
logs_cleared
).
publish
()
SnackbarEvent
(
R
.
string
.
logs_cleared
).
publish
()
requestRefresh
()
requestRefresh
()
}
}
.
add
()
fun
clearLog
()
=
repo
.
clearLogs
()
.
subscribeK
{
SnackbarEvent
(
R
.
string
.
logs_cleared
).
publish
()
requestRefresh
()
}
.
add
()
fun
clearLog
()
=
viewModelScope
.
launch
{
repo
.
clearLogs
()
SnackbarEvent
(
R
.
string
.
logs_cleared
).
publish
()
requestRefresh
()
}
}
}
app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt
View file @
8647ba47
...
@@ -47,7 +47,7 @@ class ModuleViewModel(
...
@@ -47,7 +47,7 @@ class ModuleViewModel(
private
val
repoName
:
RepoByNameDao
,
private
val
repoName
:
RepoByNameDao
,
private
val
repoUpdated
:
RepoByUpdatedDao
,
private
val
repoUpdated
:
RepoByUpdatedDao
,
private
val
repoUpdater
:
RepoUpdater
private
val
repoUpdater
:
RepoUpdater
)
:
BaseViewModel
(
useRx
=
false
),
Queryable
{
)
:
BaseViewModel
(),
Queryable
{
override
val
queryDelay
=
1000L
override
val
queryDelay
=
1000L
private
var
queryJob
:
Job
?
=
null
private
var
queryJob
:
Job
?
=
null
...
...
app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt
View file @
8647ba47
...
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.superuser
...
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.superuser
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager
import
android.content.res.Resources
import
android.content.res.Resources
import
androidx.databinding.ObservableArrayList
import
androidx.databinding.ObservableArrayList
import
androidx.lifecycle.viewModelScope
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.magiskdb.PolicyDao
import
com.topjohnwu.magisk.core.magiskdb.PolicyDao
...
@@ -10,8 +11,6 @@ import com.topjohnwu.magisk.core.model.MagiskPolicy
...
@@ -10,8 +11,6 @@ import com.topjohnwu.magisk.core.model.MagiskPolicy
import
com.topjohnwu.magisk.core.utils.BiometricHelper
import
com.topjohnwu.magisk.core.utils.BiometricHelper
import
com.topjohnwu.magisk.core.utils.currentLocale
import
com.topjohnwu.magisk.core.utils.currentLocale
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.applySchedulers
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.toggle
import
com.topjohnwu.magisk.extensions.toggle
import
com.topjohnwu.magisk.model.entity.recycler.PolicyItem
import
com.topjohnwu.magisk.model.entity.recycler.PolicyItem
import
com.topjohnwu.magisk.model.entity.recycler.TappableHeadlineItem
import
com.topjohnwu.magisk.model.entity.recycler.TappableHeadlineItem
...
@@ -24,7 +23,9 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
...
@@ -24,7 +23,9 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
import
com.topjohnwu.magisk.ui.base.adapterOf
import
com.topjohnwu.magisk.ui.base.adapterOf
import
com.topjohnwu.magisk.ui.base.diffListOf
import
com.topjohnwu.magisk.ui.base.diffListOf
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
com.topjohnwu.magisk.ui.base.itemBindingOf
import
io.reactivex.Single
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
import
me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
class
SuperuserViewModel
(
class
SuperuserViewModel
(
...
@@ -53,27 +54,23 @@ class SuperuserViewModel(
...
@@ -53,27 +54,23 @@ class SuperuserViewModel(
// ---
// ---
override
fun
rxRefresh
()
=
db
.
fetchAll
()
override
fun
refresh
()
=
viewModelScope
.
launch
{
.
flattenAsFlowable
{
it
}
state
=
State
.
LOADING
.
parallel
()
val
(
policies
,
diff
)
=
withContext
(
Dispatchers
.
Default
)
{
.
map
{
PolicyItem
(
it
,
it
.
applicationInfo
.
loadIcon
(
packageManager
))
}
val
policies
=
db
.
fetchAll
{
.
sequential
()
PolicyItem
(
it
,
it
.
applicationInfo
.
loadIcon
(
packageManager
))
.
sorted
{
o1
,
o2
->
}.
sortedWith
(
compareBy
(
compareBy
<
PolicyItem
>(
{
it
.
item
.
appName
.
toLowerCase
(
currentLocale
)
},
{
it
.
item
.
appName
.
toLowerCase
(
currentLocale
)
},
{
it
.
item
.
packageName
}
{
it
.
item
.
packageName
}
).
compare
(
o1
,
o2
)
))
policies
to
itemsPolicies
.
calculateDiff
(
policies
)
}
}
.
toList
()
itemsPolicies
.
update
(
policies
,
diff
)
.
map
{
it
to
itemsPolicies
.
calculateDiff
(
it
)
}
if
(
itemsPolicies
.
isNotEmpty
())
{
.
applySchedulers
()
itemsHelpers
.
remove
(
itemNoData
)
.
applyViewModel
(
this
)
.
subscribeK
{
itemsPolicies
.
update
(
it
.
first
,
it
.
second
)
if
(
itemsPolicies
.
isNotEmpty
())
{
itemsHelpers
.
remove
(
itemNoData
)
}
}
}
state
=
State
.
LOADED
}
// ---
// ---
...
@@ -91,14 +88,13 @@ class SuperuserViewModel(
...
@@ -91,14 +88,13 @@ class SuperuserViewModel(
SuperuserFragmentDirections
.
actionSuperuserFragmentToHideFragment
().
publish
()
SuperuserFragmentDirections
.
actionSuperuserFragmentToHideFragment
().
publish
()
fun
deletePressed
(
item
:
PolicyItem
)
{
fun
deletePressed
(
item
:
PolicyItem
)
{
fun
updateState
()
=
deletePolicy
(
item
.
item
)
fun
updateState
()
=
viewModelScope
.
launch
{
.
subscribeK
{
db
.
delete
(
item
.
item
.
uid
)
itemsPolicies
.
removeAll
{
it
.
genericItemSameAs
(
item
)
}
itemsPolicies
.
removeAll
{
it
.
genericItemSameAs
(
item
)
}
if
(
itemsPolicies
.
isEmpty
()
&&
itemsHelpers
.
isEmpty
())
{
if
(
itemsPolicies
.
isEmpty
()
&&
itemsHelpers
.
isEmpty
())
{
itemsHelpers
.
add
(
itemNoData
)
itemsHelpers
.
add
(
itemNoData
)
}
}
}
.
add
()
}
if
(
BiometricHelper
.
isEnabled
)
{
if
(
BiometricHelper
.
isEnabled
)
{
BiometricDialog
{
BiometricDialog
{
...
@@ -114,34 +110,37 @@ class SuperuserViewModel(
...
@@ -114,34 +110,37 @@ class SuperuserViewModel(
//---
//---
fun
updatePolicy
(
it
:
PolicyUpdateEvent
)
=
when
(
it
)
{
fun
updatePolicy
(
it
:
PolicyUpdateEvent
)
=
viewModelScope
.
launch
{
is
PolicyUpdateEvent
.
Notification
->
updatePolicy
(
it
.
item
).
map
{
val
snackStr
=
when
(
it
)
{
when
{
is
PolicyUpdateEvent
.
Notification
->
{
it
.
notification
->
R
.
string
.
su_snack_notif_on
updatePolicy
(
it
.
item
)
else
->
R
.
string
.
su_snack_notif_off
when
{
}
to
it
.
appName
it
.
item
.
notification
->
R
.
string
.
su_snack_notif_on
}
else
->
R
.
string
.
su_snack_notif_off
is
PolicyUpdateEvent
.
Log
->
updatePolicy
(
it
.
item
).
map
{
}
when
{
}
it
.
logging
->
R
.
string
.
su_snack_log_on
is
PolicyUpdateEvent
.
Log
->
{
else
->
R
.
string
.
su_snack_log_off
updatePolicy
(
it
.
item
)
}
to
it
.
appName
when
{
it
.
item
.
logging
->
R
.
string
.
su_snack_log_on
else
->
R
.
string
.
su_snack_log_off
}
}
}
}
}.
map
{
resources
.
getString
(
it
.
first
,
it
.
second
)
}
SnackbarEvent
(
resources
.
getString
(
snackStr
,
it
.
item
.
appName
)).
publish
()
.
subscribeK
{
SnackbarEvent
(
it
).
publish
()
}
}
.
add
()
fun
togglePolicy
(
item
:
PolicyItem
,
enable
:
Boolean
)
{
fun
togglePolicy
(
item
:
PolicyItem
,
enable
:
Boolean
)
{
fun
updateState
()
{
fun
updateState
()
{
val
policy
=
if
(
enable
)
MagiskPolicy
.
ALLOW
else
MagiskPolicy
.
DENY
val
policy
=
if
(
enable
)
MagiskPolicy
.
ALLOW
else
MagiskPolicy
.
DENY
val
app
=
item
.
item
.
copy
(
policy
=
policy
)
val
app
=
item
.
item
.
copy
(
policy
=
policy
)
updatePolicy
(
app
)
viewModelScope
.
launch
{
.
map
{
it
.
policy
==
MagiskPolicy
.
ALLOW
}
updatePolicy
(
app
)
.
map
{
if
(
it
)
R
.
string
.
su_snack_grant
else
R
.
string
.
su_snack_deny
}
val
res
=
if
(
app
.
policy
==
MagiskPolicy
.
ALLOW
)
R
.
string
.
su_snack_grant
.
map
{
resources
.
getString
(
it
).
format
(
item
.
item
.
appName
)
}
else
R
.
string
.
su_snack_deny
.
subscribeK
{
SnackbarEvent
(
it
).
publish
()
}
SnackbarEvent
(
resources
.
getString
(
res
).
format
(
item
.
item
.
appName
))
.
add
()
}
}
}
if
(
BiometricHelper
.
isEnabled
)
{
if
(
BiometricHelper
.
isEnabled
)
{
...
@@ -156,10 +155,6 @@ class SuperuserViewModel(
...
@@ -156,10 +155,6 @@ class SuperuserViewModel(
//---
//---
private
fun
updatePolicy
(
policy
:
MagiskPolicy
)
=
private
suspend
fun
updatePolicy
(
policy
:
MagiskPolicy
)
=
db
.
update
(
policy
)
db
.
update
(
policy
).
andThen
(
Single
.
just
(
policy
))
private
fun
deletePolicy
(
policy
:
MagiskPolicy
)
=
db
.
delete
(
policy
.
uid
).
andThen
(
Single
.
just
(
policy
))
}
}
build.gradle.kts
View file @
8647ba47
...
@@ -60,7 +60,7 @@ subprojects {
...
@@ -60,7 +60,7 @@ subprojects {
plugins
.
hasPlugin
(
"com.android.application"
))
{
plugins
.
hasPlugin
(
"com.android.application"
))
{
android
.
apply
{
android
.
apply
{
compileSdkVersion
(
30
)
compileSdkVersion
(
30
)
buildToolsVersion
=
"30.0.
0
"
buildToolsVersion
=
"30.0.
1
"
defaultConfig
{
defaultConfig
{
if
(
minSdkVersion
==
null
)
if
(
minSdkVersion
==
null
)
...
...
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