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
470fc97d
Commit
470fc97d
authored
Sep 13, 2021
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove SafetyNet check
parent
8d59caf6
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
3 additions
and
642 deletions
+3
-642
AndroidManifest.xml
app/shared/src/main/AndroidManifest.xml
+0
-5
HomeViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
+2
-9
CheckSafetyNetEvent.kt
.../com/topjohnwu/magisk/ui/safetynet/CheckSafetyNetEvent.kt
+0
-225
SafetyNetHelper.kt
...java/com/topjohnwu/magisk/ui/safetynet/SafetyNetHelper.kt
+0
-14
SafetynetFragment.kt
...va/com/topjohnwu/magisk/ui/safetynet/SafetynetFragment.kt
+0
-31
SafetynetViewModel.kt
...a/com/topjohnwu/magisk/ui/safetynet/SafetynetViewModel.kt
+0
-95
fragment_home_md2.xml
app/src/main/res/layout/fragment_home_md2.xml
+1
-15
fragment_safetynet_md2.xml
app/src/main/res/layout/fragment_safetynet_md2.xml
+0
-234
main.xml
app/src/main/res/navigation/main.xml
+0
-14
No files found.
app/shared/src/main/AndroidManifest.xml
View file @
470fc97d
...
@@ -25,9 +25,4 @@
...
@@ -25,9 +25,4 @@
android:usesCleartextTraffic=
"true"
android:usesCleartextTraffic=
"true"
tools:ignore=
"UnusedAttribute"
/>
tools:ignore=
"UnusedAttribute"
/>
<!-- Hardcode GMS version -->
<meta-data
android:name=
"com.google.android.gms.version"
android:value=
"12451000"
/>
</manifest>
</manifest>
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
View file @
470fc97d
...
@@ -75,9 +75,6 @@ class HomeViewModel(
...
@@ -75,9 +75,6 @@ class HomeViewModel(
var
stateManagerProgress
=
0
var
stateManagerProgress
=
0
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
stateManagerProgress
)
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
stateManagerProgress
)
@get
:
Bindable
val
showSafetyNet
get
()
=
Info
.
hasGMS
&&
isConnected
.
get
()
val
itemBinding
=
itemBindingOf
<
IconLink
>
{
val
itemBinding
=
itemBindingOf
<
IconLink
>
{
it
.
bindExtra
(
BR
.
viewModel
,
this
)
it
.
bindExtra
(
BR
.
viewModel
,
this
)
}
}
...
@@ -86,7 +83,6 @@ class HomeViewModel(
...
@@ -86,7 +83,6 @@ class HomeViewModel(
override
fun
refresh
()
=
viewModelScope
.
launch
{
override
fun
refresh
()
=
viewModelScope
.
launch
{
state
=
State
.
LOADING
state
=
State
.
LOADING
notifyPropertyChanged
(
BR
.
showSafetyNet
)
Info
.
getRemote
(
svc
)
?.
apply
{
Info
.
getRemote
(
svc
)
?.
apply
{
state
=
State
.
LOADED
state
=
State
.
LOADED
...
@@ -101,10 +97,10 @@ class HomeViewModel(
...
@@ -101,10 +97,10 @@ class HomeViewModel(
launch
{
launch
{
ensureEnv
()
ensureEnv
()
}
}
}
?:
{
}
?:
run
{
state
=
State
.
LOADING_FAILED
state
=
State
.
LOADING_FAILED
managerRemoteVersion
=
R
.
string
.
not_available
.
asText
()
managerRemoteVersion
=
R
.
string
.
not_available
.
asText
()
}
()
}
}
}
val
showTest
=
false
val
showTest
=
false
...
@@ -134,9 +130,6 @@ class HomeViewModel(
...
@@ -134,9 +130,6 @@ class HomeViewModel(
HomeFragmentDirections
.
actionHomeFragmentToInstallFragment
().
navigate
()
HomeFragmentDirections
.
actionHomeFragmentToInstallFragment
().
navigate
()
}
}
fun
onSafetyNetPressed
()
=
HomeFragmentDirections
.
actionHomeFragmentToSafetynetFragment
().
navigate
()
fun
hideNotice
()
{
fun
hideNotice
()
{
Config
.
safetyNotice
=
false
Config
.
safetyNotice
=
false
isNoticeVisible
=
false
isNoticeVisible
=
false
...
...
app/src/main/java/com/topjohnwu/magisk/ui/safetynet/CheckSafetyNetEvent.kt
deleted
100644 → 0
View file @
8d59caf6
@file
:
Suppress
(
"DEPRECATION"
)
package
com.topjohnwu.magisk.ui.safetynet
import
android.content.Context
import
android.util.Base64
import
com.squareup.moshi.Json
import
com.squareup.moshi.JsonClass
import
com.squareup.moshi.Moshi
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.arch.ContextExecutor
import
com.topjohnwu.magisk.arch.ViewEventWithScope
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.di.ServiceLocator
import
com.topjohnwu.magisk.ktx.createClassLoader
import
com.topjohnwu.magisk.ktx.reflectField
import
com.topjohnwu.magisk.ktx.writeTo
import
com.topjohnwu.magisk.signing.CryptoUtils
import
com.topjohnwu.magisk.view.MagiskDialog
import
com.topjohnwu.superuser.Shell
import
dalvik.system.BaseDexClassLoader
import
dalvik.system.DexFile
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
org.bouncycastle.asn1.ASN1Encoding
import
org.bouncycastle.asn1.ASN1Primitive
import
org.bouncycastle.est.jcajce.JsseDefaultHostnameAuthorizer
import
timber.log.Timber
import
java.io.ByteArrayInputStream
import
java.io.File
import
java.io.IOException
import
java.lang.reflect.InvocationHandler
import
java.lang.reflect.Proxy
import
java.security.SecureRandom
import
java.security.Signature
class
CheckSafetyNetEvent
(
private
val
callback
:
(
SafetyNetResult
)
->
Unit
=
{}
)
:
ViewEventWithScope
(),
ContextExecutor
,
SafetyNetHelper
.
Callback
{
private
val
svc
get
()
=
ServiceLocator
.
networkService
private
lateinit
var
jar
:
File
private
lateinit
var
nonce
:
ByteArray
override
fun
invoke
(
context
:
Context
)
{
jar
=
File
(
"${context.filesDir.parent}/snet"
,
"snet.jar"
)
scope
.
launch
(
Dispatchers
.
IO
)
{
attest
(
context
)
{
// Download and retry
Shell
.
sh
(
"rm -rf "
+
jar
.
parent
).
exec
()
jar
.
parentFile
?.
mkdir
()
withContext
(
Dispatchers
.
Main
)
{
showDialog
(
context
)
}
}
}
}
private
suspend
fun
attest
(
context
:
Context
,
onError
:
suspend
(
Exception
)
->
Unit
)
{
val
helper
:
SafetyNetHelper
try
{
val
loader
=
createClassLoader
(
jar
)
// Scan through the dex and find our helper class
var
clazz
:
Class
<*>?
=
null
loop
@for
(
dex
in
loader
.
getDexFiles
())
{
for
(
name
in
dex
.
entries
())
{
val
cls
=
loader
.
loadClass
(
name
)
if
(
InvocationHandler
::
class
.
java
.
isAssignableFrom
(
cls
))
{
clazz
=
cls
break
@loop
}
}
}
clazz
?:
throw
Exception
(
"Cannot find SafetyNetHelper implementation"
)
helper
=
Proxy
.
newProxyInstance
(
loader
,
arrayOf
(
SafetyNetHelper
::
class
.
java
),
clazz
.
newInstance
()
as
InvocationHandler
)
as
SafetyNetHelper
if
(
helper
.
version
!=
Const
.
SNET_EXT_VER
)
throw
Exception
(
"snet extension version mismatch"
)
}
catch
(
e
:
Exception
)
{
onError
(
e
)
return
}
val
random
=
SecureRandom
()
nonce
=
ByteArray
(
24
)
random
.
nextBytes
(
nonce
)
helper
.
attest
(
context
,
nonce
,
this
)
}
// All of these fields are whitelisted
private
fun
BaseDexClassLoader
.
getDexFiles
():
List
<
DexFile
>
{
val
pathList
=
BaseDexClassLoader
::
class
.
java
.
reflectField
(
"pathList"
).
get
(
this
)
val
dexElements
=
pathList
.
javaClass
.
reflectField
(
"dexElements"
).
get
(
pathList
)
as
Array
<*>
val
fileField
=
dexElements
.
javaClass
.
componentType
.
reflectField
(
"dexFile"
)
return
dexElements
.
map
{
fileField
.
get
(
it
)
as
DexFile
}
}
private
fun
download
(
context
:
Context
)
=
scope
.
launch
(
Dispatchers
.
IO
)
{
val
abort
:
suspend
(
Exception
)
->
Unit
=
{
Timber
.
e
(
it
)
withContext
(
Dispatchers
.
Main
)
{
callback
(
SafetyNetResult
())
}
}
try
{
svc
.
fetchSafetynet
().
byteStream
().
writeTo
(
jar
)
attest
(
context
,
abort
)
}
catch
(
e
:
IOException
)
{
abort
(
e
)
}
}
private
fun
showDialog
(
context
:
Context
)
{
MagiskDialog
(
context
)
.
applyTitle
(
R
.
string
.
proprietary_title
)
.
applyMessage
(
R
.
string
.
proprietary_notice
)
.
cancellable
(
false
)
.
applyButton
(
MagiskDialog
.
ButtonType
.
POSITIVE
)
{
titleRes
=
android
.
R
.
string
.
ok
onClick
{
download
(
context
)
}
}
.
applyButton
(
MagiskDialog
.
ButtonType
.
NEGATIVE
)
{
titleRes
=
android
.
R
.
string
.
cancel
onClick
{
callback
(
SafetyNetResult
(
dismiss
=
true
))
}
}
.
onCancel
{
callback
(
SafetyNetResult
(
dismiss
=
true
))
}
.
reveal
()
}
private
fun
String
.
decode
():
ByteArray
{
return
if
(
contains
(
"[+/]"
.
toRegex
()))
Base64
.
decode
(
this
,
Base64
.
DEFAULT
)
else
Base64
.
decode
(
this
,
Base64
.
URL_SAFE
)
}
private
fun
String
.
parseJws
():
SafetyNetResponse
{
val
jws
=
split
(
'.'
)
val
secondDot
=
lastIndexOf
(
'.'
)
val
rawHeader
=
String
(
jws
[
0
].
decode
())
val
payload
=
String
(
jws
[
1
].
decode
())
var
signature
=
jws
[
2
].
decode
()
val
signedBytes
=
substring
(
0
,
secondDot
).
toByteArray
()
val
moshi
=
Moshi
.
Builder
().
build
()
val
header
=
moshi
.
adapter
(
JwsHeader
::
class
.
java
).
fromJson
(
rawHeader
)
?:
error
(
"Invalid JWS header"
)
val
alg
=
when
(
header
.
algorithm
)
{
"RS256"
->
"SHA256withRSA"
"ES256"
->
{
// Convert to DER encoding
signature
=
ASN1Primitive
.
fromByteArray
(
signature
).
getEncoded
(
ASN1Encoding
.
DER
)
"SHA256withECDSA"
}
else
->
error
(
"Unsupported algorithm: ${header.algorithm}"
)
}
// Verify signature
val
certB64
=
header
.
certificates
?.
first
()
?:
error
(
"Cannot find certificate in JWS"
)
val
bis
=
ByteArrayInputStream
(
certB64
.
decode
())
val
cert
=
CryptoUtils
.
readCertificate
(
bis
)
val
verifier
=
Signature
.
getInstance
(
alg
)
verifier
.
initVerify
(
cert
.
publicKey
)
verifier
.
update
(
signedBytes
)
if
(!
verifier
.
verify
(
signature
))
error
(
"Signature mismatch"
)
// Verify hostname
val
hostnameVerifier
=
JsseDefaultHostnameAuthorizer
(
setOf
())
if
(!
hostnameVerifier
.
verify
(
"attest.android.com"
,
cert
))
error
(
"Hostname mismatch"
)
val
response
=
moshi
.
adapter
(
SafetyNetResponse
::
class
.
java
).
fromJson
(
payload
)
?:
error
(
"Invalid SafetyNet response"
)
// Verify results
if
(!
response
.
nonce
.
decode
().
contentEquals
(
nonce
))
error
(
"nonce mismatch"
)
return
response
}
override
fun
onResponse
(
response
:
String
?)
{
if
(
response
!=
null
)
{
scope
.
launch
(
Dispatchers
.
Default
)
{
val
res
=
runCatching
{
response
.
parseJws
()
}.
getOrElse
{
Timber
.
e
(
it
)
INVALID_RESPONSE
}
withContext
(
Dispatchers
.
Main
)
{
callback
(
SafetyNetResult
(
res
))
}
}
}
else
{
callback
(
SafetyNetResult
())
}
}
}
@JsonClass
(
generateAdapter
=
true
)
data class
JwsHeader
(
@Json
(
name
=
"alg"
)
val
algorithm
:
String
,
@Json
(
name
=
"x5c"
)
val
certificates
:
List
<
String
>?
)
@JsonClass
(
generateAdapter
=
true
)
data class
SafetyNetResponse
(
val
nonce
:
String
,
val
ctsProfileMatch
:
Boolean
,
val
basicIntegrity
:
Boolean
,
val
evaluationType
:
String
=
""
)
// Special instance to indicate invalid SafetyNet response
val
INVALID_RESPONSE
=
SafetyNetResponse
(
""
,
ctsProfileMatch
=
false
,
basicIntegrity
=
false
)
app/src/main/java/com/topjohnwu/magisk/ui/safetynet/SafetyNetHelper.kt
deleted
100644 → 0
View file @
8d59caf6
package
com.topjohnwu.magisk.ui.safetynet
import
android.content.Context
interface
SafetyNetHelper
{
val
version
:
Int
fun
attest
(
context
:
Context
,
nonce
:
ByteArray
,
callback
:
Callback
)
interface
Callback
{
fun
onResponse
(
response
:
String
?)
}
}
app/src/main/java/com/topjohnwu/magisk/ui/safetynet/SafetynetFragment.kt
deleted
100644 → 0
View file @
8d59caf6
package
com.topjohnwu.magisk.ui.safetynet
import
android.os.Bundle
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.arch.BaseUIFragment
import
com.topjohnwu.magisk.databinding.FragmentSafetynetMd2Binding
import
com.topjohnwu.magisk.di.viewModel
class
SafetynetFragment
:
BaseUIFragment
<
SafetynetViewModel
,
FragmentSafetynetMd2Binding
>()
{
override
val
layoutRes
=
R
.
layout
.
fragment_safetynet_md2
override
val
viewModel
by
viewModel
<
SafetynetViewModel
>()
override
fun
onStart
()
{
super
.
onStart
()
activity
.
setTitle
(
R
.
string
.
safetynet
)
}
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?):
View
?
{
super
.
onCreateView
(
inflater
,
container
,
savedInstanceState
)
// Set barrier reference IDs in code, since resource IDs will be stripped in release mode
binding
.
snetBarrier
.
referencedIds
=
intArrayOf
(
R
.
id
.
basic_text
,
R
.
id
.
cts_text
)
return
binding
.
root
}
}
app/src/main/java/com/topjohnwu/magisk/ui/safetynet/SafetynetViewModel.kt
deleted
100644 → 0
View file @
8d59caf6
package
com.topjohnwu.magisk.ui.safetynet
import
androidx.databinding.Bindable
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.arch.BaseViewModel
import
com.topjohnwu.magisk.databinding.set
class
SafetyNetResult
(
val
response
:
SafetyNetResponse
?
=
null
,
val
dismiss
:
Boolean
=
false
)
class
SafetynetViewModel
:
BaseViewModel
()
{
@get
:
Bindable
var
safetyNetTitle
=
R
.
string
.
empty
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
safetyNetTitle
)
@get
:
Bindable
var
ctsState
=
false
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
ctsState
)
@get
:
Bindable
var
basicIntegrityState
=
false
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
basicIntegrityState
)
@get
:
Bindable
var
evalType
=
""
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
evalType
)
@get
:
Bindable
var
isChecking
=
false
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
checking
)
@get
:
Bindable
var
isSuccess
=
false
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
success
,
BR
.
textColorAttr
)
@get
:
Bindable
val
textColorAttr
get
()
=
if
(
isSuccess
)
R
.
attr
.
colorOnPrimary
else
R
.
attr
.
colorOnError
init
{
cachedResult
?.
also
{
handleResult
(
SafetyNetResult
(
it
))
}
?:
attest
()
}
private
fun
attest
()
{
isChecking
=
true
CheckSafetyNetEvent
(
::
handleResult
).
publish
()
}
fun
reset
()
=
attest
()
private
fun
handleResult
(
result
:
SafetyNetResult
)
{
isChecking
=
false
if
(
result
.
dismiss
)
{
back
()
return
}
result
.
response
?.
apply
{
cachedResult
=
this
if
(
this
===
INVALID_RESPONSE
)
{
isSuccess
=
false
ctsState
=
false
basicIntegrityState
=
false
evalType
=
"N/A"
safetyNetTitle
=
R
.
string
.
safetynet_res_invalid
}
else
{
val
success
=
ctsProfileMatch
&&
basicIntegrity
isSuccess
=
success
ctsState
=
ctsProfileMatch
basicIntegrityState
=
basicIntegrity
evalType
=
if
(
evaluationType
.
contains
(
"HARDWARE"
))
"HARDWARE"
else
"BASIC"
safetyNetTitle
=
if
(
success
)
R
.
string
.
safetynet_attest_success
else
R
.
string
.
safetynet_attest_failure
}
}
?:
run
{
isSuccess
=
false
ctsState
=
false
basicIntegrityState
=
false
evalType
=
"N/A"
safetyNetTitle
=
R
.
string
.
safetynet_api_error
}
}
companion
object
{
private
var
cachedResult
:
SafetyNetResponse
?
=
null
}
}
app/src/main/res/layout/fragment_home_md2.xml
View file @
470fc97d
...
@@ -108,24 +108,10 @@
...
@@ -108,24 +108,10 @@
app:layout_constraintTop_toBottomOf=
"@+id/home_magisk_wrapper"
/>
app:layout_constraintTop_toBottomOf=
"@+id/home_magisk_wrapper"
/>
<Space
<Space
gone
=
"@{!viewModel.showSafetyNet && !
Info.env.isActive}"
gone
Unless=
"@{
Info.env.isActive}"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"@dimen/l1"
/>
android:layout_height=
"@dimen/l1"
/>
<Button
style=
"@style/WidgetFoundation.Button.Outlined"
gone=
"@{!viewModel.showSafetyNet}"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"@dimen/l1"
android:layout_marginEnd=
"@dimen/l1"
android:onClick=
"@{() -> viewModel.onSafetyNetPressed()}"
android:text=
"@string/home_check_safetynet"
android:textAllCaps=
"false"
android:textSize=
"12sp"
app:cornerRadius=
"@dimen/r1"
app:icon=
"@drawable/ic_safetynet_md2"
/>
<Button
<Button
style=
"@style/WidgetFoundation.Button.Outlined.Error"
style=
"@style/WidgetFoundation.Button.Outlined.Error"
goneUnless=
"@{Info.env.isActive}"
goneUnless=
"@{Info.env.isActive}"
...
...
app/src/main/res/layout/fragment_safetynet_md2.xml
deleted
100644 → 0
View file @
8d59caf6
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<import
type=
"android.os.Build"
/>
<import
type=
"com.topjohnwu.magisk.core.Info"
/>
<import
type=
"com.topjohnwu.magisk.BuildConfig"
/>
<import
type=
"com.topjohnwu.magisk.R"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.safetynet.SafetynetViewModel"
/>
</data>
<androidx.core.widget.NestedScrollView
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:clipToPadding=
"false"
android:fillViewport=
"true"
android:paddingTop=
"@dimen/internal_action_bar_size"
app:fitsSystemWindowsInsets=
"top|bottom"
tools:paddingBottom=
"48dp"
tools:paddingTop=
"24dp"
>
<FrameLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<TextView
invisibleUnless=
"@{viewModel.checking}"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:text=
"@string/safetynet_attest_loading"
android:textAppearance=
"@style/AppearanceFoundation.Title"
/>
<androidx.constraintlayout.widget.ConstraintLayout
invisible=
"@{viewModel.checking}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:paddingTop=
"@dimen/l1"
android:paddingBottom=
"@dimen/l1"
>
<com.google.android.material.card.MaterialCardView
android:id=
"@+id/safetynet_attestation"
style=
"@style/WidgetFoundation.Card.Elevated"
cardBackgroundColorAttr=
"@{viewModel.success ? R.attr.colorPrimary : R.attr.colorError}"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"@dimen/l1"
android:layout_marginTop=
"@dimen/l2"
android:layout_marginEnd=
"@dimen/l1"
app:cardCornerRadius=
"@dimen/l1"
app:cardElevation=
"@dimen/l1"
app:layout_constraintHorizontal_chainStyle=
"packed"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintVertical_bias=
".35"
app:layout_constraintWidth_max=
"300dp"
tools:cardBackgroundColor=
"?colorPrimary"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
<TextView
android:id=
"@+id/safetynet_title"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"@dimen/l1"
android:layout_marginTop=
"@dimen/l2"
android:layout_marginEnd=
"@dimen/l1"
android:gravity=
"center"
android:text=
"@{viewModel.safetyNetTitle}"
android:textAppearance=
"@style/AppearanceFoundation.Display.OnPrimary"
android:textStyle=
"bold"
app:textColorAttr=
"@{viewModel.textColorAttr}"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintHorizontal_chainStyle=
"packed"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:text=
"@string/safetynet_attest_success"
/>
<ImageView
android:id=
"@+id/safetynet_divider"
android:layout_width=
"50dp"
android:layout_height=
"4dp"
android:layout_marginTop=
"@dimen/l2"
app:srcCompat=
"@drawable/bg_divider_rounded_on_primary"
app:tintAttr=
"@{viewModel.textColorAttr}"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/safetynet_title"
tools:tint=
"?colorOnPrimary"
/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id=
"@+id/checkbox_layout"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:paddingBottom=
"@dimen/l1"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/safetynet_divider"
>
<TextView
android:id=
"@+id/basic_text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:gravity=
"start"
android:text=
"basicIntegrity"
android:textAppearance=
"@style/AppearanceFoundation.Body.OnPrimary"
android:textStyle=
"bold"
android:layout_marginTop=
"@dimen/l2"
app:textColorAttr=
"@{viewModel.textColorAttr}"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintEnd_toEndOf=
"@id/snet_barrier"
app:layout_constraintTop_toTopOf=
"parent"
tools:ignore=
"HardcodedText"
/>
<TextView
android:id=
"@+id/cts_text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:gravity=
"start"
android:text=
"ctsProfile"
android:textAppearance=
"@style/AppearanceFoundation.Body.OnPrimary"
android:textStyle=
"bold"
android:layout_marginTop=
"@dimen/l2"
app:textColorAttr=
"@{viewModel.textColorAttr}"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintEnd_toEndOf=
"@id/snet_barrier"
app:layout_constraintTop_toBottomOf=
"@id/basic_text"
tools:ignore=
"HardcodedText"
/>
<androidx.constraintlayout.widget.Barrier
android:id=
"@+id/snet_barrier"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
app:barrierDirection=
"end"
app:constraint_referenced_ids=
"basic_text,cts_text"
/>
<ImageView
style=
"@style/WidgetFoundation.Icon.OnPrimary"
isSelected=
"@{viewModel.basicIntegrityState}"
android:layout_gravity=
"center"
app:srcCompat=
"@drawable/ic_check_circle_md2"
app:tintAttr=
"@{viewModel.textColorAttr}"
app:layout_constraintStart_toEndOf=
"@id/snet_barrier"
app:layout_constraintTop_toTopOf=
"@id/basic_text"
app:layout_constraintBottom_toBottomOf=
"@id/basic_text"
tools:tint=
"?colorOnPrimary"
/>
<ImageView
style=
"@style/WidgetFoundation.Icon.OnPrimary"
isSelected=
"@{viewModel.ctsState}"
android:layout_gravity=
"center"
app:srcCompat=
"@drawable/ic_check_circle_md2"
app:tintAttr=
"@{viewModel.textColorAttr}"
app:layout_constraintStart_toEndOf=
"@id/snet_barrier"
app:layout_constraintTop_toTopOf=
"@id/cts_text"
app:layout_constraintBottom_toBottomOf=
"@id/cts_text"
tools:tint=
"?colorOnPrimary"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:orientation=
"horizontal"
android:paddingBottom=
"@dimen/l2"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/checkbox_layout"
>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:gravity=
"start"
android:text=
"evalType"
android:textAppearance=
"@style/AppearanceFoundation.Body.OnPrimary"
android:textStyle=
"bold"
app:textColorAttr=
"@{viewModel.textColorAttr}"
tools:ignore=
"HardcodedText"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:textAppearance=
"@style/AppearanceFoundation.Body.OnPrimary"
android:textStyle=
"bold"
android:layout_marginStart=
"@dimen/l1"
android:text=
"@{viewModel.evalType}"
app:textColorAttr=
"@{viewModel.textColorAttr}"
tools:text=
"HARDWARE"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<Button
style=
"@style/WidgetFoundation.Button.Text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"@dimen/l1"
android:layout_marginBottom=
"@dimen/l1"
android:onClick=
"@{() -> viewModel.reset()}"
android:text=
"@string/safetynet_attest_restart"
android:textAllCaps=
"false"
android:textColor=
"?colorOnSurfaceVariant"
app:icon=
"@drawable/ic_refresh_safetynet_md2"
app:iconTint=
"?colorOnSurfaceVariant"
app:layout_constraintEnd_toEndOf=
"@+id/safetynet_attestation"
app:layout_constraintTop_toBottomOf=
"@+id/safetynet_attestation"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
</androidx.core.widget.NestedScrollView>
</layout>
app/src/main/res/navigation/main.xml
View file @
470fc97d
...
@@ -33,14 +33,6 @@
...
@@ -33,14 +33,6 @@
app:popEnterAnim=
"@anim/fragment_enter_pop"
app:popEnterAnim=
"@anim/fragment_enter_pop"
app:popExitAnim=
"@anim/fragment_exit_pop"
/>
app:popExitAnim=
"@anim/fragment_exit_pop"
/>
<action
android:id=
"@+id/action_homeFragment_to_safetynetFragment"
app:destination=
"@id/safetynetFragment"
app:enterAnim=
"@anim/fragment_enter"
app:exitAnim=
"@anim/fragment_exit"
app:popEnterAnim=
"@anim/fragment_enter_pop"
app:popExitAnim=
"@anim/fragment_exit_pop"
/>
</fragment>
</fragment>
<fragment
<fragment
...
@@ -84,12 +76,6 @@
...
@@ -84,12 +76,6 @@
android:label=
"ModuleFragment"
android:label=
"ModuleFragment"
tools:layout=
"@layout/fragment_module_md2"
/>
tools:layout=
"@layout/fragment_module_md2"
/>
<fragment
android:id=
"@+id/safetynetFragment"
android:name=
"com.topjohnwu.magisk.ui.safetynet.SafetynetFragment"
android:label=
"SafetynetFragment"
tools:layout=
"@layout/fragment_safetynet_md2"
/>
<fragment
<fragment
android:id=
"@+id/settingsFragment"
android:id=
"@+id/settingsFragment"
android:name=
"com.topjohnwu.magisk.ui.settings.SettingsFragment"
android:name=
"com.topjohnwu.magisk.ui.settings.SettingsFragment"
...
...
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