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
2e4dc91b
Commit
2e4dc91b
authored
Oct 17, 2020
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Better stub hiding experience
parent
aaaaa3d0
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
162 additions
and
134 deletions
+162
-134
Config.kt
app/src/main/java/com/topjohnwu/magisk/core/Config.kt
+21
-27
Const.kt
app/src/main/java/com/topjohnwu/magisk/core/Const.kt
+1
-4
Provider.kt
app/src/main/java/com/topjohnwu/magisk/core/Provider.kt
+20
-0
SplashActivity.kt
...src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt
+18
-16
BaseDownloader.kt
...java/com/topjohnwu/magisk/core/download/BaseDownloader.kt
+2
-2
ManagerHandler.kt
...java/com/topjohnwu/magisk/core/download/ManagerHandler.kt
+3
-24
Subject.kt
...c/main/java/com/topjohnwu/magisk/core/download/Subject.kt
+3
-7
SuRequestHandler.kt
...ain/java/com/topjohnwu/magisk/core/su/SuRequestHandler.kt
+1
-1
HideAPK.kt
app/src/main/java/com/topjohnwu/magisk/core/tasks/HideAPK.kt
+73
-22
PreferenceModel.kt
...a/com/topjohnwu/magisk/data/preference/PreferenceModel.kt
+8
-10
ManagerInstallDialog.kt
...om/topjohnwu/magisk/events/dialog/ManagerInstallDialog.kt
+1
-2
SettingsItems.kt
...in/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt
+4
-4
SettingsViewModel.kt
...ava/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt
+3
-11
Notifications.kt
app/src/main/java/com/topjohnwu/magisk/view/Notifications.kt
+1
-2
manager.sh
app/src/main/res/raw/manager.sh
+1
-1
strings.xml
app/src/main/res/values/strings.xml
+2
-1
No files found.
app/src/main/java/com/topjohnwu/magisk/core/Config.kt
View file @
2e4dc91b
package
com.topjohnwu.magisk.core
package
com.topjohnwu.magisk.core
import
android.annotation.SuppressLint
import
android.content.Context
import
android.content.Context
import
android.content.SharedPreferences
import
android.content.SharedPreferences
import
android.util.Xml
import
android.util.Xml
...
@@ -9,19 +10,16 @@ import com.topjohnwu.magisk.BuildConfig
...
@@ -9,19 +10,16 @@ import com.topjohnwu.magisk.BuildConfig
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
com.topjohnwu.magisk.core.utils.BiometricHelper
import
com.topjohnwu.magisk.core.utils.BiometricHelper
import
com.topjohnwu.magisk.core.utils.defaultLocale
import
com.topjohnwu.magisk.core.utils.refreshLocale
import
com.topjohnwu.magisk.core.utils.refreshLocale
import
com.topjohnwu.magisk.data.preference.PreferenceModel
import
com.topjohnwu.magisk.data.preference.PreferenceModel
import
com.topjohnwu.magisk.data.repository.DBConfig
import
com.topjohnwu.magisk.data.repository.DBConfig
import
com.topjohnwu.magisk.di.Protected
import
com.topjohnwu.magisk.di.Protected
import
com.topjohnwu.magisk.ktx.get
import
com.topjohnwu.magisk.ktx.inject
import
com.topjohnwu.magisk.ktx.inject
import
com.topjohnwu.magisk.ui.theme.Theme
import
com.topjohnwu.magisk.ui.theme.Theme
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.io.SuFile
import
com.topjohnwu.superuser.io.SuFileInputStream
import
org.xmlpull.v1.XmlPullParser
import
org.xmlpull.v1.XmlPullParser
import
java.io.File
import
java.io.File
import
java.io.IOException
import
java.io.InputStream
object
Config
:
PreferenceModel
,
DBConfig
{
object
Config
:
PreferenceModel
,
DBConfig
{
...
@@ -29,6 +27,15 @@ object Config : PreferenceModel, DBConfig {
...
@@ -29,6 +27,15 @@ object Config : PreferenceModel, DBConfig {
override
val
settingsDao
:
SettingsDao
by
inject
()
override
val
settingsDao
:
SettingsDao
by
inject
()
override
val
context
:
Context
by
inject
(
Protected
)
override
val
context
:
Context
by
inject
(
Protected
)
@get
:
SuppressLint
(
"ApplySharedPref"
)
val
prefsFile
:
File
get
()
{
// Flush prefs to disk
prefs
.
edit
().
apply
{
remove
(
Key
.
ASKED_HOME
)
}.
commit
()
return
File
(
"${context.filesDir.parent}/shared_prefs"
,
"${fileName}.xml"
)
}
object
Key
{
object
Key
{
// db configs
// db configs
const
val
ROOT_ACCESS
=
"root_access"
const
val
ROOT_ACCESS
=
"root_access"
...
@@ -119,7 +126,7 @@ object Config : PreferenceModel, DBConfig {
...
@@ -119,7 +126,7 @@ object Config : PreferenceModel, DBConfig {
var
repoOrder
by
preference
(
Key
.
REPO_ORDER
,
Value
.
ORDER_DATE
)
var
repoOrder
by
preference
(
Key
.
REPO_ORDER
,
Value
.
ORDER_DATE
)
var
suDefaultTimeout
by
preferenceStrInt
(
Key
.
SU_REQUEST_TIMEOUT
,
10
)
var
suDefaultTimeout
by
preferenceStrInt
(
Key
.
SU_REQUEST_TIMEOUT
,
10
)
var
suAutoReponse
by
preferenceStrInt
(
Key
.
SU_AUTO_RESPONSE
,
Value
.
SU_PROMPT
)
var
suAutoRe
s
ponse
by
preferenceStrInt
(
Key
.
SU_AUTO_RESPONSE
,
Value
.
SU_PROMPT
)
var
suNotification
by
preferenceStrInt
(
Key
.
SU_NOTIFICATION
,
Value
.
NOTIFICATION_TOAST
)
var
suNotification
by
preferenceStrInt
(
Key
.
SU_NOTIFICATION
,
Value
.
NOTIFICATION_TOAST
)
var
updateChannel
by
preferenceStrInt
(
Key
.
UPDATE_CHANNEL
,
defaultChannel
)
var
updateChannel
by
preferenceStrInt
(
Key
.
UPDATE_CHANNEL
,
defaultChannel
)
...
@@ -150,8 +157,12 @@ object Config : PreferenceModel, DBConfig {
...
@@ -150,8 +157,12 @@ object Config : PreferenceModel, DBConfig {
private
const
val
SU_FINGERPRINT
=
"su_fingerprint"
private
const
val
SU_FINGERPRINT
=
"su_fingerprint"
fun
initialize
()
{
fun
load
(
pkg
:
String
)
{
prefs
.
edit
{
parsePrefs
()
}
try
{
context
.
contentResolver
.
openInputStream
(
Provider
.
PREFS_URI
(
pkg
))
?.
use
{
prefs
.
edit
{
parsePrefs
(
it
)
}
}
}
catch
(
e
:
IOException
)
{}
prefs
.
edit
{
prefs
.
edit
{
// Settings migration
// Settings migration
...
@@ -173,10 +184,8 @@ object Config : PreferenceModel, DBConfig {
...
@@ -173,10 +184,8 @@ object Config : PreferenceModel, DBConfig {
}
}
}
}
private
fun
SharedPreferences
.
Editor
.
parsePrefs
()
{
private
fun
SharedPreferences
.
Editor
.
parsePrefs
(
input
:
InputStream
)
{
val
config
=
SuFile
.
open
(
"/data/adb"
,
Const
.
MANAGER_CONFIGS
)
runCatching
{
if
(
config
.
exists
())
runCatching
{
val
input
=
SuFileInputStream
(
config
)
val
parser
=
Xml
.
newPullParser
()
val
parser
=
Xml
.
newPullParser
()
parser
.
setFeature
(
XmlPullParser
.
FEATURE_PROCESS_NAMESPACES
,
false
)
parser
.
setFeature
(
XmlPullParser
.
FEATURE_PROCESS_NAMESPACES
,
false
)
parser
.
setInput
(
input
,
"UTF-8"
)
parser
.
setInput
(
input
,
"UTF-8"
)
...
@@ -220,21 +229,6 @@ object Config : PreferenceModel, DBConfig {
...
@@ -220,21 +229,6 @@ object Config : PreferenceModel, DBConfig {
else
->
parser
.
next
()
else
->
parser
.
next
()
}
}
}
}
config
.
delete
()
}
}
}
}
fun
export
()
{
// Flush prefs to disk
prefs
.
edit
().
apply
{
remove
(
Key
.
ASKED_HOME
)
}.
commit
()
val
context
=
get
<
Context
>(
Protected
)
val
xml
=
File
(
"${context.filesDir.parent}/shared_prefs"
,
"${context.packageName}_preferences.xml"
)
Shell
.
su
(
"cat $xml > /data/adb/${Const.MANAGER_CONFIGS}"
).
exec
()
}
}
}
app/src/main/java/com/topjohnwu/magisk/core/Const.kt
View file @
2e4dc91b
...
@@ -46,7 +46,6 @@ object Const {
...
@@ -46,7 +46,6 @@ object Const {
}
}
object
Url
{
object
Url
{
const
val
ZIP_URL
=
"https://github.com/Magisk-Modules-Repo/%s/archive/master.zip"
const
val
PATREON_URL
=
"https://www.patreon.com/topjohnwu"
const
val
PATREON_URL
=
"https://www.patreon.com/topjohnwu"
const
val
SOURCE_CODE_URL
=
"https://github.com/topjohnwu/Magisk"
const
val
SOURCE_CODE_URL
=
"https://github.com/topjohnwu/Magisk"
...
@@ -58,11 +57,9 @@ object Const {
...
@@ -58,11 +57,9 @@ object Const {
}
}
object
Key
{
object
Key
{
// others
const
val
LINK_KEY
=
"Link"
const
val
ETAG_KEY
=
"ETag"
// intents
// intents
const
val
OPEN_SECTION
=
"section"
const
val
OPEN_SECTION
=
"section"
const
val
HIDDEN_PKG
=
"hidden_pkg"
}
}
object
Value
{
object
Value
{
...
...
app/src/main/java/com/topjohnwu/magisk/core/Provider.kt
View file @
2e4dc91b
...
@@ -2,9 +2,13 @@ package com.topjohnwu.magisk.core
...
@@ -2,9 +2,13 @@ package com.topjohnwu.magisk.core
import
android.content.Context
import
android.content.Context
import
android.content.pm.ProviderInfo
import
android.content.pm.ProviderInfo
import
android.net.Uri
import
android.os.Bundle
import
android.os.Bundle
import
android.os.ParcelFileDescriptor
import
android.os.ParcelFileDescriptor.MODE_READ_ONLY
import
com.topjohnwu.magisk.FileProvider
import
com.topjohnwu.magisk.FileProvider
import
com.topjohnwu.magisk.core.su.SuCallbackHandler
import
com.topjohnwu.magisk.core.su.SuCallbackHandler
import
java.io.File
open
class
Provider
:
FileProvider
()
{
open
class
Provider
:
FileProvider
()
{
...
@@ -16,4 +20,20 @@ open class Provider : FileProvider() {
...
@@ -16,4 +20,20 @@ open class Provider : FileProvider() {
SuCallbackHandler
(
context
!!
,
method
,
extras
)
SuCallbackHandler
(
context
!!
,
method
,
extras
)
return
Bundle
.
EMPTY
return
Bundle
.
EMPTY
}
}
override
fun
openFile
(
uri
:
Uri
,
mode
:
String
):
ParcelFileDescriptor
?
{
return
when
(
uri
.
encodedPath
?:
return
null
)
{
"/apk_file"
->
ParcelFileDescriptor
.
open
(
File
(
context
!!
.
packageCodePath
),
MODE_READ_ONLY
)
"/prefs_file"
->
ParcelFileDescriptor
.
open
(
Config
.
prefsFile
,
MODE_READ_ONLY
)
else
->
super
.
openFile
(
uri
,
mode
)
}
}
companion
object
{
fun
APK_URI
(
pkg
:
String
)
=
Uri
.
Builder
().
scheme
(
"content"
).
authority
(
"$pkg.provider"
).
path
(
"apk_file"
).
build
()
fun
PREFS_URI
(
pkg
:
String
)
=
Uri
.
Builder
().
scheme
(
"content"
).
authority
(
"$pkg.provider"
).
path
(
"prefs_file"
).
build
()
}
}
}
app/src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt
View file @
2e4dc91b
...
@@ -3,9 +3,9 @@ package com.topjohnwu.magisk.core
...
@@ -3,9 +3,9 @@ package com.topjohnwu.magisk.core
import
android.app.Activity
import
android.app.Activity
import
android.content.Context
import
android.content.Context
import
android.os.Bundle
import
android.os.Bundle
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.BuildConfig
.APPLICATION_ID
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.
network.RawServices
import
com.topjohnwu.magisk.data.
repository.NetworkService
import
com.topjohnwu.magisk.ktx.get
import
com.topjohnwu.magisk.ktx.get
import
com.topjohnwu.magisk.ui.MainActivity
import
com.topjohnwu.magisk.ui.MainActivity
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.magisk.view.Notifications
...
@@ -29,18 +29,18 @@ open class SplashActivity : Activity() {
...
@@ -29,18 +29,18 @@ open class SplashActivity : Activity() {
}
}
}
}
private
fun
handleRepackage
()
{
private
fun
handleRepackage
(
pkg
:
String
?)
{
val
pkg
=
Config
.
suManager
if
(
packageName
!=
APPLICATION_ID
)
{
if
(
Config
.
suManager
.
isNotEmpty
()
&&
packageName
==
BuildConfig
.
APPLICATION_ID
)
{
Config
.
suManager
=
""
Shell
.
su
(
"(pm uninstall $pkg)& >/dev/null 2>&1"
).
exec
()
}
if
(
pkg
==
packageName
)
{
runCatching
{
runCatching
{
//
We are the manager, remove com.topjohnwu.magisk
as it could be malware
//
Hidden, remove com.topjohnwu.magisk if exist
as it could be malware
packageManager
.
getApplicationInfo
(
BuildConfig
.
APPLICATION_ID
,
0
)
packageManager
.
getApplicationInfo
(
APPLICATION_ID
,
0
)
Shell
.
su
(
"(pm uninstall $
{BuildConfig.APPLICATION_ID}
)& >/dev/null 2>&1"
).
exec
()
Shell
.
su
(
"(pm uninstall $
APPLICATION_ID
)& >/dev/null 2>&1"
).
exec
()
}
}
}
else
{
if
(
Config
.
suManager
.
isNotEmpty
())
Config
.
suManager
=
""
pkg
?:
return
Shell
.
su
(
"(pm uninstall $pkg)& >/dev/null 2>&1"
).
exec
()
}
}
}
}
...
@@ -48,14 +48,16 @@ open class SplashActivity : Activity() {
...
@@ -48,14 +48,16 @@ open class SplashActivity : Activity() {
// Pre-initialize root shell
// Pre-initialize root shell
Shell
.
getShell
()
Shell
.
getShell
()
Config
.
initialize
()
val
hiddenPackage
=
intent
.
getStringExtra
(
Const
.
Key
.
HIDDEN_PKG
)
handleRepackage
()
Config
.
load
(
hiddenPackage
?:
APPLICATION_ID
)
handleRepackage
(
hiddenPackage
)
Notifications
.
setup
(
this
)
Notifications
.
setup
(
this
)
UpdateCheckService
.
schedule
(
this
)
UpdateCheckService
.
schedule
(
this
)
Shortcuts
.
setupDynamic
(
this
)
Shortcuts
.
setupDynamic
(
this
)
// Pre-fetch network s
tuff
s
// Pre-fetch network s
ervice
s
get
<
RawServices
>()
get
<
NetworkService
>()
DONE
=
true
DONE
=
true
...
...
app/src/main/java/com/topjohnwu/magisk/core/download/BaseDownloader.kt
View file @
2e4dc91b
...
@@ -69,8 +69,8 @@ abstract class BaseDownloader : BaseService(), KoinComponent {
...
@@ -69,8 +69,8 @@ abstract class BaseDownloader : BaseService(), KoinComponent {
// -- Download logic
// -- Download logic
private
suspend
fun
Subject
.
startDownload
()
{
private
suspend
fun
Subject
.
startDownload
()
{
val
skip
=
this
is
Subject
.
Magisk
&&
file
.
checkSum
(
"MD5"
,
magisk
.
md5
)
val
skip
Dl
=
this
is
Subject
.
Magisk
&&
file
.
checkSum
(
"MD5"
,
magisk
.
md5
)
if
(!
skip
)
{
if
(!
skip
Dl
)
{
val
stream
=
service
.
fetchFile
(
url
).
toProgressStream
(
this
)
val
stream
=
service
.
fetchFile
(
url
).
toProgressStream
(
this
)
when
(
this
)
{
when
(
this
)
{
is
Subject
.
Module
->
// Download and process on-the-fly
is
Subject
.
Module
->
// Download and process on-the-fly
...
...
app/src/main/java/com/topjohnwu/magisk/core/download/ManagerHandler.kt
View file @
2e4dc91b
...
@@ -5,20 +5,16 @@ import androidx.core.net.toFile
...
@@ -5,20 +5,16 @@ import androidx.core.net.toFile
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.download.Action.APK.Restore
import
com.topjohnwu.magisk.core.download.Action.APK.Upgrade
import
com.topjohnwu.magisk.core.isRunningAsStub
import
com.topjohnwu.magisk.core.isRunningAsStub
import
com.topjohnwu.magisk.core.tasks.
Patch
APK
import
com.topjohnwu.magisk.core.tasks.
Hide
APK
import
com.topjohnwu.magisk.ktx.relaunchApp
import
com.topjohnwu.magisk.ktx.relaunchApp
import
com.topjohnwu.magisk.ktx.writeTo
import
com.topjohnwu.magisk.ktx.writeTo
import
com.topjohnwu.superuser.Shell
import
java.io.File
import
java.io.File
private
fun
Context
.
patch
(
apk
:
File
)
{
private
fun
Context
.
patch
(
apk
:
File
)
{
val
patched
=
File
(
apk
.
parent
,
"patched.apk"
)
val
patched
=
File
(
apk
.
parent
,
"patched.apk"
)
Patch
APK
.
patch
(
this
,
apk
.
path
,
patched
.
path
,
packageName
,
applicationInfo
.
nonLocalizedLabel
)
Hide
APK
.
patch
(
this
,
apk
.
path
,
patched
.
path
,
packageName
,
applicationInfo
.
nonLocalizedLabel
)
apk
.
delete
()
apk
.
delete
()
patched
.
renameTo
(
apk
)
patched
.
renameTo
(
apk
)
}
}
...
@@ -31,7 +27,7 @@ private fun BaseDownloader.notifyHide(id: Int) {
...
@@ -31,7 +27,7 @@ private fun BaseDownloader.notifyHide(id: Int) {
}
}
}
}
private
suspend
fun
BaseDownloader
.
upgrade
(
subject
:
Subject
.
Manager
)
{
suspend
fun
BaseDownloader
.
handleAPK
(
subject
:
Subject
.
Manager
)
{
val
apk
=
subject
.
file
.
toFile
()
val
apk
=
subject
.
file
.
toFile
()
val
id
=
subject
.
notifyID
()
val
id
=
subject
.
notifyID
()
if
(
isRunningAsStub
)
{
if
(
isRunningAsStub
)
{
...
@@ -53,20 +49,3 @@ private suspend fun BaseDownloader.upgrade(subject: Subject.Manager) {
...
@@ -53,20 +49,3 @@ private suspend fun BaseDownloader.upgrade(subject: Subject.Manager) {
patch
(
apk
)
patch
(
apk
)
}
}
}
}
private
fun
BaseDownloader
.
restore
(
apk
:
File
,
id
:
Int
)
{
update
(
id
)
{
it
.
setProgress
(
0
,
0
,
true
)
.
setProgress
(
0
,
0
,
true
)
.
setContentTitle
(
getString
(
R
.
string
.
restore_img_msg
))
.
setContentText
(
""
)
}
Config
.
export
()
Shell
.
su
(
"pm install $apk && pm uninstall $packageName"
).
exec
()
}
suspend
fun
BaseDownloader
.
handleAPK
(
subject
:
Subject
.
Manager
)
=
when
(
subject
.
action
)
{
is
Upgrade
->
upgrade
(
subject
)
is
Restore
->
restore
(
subject
.
file
.
toFile
(),
subject
.
notifyID
())
}
app/src/main/java/com/topjohnwu/magisk/core/download/Subject.kt
View file @
2e4dc91b
...
@@ -40,16 +40,12 @@ sealed class Subject : Parcelable {
...
@@ -40,16 +40,12 @@ sealed class Subject : Parcelable {
@Parcelize
@Parcelize
class
Manager
(
class
Manager
(
override
val
action
:
Action
.
APK
,
private
val
app
:
ManagerJson
=
Info
.
remote
.
app
,
private
val
app
:
ManagerJson
=
Info
.
remote
.
app
,
val
stub
:
StubJson
=
Info
.
remote
.
stub
val
stub
:
StubJson
=
Info
.
remote
.
stub
)
:
Subject
()
{
)
:
Subject
()
{
override
val
action
get
()
=
Action
.
Download
override
val
title
:
String
override
val
title
:
String
get
()
=
"MagiskManager-${app.version}(${app.versionCode})"
get
()
=
"MagiskManager-${app.version}(${app.versionCode})"
override
val
url
:
String
get
()
=
app
.
link
override
val
url
:
String
get
()
=
app
.
link
@IgnoredOnParcel
@IgnoredOnParcel
override
val
file
by
lazy
{
override
val
file
by
lazy
{
...
...
app/src/main/java/com/topjohnwu/magisk/core/su/SuRequestHandler.kt
View file @
2e4dc91b
...
@@ -36,7 +36,7 @@ class SuRequestHandler(
...
@@ -36,7 +36,7 @@ class SuRequestHandler(
if
(
policy
.
packageName
==
BuildConfig
.
APPLICATION_ID
)
if
(
policy
.
packageName
==
BuildConfig
.
APPLICATION_ID
)
return
false
return
false
when
(
Config
.
suAutoReponse
)
{
when
(
Config
.
suAutoRe
s
ponse
)
{
Config
.
Value
.
SU_AUTO_DENY
->
{
Config
.
Value
.
SU_AUTO_DENY
->
{
respond
(
SuPolicy
.
DENY
,
0
)
respond
(
SuPolicy
.
DENY
,
0
)
return
false
return
false
...
...
app/src/main/java/com/topjohnwu/magisk/core/tasks/
Patch
APK.kt
→
app/src/main/java/com/topjohnwu/magisk/core/tasks/
Hide
APK.kt
View file @
2e4dc91b
package
com.topjohnwu.magisk.core.tasks
package
com.topjohnwu.magisk.core.tasks
import
android.app.ProgressDialog
import
android.content.Context
import
android.content.Context
import
android.content.Intent
import
android.os.Build.VERSION.SDK_INT
import
android.os.Build.VERSION.SDK_INT
import
android.widget.Toast
import
android.widget.Toast
import
com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.*
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.isRunningAsStub
import
com.topjohnwu.magisk.core.utils.AXML
import
com.topjohnwu.magisk.core.utils.AXML
import
com.topjohnwu.magisk.core.utils.Keygen
import
com.topjohnwu.magisk.core.utils.Keygen
import
com.topjohnwu.magisk.data.repository.NetworkService
import
com.topjohnwu.magisk.data.repository.NetworkService
import
com.topjohnwu.magisk.ktx.
ge
t
import
com.topjohnwu.magisk.ktx.
injec
t
import
com.topjohnwu.magisk.ktx.writeTo
import
com.topjohnwu.magisk.ktx.writeTo
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.signing.JarMap
import
com.topjohnwu.signing.JarMap
import
com.topjohnwu.signing.SignApk
import
com.topjohnwu.signing.SignApk
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
...
@@ -28,18 +28,20 @@ import java.io.FileOutputStream
...
@@ -28,18 +28,20 @@ import java.io.FileOutputStream
import
java.io.IOException
import
java.io.IOException
import
java.security.SecureRandom
import
java.security.SecureRandom
object
Patch
APK
{
object
Hide
APK
{
private
const
val
ALPHA
=
"abcdefghijklmnopqrstuvwxyz"
private
const
val
ALPHA
=
"abcdefghijklmnopqrstuvwxyz"
private
const
val
ALPHADOTS
=
"$ALPHA....."
private
const
val
ALPHADOTS
=
"$ALPHA....."
private
const
val
APP_ID
=
"com.topjohnwu.magisk"
private
const
val
APP_NAME
=
"Magisk Manager"
private
const
val
APP_NAME
=
"Magisk Manager"
// Some arbitrary limit
// Some arbitrary limit
const
val
MAX_LABEL_LENGTH
=
32
const
val
MAX_LABEL_LENGTH
=
32
private
fun
genPackageName
():
CharSequence
{
private
val
svc
:
NetworkService
by
inject
()
private
val
Context
.
APK_URI
get
()
=
Provider
.
APK_URI
(
packageName
)
private
val
Context
.
PREFS_URI
get
()
=
Provider
.
PREFS_URI
(
packageName
)
private
fun
genPackageName
():
String
{
val
random
=
SecureRandom
()
val
random
=
SecureRandom
()
val
len
=
5
+
random
.
nextInt
(
15
)
val
len
=
5
+
random
.
nextInt
(
15
)
val
builder
=
StringBuilder
(
len
)
val
builder
=
StringBuilder
(
len
)
...
@@ -59,20 +61,20 @@ object PatchAPK {
...
@@ -59,20 +61,20 @@ object PatchAPK {
val
idx
=
random
.
nextInt
(
len
-
1
)
val
idx
=
random
.
nextInt
(
len
-
1
)
builder
[
idx
]
=
'.'
builder
[
idx
]
=
'.'
}
}
return
builder
return
builder
.
toString
()
}
}
fun
patch
(
fun
patch
(
context
:
Context
,
context
:
Context
,
apk
:
String
,
out
:
String
,
apk
:
String
,
out
:
String
,
pkg
:
CharSequence
,
label
:
CharSequence
pkg
:
String
,
label
:
CharSequence
):
Boolean
{
):
Boolean
{
try
{
try
{
val
jar
=
JarMap
.
open
(
apk
)
val
jar
=
JarMap
.
open
(
apk
)
val
je
=
jar
.
getJarEntry
(
Const
.
ANDROID_MANIFEST
)
val
je
=
jar
.
getJarEntry
(
Const
.
ANDROID_MANIFEST
)
val
xml
=
AXML
(
jar
.
getRawData
(
je
))
val
xml
=
AXML
(
jar
.
getRawData
(
je
))
if
(!
xml
.
findAndPatch
(
APP
_ID
to
pkg
.
toString
()
,
APP_NAME
to
label
.
toString
()))
if
(!
xml
.
findAndPatch
(
APP
LICATION_ID
to
pkg
,
APP_NAME
to
label
.
toString
()))
return
false
return
false
// Write apk changes
// Write apk changes
...
@@ -91,7 +93,6 @@ object PatchAPK {
...
@@ -91,7 +93,6 @@ object PatchAPK {
val
dlStub
=
!
isRunningAsStub
&&
SDK_INT
>=
28
&&
Const
.
Version
.
atLeast_20_2
()
val
dlStub
=
!
isRunningAsStub
&&
SDK_INT
>=
28
&&
Const
.
Version
.
atLeast_20_2
()
val
src
=
if
(
dlStub
)
{
val
src
=
if
(
dlStub
)
{
val
stub
=
File
(
context
.
cacheDir
,
"stub.apk"
)
val
stub
=
File
(
context
.
cacheDir
,
"stub.apk"
)
val
svc
=
get
<
NetworkService
>()
try
{
try
{
svc
.
fetchFile
(
Info
.
remote
.
stub
.
link
).
byteStream
().
use
{
svc
.
fetchFile
(
Info
.
remote
.
stub
.
link
).
byteStream
().
use
{
it
.
writeTo
(
stub
)
it
.
writeTo
(
stub
)
...
@@ -117,23 +118,73 @@ object PatchAPK {
...
@@ -117,23 +118,73 @@ object PatchAPK {
if
(!
Shell
.
su
(
"adb_pm_install $repack"
).
exec
().
isSuccess
)
if
(!
Shell
.
su
(
"adb_pm_install $repack"
).
exec
().
isSuccess
)
return
false
return
false
Config
.
suManager
=
pkg
.
toString
()
context
.
apply
{
Config
.
export
()
val
intent
=
packageManager
.
getLaunchIntentForPackage
(
pkg
)
?:
return
false
Shell
.
su
(
"pm uninstall $APP_ID"
).
submit
()
Config
.
suManager
=
pkg
grantUriPermission
(
pkg
,
APK_URI
,
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
)
grantUriPermission
(
pkg
,
PREFS_URI
,
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
)
startActivity
(
intent
)
}
return
true
return
true
}
}
fun
hideManager
(
context
:
Context
,
label
:
String
)
{
@Suppress
(
"DEPRECATION"
)
val
progress
=
Notifications
.
progress
(
context
,
context
.
getString
(
R
.
string
.
hide_manager_title
))
fun
hide
(
context
:
Context
,
label
:
String
)
{
Notifications
.
mgr
.
notify
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
,
progress
.
build
()
)
val
dialog
=
ProgressDialog
.
show
(
context
,
context
.
getString
(
R
.
string
.
hide_manager_title
),
""
,
true
)
GlobalScope
.
launch
{
GlobalScope
.
launch
{
val
result
=
withContext
(
Dispatchers
.
IO
)
{
val
result
=
withContext
(
Dispatchers
.
IO
)
{
patchAndHide
(
context
,
label
)
patchAndHide
(
context
,
label
)
}
}
if
(!
result
)
if
(!
result
)
{
Utils
.
toast
(
R
.
string
.
hide_manager_fail_toast
,
Toast
.
LENGTH_LONG
)
Utils
.
toast
(
R
.
string
.
hide_manager_fail_toast
,
Toast
.
LENGTH_LONG
)
Notifications
.
mgr
.
cancel
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
)
dialog
.
dismiss
()
}
}
}
private
suspend
fun
downloadAndRestore
(
context
:
Context
):
Boolean
{
val
apk
=
if
(
isRunningAsStub
)
{
DynAPK
.
current
(
context
)
}
else
{
File
(
context
.
cacheDir
,
"manager.apk"
).
also
{
apk
->
try
{
svc
.
fetchFile
(
Info
.
remote
.
app
.
link
).
byteStream
().
use
{
it
.
writeTo
(
apk
)
}
}
catch
(
e
:
IOException
)
{
Timber
.
e
(
e
)
return
false
}
}
}
if
(!
Shell
.
su
(
"adb_pm_install $apk"
).
exec
().
isSuccess
)
return
false
context
.
apply
{
val
intent
=
packageManager
.
getLaunchIntentForPackage
(
APPLICATION_ID
)
?:
return
false
Config
.
suManager
=
""
grantUriPermission
(
APPLICATION_ID
,
APK_URI
,
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
)
grantUriPermission
(
APPLICATION_ID
,
PREFS_URI
,
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
)
intent
.
putExtra
(
Const
.
Key
.
HIDDEN_PKG
,
packageName
)
startActivity
(
intent
)
}
return
true
}
@Suppress
(
"DEPRECATION"
)
fun
restore
(
context
:
Context
)
{
val
dialog
=
ProgressDialog
.
show
(
context
,
context
.
getString
(
R
.
string
.
restore_img_msg
),
""
,
true
)
GlobalScope
.
launch
{
val
result
=
withContext
(
Dispatchers
.
IO
)
{
downloadAndRestore
(
context
)
}
if
(!
result
)
{
Utils
.
toast
(
R
.
string
.
restore_manager_fail_toast
,
Toast
.
LENGTH_LONG
)
dialog
.
dismiss
()
}
}
}
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/data/preference/PreferenceModel.kt
View file @
2e4dc91b
...
@@ -11,16 +11,14 @@ interface PreferenceModel {
...
@@ -11,16 +11,14 @@ interface PreferenceModel {
val
fileName
:
String
val
fileName
:
String
get
()
=
"${context.packageName}_preferences"
get
()
=
"${context.packageName}_preferences"
val
commitPrefs
:
Boolean
get
()
=
false
val
prefs
:
SharedPreferences
val
prefs
:
SharedPreferences
get
()
=
context
.
getSharedPreferences
(
fileName
,
Context
.
MODE_PRIVATE
)
get
()
=
context
.
getSharedPreferences
(
fileName
,
Context
.
MODE_PRIVATE
)
fun
preferenceStrInt
(
fun
preferenceStrInt
(
name
:
String
,
name
:
String
,
default
:
Int
,
default
:
Int
,
writeDefault
:
Boolean
=
false
,
commit
:
Boolean
=
false
commit
:
Boolean
=
commitPrefs
)
=
object
:
ReadWriteProperty
<
PreferenceModel
,
Int
>
{
)
=
object
:
ReadWriteProperty
<
PreferenceModel
,
Int
>
{
val
base
=
StringProperty
(
name
,
default
.
toString
(),
commit
)
val
base
=
StringProperty
(
name
,
default
.
toString
(),
commit
)
override
fun
getValue
(
thisRef
:
PreferenceModel
,
property
:
KProperty
<
*
>):
Int
=
override
fun
getValue
(
thisRef
:
PreferenceModel
,
property
:
KProperty
<
*
>):
Int
=
...
@@ -33,37 +31,37 @@ interface PreferenceModel {
...
@@ -33,37 +31,37 @@ interface PreferenceModel {
fun
preference
(
fun
preference
(
name
:
String
,
name
:
String
,
default
:
Boolean
,
default
:
Boolean
,
commit
:
Boolean
=
commitPrefs
commit
:
Boolean
=
false
)
=
BooleanProperty
(
name
,
default
,
commit
)
)
=
BooleanProperty
(
name
,
default
,
commit
)
fun
preference
(
fun
preference
(
name
:
String
,
name
:
String
,
default
:
Float
,
default
:
Float
,
commit
:
Boolean
=
commitPrefs
commit
:
Boolean
=
false
)
=
FloatProperty
(
name
,
default
,
commit
)
)
=
FloatProperty
(
name
,
default
,
commit
)
fun
preference
(
fun
preference
(
name
:
String
,
name
:
String
,
default
:
Int
,
default
:
Int
,
commit
:
Boolean
=
commitPrefs
commit
:
Boolean
=
false
)
=
IntProperty
(
name
,
default
,
commit
)
)
=
IntProperty
(
name
,
default
,
commit
)
fun
preference
(
fun
preference
(
name
:
String
,
name
:
String
,
default
:
Long
,
default
:
Long
,
commit
:
Boolean
=
commitPrefs
commit
:
Boolean
=
false
)
=
LongProperty
(
name
,
default
,
commit
)
)
=
LongProperty
(
name
,
default
,
commit
)
fun
preference
(
fun
preference
(
name
:
String
,
name
:
String
,
default
:
String
,
default
:
String
,
commit
:
Boolean
=
commitPrefs
commit
:
Boolean
=
false
)
=
StringProperty
(
name
,
default
,
commit
)
)
=
StringProperty
(
name
,
default
,
commit
)
fun
preference
(
fun
preference
(
name
:
String
,
name
:
String
,
default
:
Set
<
String
>,
default
:
Set
<
String
>,
commit
:
Boolean
=
commitPrefs
commit
:
Boolean
=
false
)
=
StringSetProperty
(
name
,
default
,
commit
)
)
=
StringSetProperty
(
name
,
default
,
commit
)
}
}
app/src/main/java/com/topjohnwu/magisk/events/dialog/ManagerInstallDialog.kt
View file @
2e4dc91b
...
@@ -2,7 +2,6 @@ package com.topjohnwu.magisk.events.dialog
...
@@ -2,7 +2,6 @@ package com.topjohnwu.magisk.events.dialog
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.download.Action
import
com.topjohnwu.magisk.core.download.DownloadService
import
com.topjohnwu.magisk.core.download.DownloadService
import
com.topjohnwu.magisk.core.download.Subject
import
com.topjohnwu.magisk.core.download.Subject
import
com.topjohnwu.magisk.ktx.res
import
com.topjohnwu.magisk.ktx.res
...
@@ -16,7 +15,7 @@ class ManagerInstallDialog : DialogEvent() {
...
@@ -16,7 +15,7 @@ class ManagerInstallDialog : DialogEvent() {
override
fun
build
(
dialog
:
MagiskDialog
)
{
override
fun
build
(
dialog
:
MagiskDialog
)
{
with
(
dialog
)
{
with
(
dialog
)
{
val
subject
=
Subject
.
Manager
(
Action
.
APK
.
Upgrade
)
val
subject
=
Subject
.
Manager
()
applyTitle
(
R
.
string
.
repo_install_title
.
res
(
R
.
string
.
app_name
.
res
()))
applyTitle
(
R
.
string
.
repo_install_title
.
res
(
R
.
string
.
app_name
.
res
()))
applyMessage
(
R
.
string
.
repo_install_msg
.
res
(
subject
.
title
))
applyMessage
(
R
.
string
.
repo_install_msg
.
res
(
subject
.
title
))
...
...
app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt
View file @
2e4dc91b
...
@@ -11,7 +11,7 @@ import com.topjohnwu.magisk.core.Config
...
@@ -11,7 +11,7 @@ import com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.UpdateCheckService
import
com.topjohnwu.magisk.core.UpdateCheckService
import
com.topjohnwu.magisk.core.tasks.
Patch
APK
import
com.topjohnwu.magisk.core.tasks.
Hide
APK
import
com.topjohnwu.magisk.core.utils.BiometricHelper
import
com.topjohnwu.magisk.core.utils.BiometricHelper
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils
import
com.topjohnwu.magisk.core.utils.availableLocales
import
com.topjohnwu.magisk.core.utils.availableLocales
...
@@ -90,7 +90,7 @@ object Hide : BaseSettingsItem.Input() {
...
@@ -90,7 +90,7 @@ object Hide : BaseSettingsItem.Input() {
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
result
,
BR
.
error
)
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
result
,
BR
.
error
)
val
maxLength
val
maxLength
get
()
=
Patch
APK
.
MAX_LABEL_LENGTH
get
()
=
Hide
APK
.
MAX_LABEL_LENGTH
@get
:
Bindable
@get
:
Bindable
val
isError
val
isError
...
@@ -288,9 +288,9 @@ object AutomaticResponse : BaseSettingsItem.Selector() {
...
@@ -288,9 +288,9 @@ object AutomaticResponse : BaseSettingsItem.Selector() {
override
val
entryRes
=
R
.
array
.
auto_response
override
val
entryRes
=
R
.
array
.
auto_response
override
val
entryValRes
=
R
.
array
.
value_array
override
val
entryValRes
=
R
.
array
.
value_array
override
var
value
=
Config
.
suAutoReponse
override
var
value
=
Config
.
suAutoRe
s
ponse
set
(
value
)
=
setV
(
value
,
field
,
{
field
=
it
})
{
set
(
value
)
=
setV
(
value
,
field
,
{
field
=
it
})
{
Config
.
suAutoReponse
=
entryValues
[
it
].
toInt
()
Config
.
suAutoRe
s
ponse
=
entryValues
[
it
].
toInt
()
}
}
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt
View file @
2e4dc91b
...
@@ -15,11 +15,8 @@ import com.topjohnwu.magisk.arch.diffListOf
...
@@ -15,11 +15,8 @@ import com.topjohnwu.magisk.arch.diffListOf
import
com.topjohnwu.magisk.arch.itemBindingOf
import
com.topjohnwu.magisk.arch.itemBindingOf
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.download.Action
import
com.topjohnwu.magisk.core.download.DownloadService
import
com.topjohnwu.magisk.core.download.Subject
import
com.topjohnwu.magisk.core.isRunningAsStub
import
com.topjohnwu.magisk.core.isRunningAsStub
import
com.topjohnwu.magisk.core.tasks.
Patch
APK
import
com.topjohnwu.magisk.core.tasks.
Hide
APK
import
com.topjohnwu.magisk.data.database.RepoDao
import
com.topjohnwu.magisk.data.database.RepoDao
import
com.topjohnwu.magisk.events.AddHomeIconEvent
import
com.topjohnwu.magisk.events.AddHomeIconEvent
import
com.topjohnwu.magisk.events.RecreateEvent
import
com.topjohnwu.magisk.events.RecreateEvent
...
@@ -104,7 +101,7 @@ class SettingsViewModel(
...
@@ -104,7 +101,7 @@ class SettingsViewModel(
is
Theme
->
SettingsFragmentDirections
.
actionSettingsFragmentToThemeFragment
().
publish
()
is
Theme
->
SettingsFragmentDirections
.
actionSettingsFragmentToThemeFragment
().
publish
()
is
ClearRepoCache
->
clearRepoCache
()
is
ClearRepoCache
->
clearRepoCache
()
is
SystemlessHosts
->
createHosts
()
is
SystemlessHosts
->
createHosts
()
is
Restore
->
restoreManager
(
)
is
Restore
->
HideAPK
.
restore
(
view
.
context
)
is
AddShortcut
->
AddHomeIconEvent
().
publish
()
is
AddShortcut
->
AddHomeIconEvent
().
publish
()
else
->
callback
()
else
->
callback
()
}
}
...
@@ -112,7 +109,7 @@ class SettingsViewModel(
...
@@ -112,7 +109,7 @@ class SettingsViewModel(
override
fun
onItemChanged
(
view
:
View
,
item
:
BaseSettingsItem
)
=
when
(
item
)
{
override
fun
onItemChanged
(
view
:
View
,
item
:
BaseSettingsItem
)
=
when
(
item
)
{
is
Language
->
RecreateEvent
().
publish
()
is
Language
->
RecreateEvent
().
publish
()
is
UpdateChannel
->
openUrlIfNecessary
(
view
)
is
UpdateChannel
->
openUrlIfNecessary
(
view
)
is
Hide
->
PatchAPK
.
hideManager
(
view
.
context
,
item
.
value
)
is
Hide
->
HideAPK
.
hide
(
view
.
context
,
item
.
value
)
else
->
Unit
else
->
Unit
}
}
...
@@ -142,9 +139,4 @@ class SettingsViewModel(
...
@@ -142,9 +139,4 @@ class SettingsViewModel(
Utils
.
toast
(
R
.
string
.
settings_hosts_toast
,
Toast
.
LENGTH_SHORT
)
Utils
.
toast
(
R
.
string
.
settings_hosts_toast
,
Toast
.
LENGTH_SHORT
)
}
}
}
}
private
fun
restoreManager
()
{
DownloadService
.
start
(
get
(),
Subject
.
Manager
(
Action
.
APK
.
Restore
))
}
}
}
app/src/main/java/com/topjohnwu/magisk/view/Notifications.kt
View file @
2e4dc91b
...
@@ -15,7 +15,6 @@ import com.topjohnwu.magisk.core.Const.ID.PROGRESS_NOTIFICATION_CHANNEL
...
@@ -15,7 +15,6 @@ import com.topjohnwu.magisk.core.Const.ID.PROGRESS_NOTIFICATION_CHANNEL
import
com.topjohnwu.magisk.core.Const.ID.UPDATE_NOTIFICATION_CHANNEL
import
com.topjohnwu.magisk.core.Const.ID.UPDATE_NOTIFICATION_CHANNEL
import
com.topjohnwu.magisk.core.SplashActivity
import
com.topjohnwu.magisk.core.SplashActivity
import
com.topjohnwu.magisk.core.cmp
import
com.topjohnwu.magisk.core.cmp
import
com.topjohnwu.magisk.core.download.Action
import
com.topjohnwu.magisk.core.download.DownloadService
import
com.topjohnwu.magisk.core.download.DownloadService
import
com.topjohnwu.magisk.core.download.Subject
import
com.topjohnwu.magisk.core.download.Subject
import
com.topjohnwu.magisk.core.intent
import
com.topjohnwu.magisk.core.intent
...
@@ -70,7 +69,7 @@ object Notifications {
...
@@ -70,7 +69,7 @@ object Notifications {
}
}
fun
managerUpdate
(
context
:
Context
)
{
fun
managerUpdate
(
context
:
Context
)
{
val
intent
=
DownloadService
.
pendingIntent
(
context
,
Subject
.
Manager
(
Action
.
APK
.
Upgrade
))
val
intent
=
DownloadService
.
pendingIntent
(
context
,
Subject
.
Manager
())
val
builder
=
updateBuilder
(
context
)
val
builder
=
updateBuilder
(
context
)
.
setContentTitle
(
context
.
getString
(
R
.
string
.
manager_update_title
))
.
setContentTitle
(
context
.
getString
(
R
.
string
.
manager_update_title
))
...
...
app/src/main/res/raw/manager.sh
View file @
2e4dc91b
...
@@ -90,7 +90,7 @@ EOF
...
@@ -90,7 +90,7 @@ EOF
}
}
adb_pm_install
()
{
adb_pm_install
()
{
local
tmp
=
/data/local/tmp/
patched
.apk
local
tmp
=
/data/local/tmp/
temp
.apk
cp
-f
"
$1
"
$tmp
cp
-f
"
$1
"
$tmp
chmod
644
$tmp
chmod
644
$tmp
su 2000
-c
pm
install
$tmp
||
pm
install
$tmp
su 2000
-c
pm
install
$tmp
||
pm
install
$tmp
...
...
app/src/main/res/values/strings.xml
View file @
2e4dc91b
...
@@ -217,7 +217,8 @@
...
@@ -217,7 +217,8 @@
<string
name=
"done"
>
Done!
</string>
<string
name=
"done"
>
Done!
</string>
<string
name=
"failure"
>
Failed
</string>
<string
name=
"failure"
>
Failed
</string>
<string
name=
"hide_manager_title"
>
Hiding Magisk Manager…
</string>
<string
name=
"hide_manager_title"
>
Hiding Magisk Manager…
</string>
<string
name=
"hide_manager_fail_toast"
>
Hide Magisk Manager failed.
</string>
<string
name=
"hide_manager_fail_toast"
>
Hide Magisk Manager failed
</string>
<string
name=
"restore_manager_fail_toast"
>
Restoring Magisk Manager failed
</string>
<string
name=
"open_link_failed_toast"
>
No application found to open the link
</string>
<string
name=
"open_link_failed_toast"
>
No application found to open the link
</string>
<string
name=
"complete_uninstall"
>
Complete Uninstall
</string>
<string
name=
"complete_uninstall"
>
Complete Uninstall
</string>
<string
name=
"restore_img"
>
Restore Images
</string>
<string
name=
"restore_img"
>
Restore Images
</string>
...
...
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