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
ff3d66a6
Commit
ff3d66a6
authored
Dec 13, 2018
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Separate backend logic from frontend UI
parent
006d28ab
Hide whitespace changes
Inline
Side-by-side
Showing
86 changed files
with
1189 additions
and
779 deletions
+1189
-779
.gitignore
app/.gitignore
+0
-1
build.gradle
app/build.gradle
+1
-0
proguard-rules.pro
app/proguard-rules.pro
+3
-6
AndroidManifest.xml
app/src/full/AndroidManifest.xml
+0
-3
a.java
app/src/full/java/a/a.java
+1
-1
g.java
app/src/full/java/a/g.java
+0
-7
q.java
app/src/full/java/a/q.java
+2
-2
AboutActivity.java
app/src/full/java/com/topjohnwu/magisk/AboutActivity.java
+6
-5
ClassMap.java
app/src/full/java/com/topjohnwu/magisk/ClassMap.java
+34
-0
DonationActivity.java
app/src/full/java/com/topjohnwu/magisk/DonationActivity.java
+4
-3
FlashActivity.java
app/src/full/java/com/topjohnwu/magisk/FlashActivity.java
+141
-49
MainActivity.java
app/src/full/java/com/topjohnwu/magisk/MainActivity.java
+9
-7
NoUIActivity.java
app/src/full/java/com/topjohnwu/magisk/NoUIActivity.java
+0
-13
SplashActivity.java
app/src/full/java/com/topjohnwu/magisk/SplashActivity.java
+14
-11
SuRequestActivity.java
...src/full/java/com/topjohnwu/magisk/SuRequestActivity.java
+6
-4
ApplicationAdapter.java
...ava/com/topjohnwu/magisk/adapters/ApplicationAdapter.java
+3
-3
ModulesAdapter.java
...ll/java/com/topjohnwu/magisk/adapters/ModulesAdapter.java
+1
-1
PolicyAdapter.java
...ull/java/com/topjohnwu/magisk/adapters/PolicyAdapter.java
+2
-2
ReposAdapter.java
...full/java/com/topjohnwu/magisk/adapters/ReposAdapter.java
+5
-5
SuLogAdapter.java
...full/java/com/topjohnwu/magisk/adapters/SuLogAdapter.java
+2
-2
FlashZip.java
app/src/full/java/com/topjohnwu/magisk/asyncs/FlashZip.java
+0
-104
BaseActivity.java
...ll/java/com/topjohnwu/magisk/components/BaseActivity.java
+22
-24
BaseFragment.java
...ll/java/com/topjohnwu/magisk/components/BaseFragment.java
+4
-5
EnvFixDialog.java
...ll/java/com/topjohnwu/magisk/components/EnvFixDialog.java
+25
-2
InstallMethodDialog.java
.../com/topjohnwu/magisk/components/InstallMethodDialog.java
+10
-10
MagiskInstallDialog.java
.../com/topjohnwu/magisk/components/MagiskInstallDialog.java
+14
-16
ManagerInstallDialog.java
...com/topjohnwu/magisk/components/ManagerInstallDialog.java
+9
-12
MarkDownWindow.java
.../java/com/topjohnwu/magisk/components/MarkDownWindow.java
+9
-11
Notifications.java
...l/java/com/topjohnwu/magisk/components/Notifications.java
+30
-29
ProgressNotification.java
...com/topjohnwu/magisk/components/ProgressNotification.java
+6
-8
SnackbarMaker.java
...l/java/com/topjohnwu/magisk/components/SnackbarMaker.java
+1
-1
UninstallDialog.java
...java/com/topjohnwu/magisk/components/UninstallDialog.java
+5
-4
MagiskFragment.java
...l/java/com/topjohnwu/magisk/fragments/MagiskFragment.java
+11
-11
MagiskHideFragment.java
...va/com/topjohnwu/magisk/fragments/MagiskHideFragment.java
+1
-1
MagiskLogFragment.java
...ava/com/topjohnwu/magisk/fragments/MagiskLogFragment.java
+2
-2
ModulesFragment.java
.../java/com/topjohnwu/magisk/fragments/ModulesFragment.java
+6
-6
ReposFragment.java
...ll/java/com/topjohnwu/magisk/fragments/ReposFragment.java
+9
-9
SettingsFragment.java
...java/com/topjohnwu/magisk/fragments/SettingsFragment.java
+30
-30
SuLogFragment.java
...ll/java/com/topjohnwu/magisk/fragments/SuLogFragment.java
+2
-2
SuperuserFragment.java
...ava/com/topjohnwu/magisk/fragments/SuperuserFragment.java
+3
-3
GeneralReceiver.java
.../java/com/topjohnwu/magisk/receivers/GeneralReceiver.java
+13
-12
ShortcutReceiver.java
...java/com/topjohnwu/magisk/receivers/ShortcutReceiver.java
+25
-25
OnBootService.java
...ull/java/com/topjohnwu/magisk/services/OnBootService.java
+3
-3
UpdateCheckService.java
...ava/com/topjohnwu/magisk/services/UpdateCheckService.java
+12
-2
AppUtils.java
app/src/full/java/com/topjohnwu/magisk/utils/AppUtils.java
+50
-0
DownloadApp.java
...src/full/java/com/topjohnwu/magisk/utils/DownloadApp.java
+14
-14
DownloadModule.java
.../full/java/com/topjohnwu/magisk/utils/DownloadModule.java
+9
-11
FingerprintHelper.java
...ll/java/com/topjohnwu/magisk/utils/FingerprintHelper.java
+8
-10
PatchAPK.java
app/src/full/java/com/topjohnwu/magisk/utils/PatchAPK.java
+13
-13
SuConnector.java
...src/full/java/com/topjohnwu/magisk/utils/SuConnector.java
+12
-13
Download.java
app/src/main/java/com/topjohnwu/magisk/utils/Download.java
+0
-6
build.py
build.py
+1
-1
.gitignore
core/.gitignore
+2
-0
build.gradle
core/build.gradle
+33
-0
proguard-rules.pro
core/proguard-rules.pro
+21
-0
AndroidManifest.xml
core/src/main/AndroidManifest.xml
+2
-0
App.java
core/src/main/java/com/topjohnwu/core/App.java
+15
-14
Const.java
core/src/main/java/com/topjohnwu/core/Const.java
+2
-2
Data.java
core/src/main/java/com/topjohnwu/core/Data.java
+16
-52
BaseModule.java
...rc/main/java/com/topjohnwu/core/container/BaseModule.java
+1
-1
Module.java
core/src/main/java/com/topjohnwu/core/container/Module.java
+1
-1
Policy.java
core/src/main/java/com/topjohnwu/core/container/Policy.java
+2
-2
Repo.java
core/src/main/java/com/topjohnwu/core/container/Repo.java
+5
-6
SuLogEntry.java
...rc/main/java/com/topjohnwu/core/container/SuLogEntry.java
+2
-2
TarEntry.java
.../src/main/java/com/topjohnwu/core/container/TarEntry.java
+1
-1
ValueSortedMap.java
...ain/java/com/topjohnwu/core/container/ValueSortedMap.java
+1
-1
MagiskDB.java
core/src/main/java/com/topjohnwu/core/database/MagiskDB.java
+8
-8
RepoDatabaseHelper.java
.../java/com/topjohnwu/core/database/RepoDatabaseHelper.java
+13
-16
CheckUpdates.java
.../src/main/java/com/topjohnwu/core/tasks/CheckUpdates.java
+9
-15
FlashZip.java
core/src/main/java/com/topjohnwu/core/tasks/FlashZip.java
+83
-0
MagiskInstaller.java
...c/main/java/com/topjohnwu/core/tasks/MagiskInstaller.java
+288
-0
ParallelTask.java
.../src/main/java/com/topjohnwu/core/tasks/ParallelTask.java
+1
-1
SafetyNet.java
core/src/main/java/com/topjohnwu/core/tasks/SafetyNet.java
+6
-6
UpdateRepos.java
core/src/main/java/com/topjohnwu/core/tasks/UpdateRepos.java
+18
-23
BootSigner.java
core/src/main/java/com/topjohnwu/core/utils/BootSigner.java
+1
-1
ISafetyNetHelper.java
.../main/java/com/topjohnwu/core/utils/ISafetyNetHelper.java
+1
-1
LocaleManager.java
...src/main/java/com/topjohnwu/core/utils/LocaleManager.java
+9
-13
Logger.java
core/src/main/java/com/topjohnwu/core/utils/Logger.java
+3
-3
RootUtils.java
core/src/main/java/com/topjohnwu/core/utils/RootUtils.java
+4
-4
Topic.java
core/src/main/java/com/topjohnwu/core/utils/Topic.java
+3
-3
Utils.java
core/src/main/java/com/topjohnwu/core/utils/Utils.java
+40
-73
ZipUtils.java
core/src/main/java/com/topjohnwu/core/utils/ZipUtils.java
+1
-1
bootctl
core/src/main/res/raw/bootctl
+0
-0
nonroot_utils.sh
core/src/main/res/raw/nonroot_utils.sh
+0
-0
utils.sh
core/src/main/res/raw/utils.sh
+3
-3
settings.gradle
settings.gradle
+1
-1
No files found.
app/.gitignore
View file @
ff3d66a6
...
...
@@ -6,7 +6,6 @@
app/release
*.hprof
.externalNativeBuild/
src/full/res/raw/util_functions.sh
public.certificate.x509.pem
private.key.pk8
*.apk
app/build.gradle
View file @
ff3d66a6
...
...
@@ -73,6 +73,7 @@ dependencies {
implementation
'androidx.core:core:1.0.1'
implementation
project
(
':net'
)
fullImplementation
project
(
':utils'
)
fullImplementation
project
(
':core'
)
fullImplementation
'androidx.appcompat:appcompat:1.0.2'
fullImplementation
"androidx.preference:preference:${rootProject.ext.androidXVersion}"
fullImplementation
"androidx.recyclerview:recyclerview:${rootProject.ext.androidXVersion}"
...
...
app/proguard-rules.pro
View file @
ff3d66a6
...
...
@@ -23,14 +23,11 @@
-
dontwarn
javax
.
naming
.
**
# Snet extention
-
keepclassmembers
class
com
.
topjohnwu
.
magisk
.
utils
.
ISafetyNetHelper
{
*
;
}
-
keepclassmembers
class
com
.
topjohnwu
.
magisk
.
utils
.
BootSigner
{
*
;
}
# Fast Android Networking Library
-
dontwarn
okhttp3
.
**
-
keepclassmembers
class
com
.
topjohnwu
.
core
.
utils
.
ISafetyNetHelper
{
*
;
}
-
keepclassmembers
class
com
.
topjohnwu
.
core
.
utils
.
BootSigner
{
*
;
}
# Strip logging
-
assumenosideeffects
class
com
.
topjohnwu
.
magisk
.
utils
.
Logger
{
-
assumenosideeffects
class
com
.
topjohnwu
.
core
.
utils
.
Logger
{
public
***
debug
(...);
}
...
...
app/src/full/AndroidManifest.xml
View file @
ff3d66a6
...
...
@@ -40,9 +40,6 @@
android:configChanges=
"keyboardHidden|orientation|screenSize"
android:screenOrientation=
"nosensor"
android:theme=
"@style/AppTheme.StatusBar"
/>
<activity
android:name=
"a.g"
android:theme=
"@style/AppTheme.Translucent"
/>
<!-- Superuser -->
...
...
app/src/full/java/a/a.java
View file @
ff3d66a6
package
a
;
import
com.topjohnwu.
magisk
.utils.BootSigner
;
import
com.topjohnwu.
core
.utils.BootSigner
;
import
androidx.annotation.Keep
;
...
...
app/src/full/java/a/g.java
deleted
100644 → 0
View file @
006d28ab
package
a
;
import
com.topjohnwu.magisk.NoUIActivity
;
public
class
g
extends
NoUIActivity
{
/* stub */
}
app/src/full/java/a/q.java
View file @
ff3d66a6
package
a
;
import
com.topjohnwu.
magisk.MagiskManager
;
import
com.topjohnwu.
core.App
;
public
class
q
extends
MagiskManager
{
public
class
q
extends
App
{
/* stub */
}
app/src/full/java/com/topjohnwu/magisk/AboutActivity.java
View file @
ff3d66a6
...
...
@@ -5,10 +5,11 @@ import android.os.Bundle;
import
android.text.TextUtils
;
import
android.view.View
;
import
com.topjohnwu.
magisk.asyncs.MarkDownWindow
;
import
com.topjohnwu.
core.Const
;
import
com.topjohnwu.magisk.components.AboutCardRow
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.components.MarkDownWindow
;
import
com.topjohnwu.magisk.utils.AppUtils
;
import
java.util.Locale
;
...
...
@@ -62,9 +63,9 @@ public class AboutActivity extends BaseActivity {
appTranslators
.
setSummary
(
translators
);
}
appSourceCode
.
setOnClickListener
(
v
->
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
SOURCE_CODE_URL
)));
supportThread
.
setOnClickListener
(
v
->
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
XDA_THREAD
)));
twitter
.
setOnClickListener
(
v
->
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
TWITTER_URL
)));
appSourceCode
.
setOnClickListener
(
v
->
App
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
SOURCE_CODE_URL
)));
supportThread
.
setOnClickListener
(
v
->
App
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
XDA_THREAD
)));
twitter
.
setOnClickListener
(
v
->
App
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
TWITTER_URL
)));
setFloating
();
}
...
...
app/src/full/java/com/topjohnwu/magisk/ClassMap.java
0 → 100644
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.magisk.components.AboutCardRow
;
import
com.topjohnwu.magisk.receivers.GeneralReceiver
;
import
com.topjohnwu.magisk.receivers.ShortcutReceiver
;
import
com.topjohnwu.magisk.services.OnBootService
;
import
com.topjohnwu.magisk.services.UpdateCheckService
;
import
java.util.HashMap
;
import
java.util.Map
;
public
class
ClassMap
{
private
static
Map
<
Class
,
Class
>
classMap
=
new
HashMap
<>();
static
{
classMap
.
put
(
App
.
class
,
a
.
q
.
class
);
classMap
.
put
(
MainActivity
.
class
,
a
.
b
.
class
);
classMap
.
put
(
SplashActivity
.
class
,
a
.
c
.
class
);
classMap
.
put
(
AboutActivity
.
class
,
a
.
d
.
class
);
classMap
.
put
(
DonationActivity
.
class
,
a
.
e
.
class
);
classMap
.
put
(
FlashActivity
.
class
,
a
.
f
.
class
);
classMap
.
put
(
GeneralReceiver
.
class
,
a
.
h
.
class
);
classMap
.
put
(
ShortcutReceiver
.
class
,
a
.
i
.
class
);
classMap
.
put
(
OnBootService
.
class
,
a
.
j
.
class
);
classMap
.
put
(
UpdateCheckService
.
class
,
a
.
k
.
class
);
classMap
.
put
(
AboutCardRow
.
class
,
a
.
l
.
class
);
classMap
.
put
(
SuRequestActivity
.
class
,
a
.
m
.
class
);
}
public
static
Class
get
(
Class
c
)
{
return
classMap
.
get
(
c
);
}
}
app/src/full/java/com/topjohnwu/magisk/DonationActivity.java
View file @
ff3d66a6
...
...
@@ -3,9 +3,10 @@ package com.topjohnwu.magisk;
import
android.net.Uri
;
import
android.os.Bundle
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.magisk.components.AboutCardRow
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.
App
Utils
;
import
androidx.annotation.Nullable
;
import
androidx.appcompat.app.ActionBar
;
...
...
@@ -38,7 +39,7 @@ public class DonationActivity extends BaseActivity {
ab
.
setDisplayHomeAsUpEnabled
(
true
);
}
paypal
.
setOnClickListener
(
v
->
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
PAYPAL_URL
)));
patreon
.
setOnClickListener
(
v
->
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
PATREON_URL
)));
paypal
.
setOnClickListener
(
v
->
App
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
PAYPAL_URL
)));
patreon
.
setOnClickListener
(
v
->
App
Utils
.
openLink
(
this
,
Uri
.
parse
(
Const
.
Url
.
PATREON_URL
)));
}
}
app/src/full/java/com/topjohnwu/magisk/FlashActivity.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
;
import
android.Manifest
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.os.Bundle
;
...
...
@@ -12,18 +11,22 @@ import android.widget.ScrollView;
import
android.widget.TextView
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.asyncs.FlashZip
;
import
com.topjohnwu.magisk.asyncs.InstallMagisk
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.tasks.FlashZip
;
import
com.topjohnwu.core.tasks.MagiskInstaller
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.CallbackList
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
import
java.io.File
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Calendar
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Locale
;
...
...
@@ -40,7 +43,7 @@ public class FlashActivity extends BaseActivity {
@BindView
(
R
.
id
.
reboot
)
public
Button
reboot
;
@BindView
(
R
.
id
.
scrollView
)
ScrollView
sv
;
private
List
<
String
>
logs
;
private
List
<
String
>
console
,
logs
;
@OnClick
(
R
.
id
.
reboot
)
void
reboot
()
{
...
...
@@ -49,7 +52,7 @@ public class FlashActivity extends BaseActivity {
@OnClick
(
R
.
id
.
save_logs
)
void
saveLogs
()
{
runWith
Permission
(
new
String
[]
{
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
},
()
->
{
runWith
ExternalRW
(
()
->
{
Calendar
now
=
Calendar
.
getInstance
();
String
filename
=
String
.
format
(
Locale
.
US
,
"magisk_install_log_%04d%02d%02d_%02d%02d%02d.log"
,
...
...
@@ -71,6 +74,17 @@ public class FlashActivity extends BaseActivity {
});
}
@OnClick
(
R
.
id
.
close
)
@Override
public
void
finish
()
{
super
.
finish
();
}
@Override
public
void
onBackPressed
()
{
// Prevent user accidentally press back button
}
@Override
public
int
getDarkTheme
()
{
return
R
.
style
.
AppTheme_StatusBar_Dark
;
...
...
@@ -92,77 +106,155 @@ public class FlashActivity extends BaseActivity {
if
(!
Shell
.
rootAccess
())
reboot
.
setVisibility
(
View
.
GONE
);
logs
=
new
ArrayList
<>();
CallbackList
<
String
>
console
=
new
CallbackList
<
String
>(
new
ArrayList
<>())
{
private
void
updateUI
()
{
flashLogs
.
setText
(
TextUtils
.
join
(
"\n"
,
this
));
sv
.
postDelayed
(()
->
sv
.
fullScroll
(
ScrollView
.
FOCUS_DOWN
),
10
);
}
@Override
public
void
onAddElement
(
String
s
)
{
logs
.
add
(
s
);
updateUI
();
}
@Override
public
String
set
(
int
i
,
String
s
)
{
String
ret
=
super
.
set
(
i
,
s
);
Data
.
mainHandler
.
post
(
this
::
updateUI
);
return
ret
;
}
};
logs
=
Collections
.
synchronizedList
(
new
ArrayList
<>());
console
=
new
ConsoleList
();
// We must receive a Uri of the target zip
Intent
intent
=
getIntent
();
Uri
uri
=
intent
.
getData
();
switch
(
intent
.
getStringExtra
(
Const
.
Key
.
FLASH_ACTION
))
{
case
Const
.
Value
.
FLASH_ZIP
:
new
Flash
Zip
(
this
,
uri
,
console
,
logs
).
exec
();
new
Flash
Module
(
uri
).
exec
();
break
;
case
Const
.
Value
.
UNINSTALL
:
new
Uninstall
Magisk
(
this
,
uri
,
console
,
logs
).
exec
();
new
Uninstall
(
uri
).
exec
();
break
;
case
Const
.
Value
.
FLASH_MAGISK
:
new
InstallMagisk
(
this
,
console
,
logs
,
InstallMagisk
.
DIRECT_MODE
).
exec
();
new
DirectInstall
(
).
exec
();
break
;
case
Const
.
Value
.
FLASH_INACTIVE_SLOT
:
new
InstallMagisk
(
this
,
console
,
logs
,
InstallMagisk
.
SECOND_SLOT_MODE
).
exec
();
new
SecondSlot
(
).
exec
();
break
;
case
Const
.
Value
.
PATCH_BOOT
:
new
InstallMagisk
(
this
,
console
,
logs
,
intent
.
getParcelableExtra
(
Const
.
Key
.
FLASH_SET_BOOT
)).
exec
();
new
PatchBoot
(
uri
).
exec
();
break
;
}
}
@OnClick
(
R
.
id
.
close
)
@Override
public
void
finish
()
{
super
.
finish
();
private
class
ConsoleList
extends
CallbackList
<
String
>
{
ConsoleList
()
{
super
(
new
ArrayList
<>());
}
private
void
updateUI
()
{
flashLogs
.
setText
(
TextUtils
.
join
(
"\n"
,
this
));
sv
.
postDelayed
(()
->
sv
.
fullScroll
(
ScrollView
.
FOCUS_DOWN
),
10
);
}
@Override
public
void
onAddElement
(
String
s
)
{
logs
.
add
(
s
);
updateUI
();
}
@Override
public
String
set
(
int
i
,
String
s
)
{
String
ret
=
super
.
set
(
i
,
s
);
App
.
mainHandler
.
post
(
this
::
updateUI
);
return
ret
;
}
}
@Override
public
void
onBackPressed
()
{
// Prevent user accidentally press back button
private
class
FlashModule
extends
FlashZip
{
FlashModule
(
Uri
uri
)
{
super
(
uri
,
console
,
logs
);
}
@Override
protected
void
onResult
(
boolean
success
)
{
if
(
success
)
{
Utils
.
loadModules
();
}
else
{
console
.
add
(
"! Installation failed"
);
reboot
.
setVisibility
(
View
.
GONE
);
}
buttonPanel
.
setVisibility
(
View
.
VISIBLE
);
}
}
private
static
class
UninstallMagisk
extends
FlashZip
{
private
class
Uninstall
extends
FlashModule
{
private
UninstallMagisk
(
BaseActivity
context
,
Uri
uri
,
List
<
String
>
console
,
List
<
String
>
logs
)
{
super
(
context
,
uri
,
console
,
logs
);
Uninstall
(
Uri
uri
)
{
super
(
uri
);
}
@Override
protected
void
onPostExecute
(
Integer
result
)
{
if
(
result
==
1
)
{
Data
.
mainHandler
.
postDelayed
(()
->
Shell
.
su
(
"pm uninstall "
+
getActivity
().
getPackageName
()).
exec
(),
3000
);
protected
void
onResult
(
boolean
success
)
{
if
(
success
)
App
.
mainHandler
.
postDelayed
(
Shell
.
su
(
"pm uninstall "
+
getPackageName
())::
exec
,
3000
);
else
super
.
onResult
(
false
);
}
}
private
abstract
class
BaseInstaller
extends
MagiskInstaller
{
BaseInstaller
()
{
super
(
console
,
logs
);
}
@Override
protected
void
onResult
(
boolean
success
)
{
if
(
success
)
{
console
.
add
(
"- All done!"
);
}
else
{
super
.
onPostExecute
(
result
);
Shell
.
sh
(
"rm -rf "
+
installDir
).
submit
();
console
.
add
(
"! Installation failed"
);
reboot
.
setVisibility
(
View
.
GONE
);
}
buttonPanel
.
setVisibility
(
View
.
VISIBLE
);
}
}
private
class
DirectInstall
extends
BaseInstaller
{
@Override
protected
boolean
operations
()
{
console
.
add
(
"- Detecting target image"
);
srcBoot
=
ShellUtils
.
fastCmd
(
"find_boot_image"
,
"echo \"$BOOTIMAGE\""
);
if
(
srcBoot
.
isEmpty
())
{
console
.
add
(
"! Unable to detect target image"
);
return
false
;
}
return
extractZip
()
&&
patchBoot
()
&&
flashBoot
();
}
}
private
class
SecondSlot
extends
BaseInstaller
{
@Override
protected
boolean
operations
()
{
String
slot
=
ShellUtils
.
fastCmd
(
"echo $SLOT"
);
String
target
=
(
TextUtils
.
equals
(
slot
,
"_a"
)
?
"_b"
:
"_a"
);
console
.
add
(
"- Target slot: "
+
target
);
console
.
add
(
"- Detecting target image"
);
srcBoot
=
ShellUtils
.
fastCmd
(
"SLOT="
+
target
,
"find_boot_image"
,
"SLOT="
+
slot
,
"echo \"$BOOTIMAGE\""
);
if
(
srcBoot
.
isEmpty
())
{
console
.
add
(
"! Unable to detect target image"
);
return
false
;
}
return
extractZip
()
&&
patchBoot
()
&&
flashBoot
()
&&
postOTA
();
}
}
private
class
PatchBoot
extends
BaseInstaller
{
private
Uri
uri
;
PatchBoot
(
Uri
u
)
{
uri
=
u
;
}
@Override
protected
boolean
operations
()
{
return
copyBoot
(
uri
)
&&
extractZip
()
&&
patchBoot
()
&&
storeBoot
();
}
}
}
app/src/full/java/com/topjohnwu/magisk/MainActivity.java
View file @
ff3d66a6
...
...
@@ -8,6 +8,10 @@ import android.view.MenuItem;
import
android.view.View
;
import
com.google.android.material.navigation.NavigationView
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.fragments.LogFragment
;
import
com.topjohnwu.magisk.fragments.MagiskFragment
;
...
...
@@ -17,8 +21,6 @@ import com.topjohnwu.magisk.fragments.ReposFragment;
import
com.topjohnwu.magisk.fragments.SettingsFragment
;
import
com.topjohnwu.magisk.fragments.SuperuserFragment
;
import
com.topjohnwu.magisk.utils.Download
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
androidx.annotation.NonNull
;
...
...
@@ -49,8 +51,8 @@ public class MainActivity extends BaseActivity
@Override
protected
void
onCreate
(
final
Bundle
savedInstanceState
)
{
if
(!
mm
.
hasI
nit
)
{
startActivity
(
new
Intent
(
this
,
Data
.
c
lassMap
.
get
(
SplashActivity
.
class
)));
if
(!
app
.
i
nit
)
{
startActivity
(
new
Intent
(
this
,
C
lassMap
.
get
(
SplashActivity
.
class
)));
finish
();
}
...
...
@@ -120,7 +122,7 @@ public class MainActivity extends BaseActivity
public
void
checkHideSection
()
{
Menu
menu
=
navigationView
.
getMenu
();
menu
.
findItem
(
R
.
id
.
magiskhide
).
setVisible
(
Shell
.
rootAccess
()
&&
mm
.
prefs
.
getBoolean
(
Const
.
Key
.
MAGISKHIDE
,
false
));
app
.
prefs
.
getBoolean
(
Const
.
Key
.
MAGISKHIDE
,
false
));
menu
.
findItem
(
R
.
id
.
modules
).
setVisible
(
Shell
.
rootAccess
()
&&
Data
.
magiskVersionCode
>=
0
);
menu
.
findItem
(
R
.
id
.
downloads
).
setVisible
(
Download
.
checkNetworkStatus
(
this
)
&&
Shell
.
rootAccess
()
&&
Data
.
magiskVersionCode
>=
0
);
...
...
@@ -189,11 +191,11 @@ public class MainActivity extends BaseActivity
displayFragment
(
new
SettingsFragment
(),
true
);
break
;
case
R
.
id
.
app_about
:
startActivity
(
new
Intent
(
this
,
Data
.
c
lassMap
.
get
(
AboutActivity
.
class
)));
startActivity
(
new
Intent
(
this
,
C
lassMap
.
get
(
AboutActivity
.
class
)));
mDrawerItem
=
bak
;
break
;
case
R
.
id
.
donation
:
startActivity
(
new
Intent
(
this
,
Data
.
c
lassMap
.
get
(
DonationActivity
.
class
)));
startActivity
(
new
Intent
(
this
,
C
lassMap
.
get
(
DonationActivity
.
class
)));
mDrawerItem
=
bak
;
break
;
}
...
...
app/src/full/java/com/topjohnwu/magisk/NoUIActivity.java
deleted
100644 → 0
View file @
006d28ab
package
com
.
topjohnwu
.
magisk
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
androidx.annotation.NonNull
;
public
class
NoUIActivity
extends
BaseActivity
{
@Override
public
void
onRequestPermissionsResult
(
int
requestCode
,
@NonNull
String
[]
permissions
,
@NonNull
int
[]
grantResults
)
{
super
.
onRequestPermissionsResult
(
requestCode
,
permissions
,
grantResults
);
finish
();
}
}
app/src/full/java/com/topjohnwu/magisk/SplashActivity.java
View file @
ff3d66a6
...
...
@@ -5,14 +5,17 @@ import android.content.pm.PackageManager;
import
android.os.Bundle
;
import
android.text.TextUtils
;
import
com.topjohnwu.magisk.asyncs.CheckUpdates
;
import
com.topjohnwu.magisk.asyncs.UpdateRepos
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.tasks.CheckUpdates
;
import
com.topjohnwu.core.tasks.UpdateRepos
;
import
com.topjohnwu.core.utils.LocaleManager
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.components.Notifications
;
import
com.topjohnwu.magisk.receivers.ShortcutReceiver
;
import
com.topjohnwu.magisk.utils.AppUtils
;
import
com.topjohnwu.magisk.utils.Download
;
import
com.topjohnwu.magisk.utils.LocaleManager
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
public
class
SplashActivity
extends
BaseActivity
{
...
...
@@ -21,9 +24,9 @@ public class SplashActivity extends BaseActivity {
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
String
pkg
=
mm
.
mDB
.
getStrings
(
Const
.
Key
.
SU_MANAGER
,
null
);
String
pkg
=
app
.
mDB
.
getStrings
(
Const
.
Key
.
SU_MANAGER
,
null
);
if
(
pkg
!=
null
&&
getPackageName
().
equals
(
BuildConfig
.
APPLICATION_ID
))
{
mm
.
mDB
.
setStrings
(
Const
.
Key
.
SU_MANAGER
,
null
);
app
.
mDB
.
setStrings
(
Const
.
Key
.
SU_MANAGER
,
null
);
Shell
.
su
(
"pm uninstall "
+
pkg
).
exec
();
}
if
(
TextUtils
.
equals
(
pkg
,
getPackageName
()))
{
...
...
@@ -37,7 +40,7 @@ public class SplashActivity extends BaseActivity {
// Magisk working as expected
if
(
Shell
.
rootAccess
()
&&
Data
.
magiskVersionCode
>
0
)
{
// Update check service
Utils
.
setupUpdateCheck
();
App
Utils
.
setupUpdateCheck
();
// Load modules
Utils
.
loadModules
();
}
...
...
@@ -45,13 +48,13 @@ public class SplashActivity extends BaseActivity {
Data
.
importPrefs
();
// Dynamic detect all locales
LocaleManager
.
loadAvailableLocales
();
LocaleManager
.
loadAvailableLocales
(
R
.
string
.
download_file_error
);
// Create notification channel on Android O
Notifications
.
setup
(
this
);
// Setup shortcuts
sendBroadcast
(
new
Intent
(
this
,
Data
.
c
lassMap
.
get
(
ShortcutReceiver
.
class
)));
sendBroadcast
(
new
Intent
(
this
,
C
lassMap
.
get
(
ShortcutReceiver
.
class
)));
if
(
Download
.
checkNetworkStatus
(
this
))
{
// Fire update check
...
...
@@ -63,9 +66,9 @@ public class SplashActivity extends BaseActivity {
// Write back default values
Data
.
writeConfig
();
mm
.
hasI
nit
=
true
;
app
.
i
nit
=
true
;
Intent
intent
=
new
Intent
(
this
,
Data
.
c
lassMap
.
get
(
MainActivity
.
class
));
Intent
intent
=
new
Intent
(
this
,
C
lassMap
.
get
(
MainActivity
.
class
));
intent
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
getIntent
().
getStringExtra
(
Const
.
Key
.
OPEN_SECTION
));
intent
.
putExtra
(
BaseActivity
.
INTENT_PERM
,
getIntent
().
getStringExtra
(
BaseActivity
.
INTENT_PERM
));
startActivity
(
intent
);
...
...
app/src/full/java/com/topjohnwu/magisk/SuRequestActivity.java
View file @
ff3d66a6
...
...
@@ -15,8 +15,10 @@ import android.widget.LinearLayout;
import
android.widget.Spinner
;
import
android.widget.TextView
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.container.Policy
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.container.Policy
;
import
com.topjohnwu.magisk.utils.FingerprintHelper
;
import
com.topjohnwu.magisk.utils.SuConnector
;
...
...
@@ -70,7 +72,7 @@ public class SuRequestActivity extends BaseActivity {
supportRequestWindowFeature
(
Window
.
FEATURE_NO_TITLE
);
PackageManager
pm
=
getPackageManager
();
mm
.
mDB
.
clearOutdated
();
app
.
mDB
.
clearOutdated
();
// Get policy
Intent
intent
=
getIntent
();
...
...
@@ -84,7 +86,7 @@ public class SuRequestActivity extends BaseActivity {
};
Bundle
bundle
=
connector
.
readSocketInput
();
int
uid
=
Integer
.
parseInt
(
bundle
.
getString
(
"uid"
));
policy
=
mm
.
mDB
.
getPolicy
(
uid
);
policy
=
app
.
mDB
.
getPolicy
(
uid
);
if
(
policy
==
null
)
{
policy
=
new
Policy
(
uid
,
pm
);
}
...
...
@@ -212,7 +214,7 @@ public class SuRequestActivity extends BaseActivity {
policy
.
policy
=
action
;
if
(
time
>=
0
)
{
policy
.
until
=
(
time
==
0
)
?
0
:
(
System
.
currentTimeMillis
()
/
1000
+
time
*
60
);
mm
.
mDB
.
updatePolicy
(
policy
);
app
.
mDB
.
updatePolicy
(
policy
);
}
handleAction
();
}
...
...
app/src/full/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java
View file @
ff3d66a6
...
...
@@ -13,10 +13,10 @@ import android.widget.Filter;
import
android.widget.ImageView
;
import
android.widget.TextView
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
java.util.ArrayList
;
...
...
app/src/full/java/com/topjohnwu/magisk/adapters/ModulesAdapter.java
View file @
ff3d66a6
...
...
@@ -10,9 +10,9 @@ import android.widget.ImageView;
import
android.widget.TextView
;
import
com.google.android.material.snackbar.Snackbar
;
import
com.topjohnwu.core.container.Module
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.components.SnackbarMaker
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.superuser.Shell
;
import
java.util.List
;
...
...
app/src/full/java/com/topjohnwu/magisk/adapters/PolicyAdapter.java
View file @
ff3d66a6
...
...
@@ -10,12 +10,12 @@ import android.widget.Switch;
import
android.widget.TextView
;
import
com.google.android.material.snackbar.Snackbar
;
import
com.topjohnwu.core.container.Policy
;
import
com.topjohnwu.core.database.MagiskDB
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.components.CustomAlertDialog
;
import
com.topjohnwu.magisk.components.ExpandableView
;
import
com.topjohnwu.magisk.components.SnackbarMaker
;
import
com.topjohnwu.magisk.container.Policy
;
import
com.topjohnwu.magisk.database.MagiskDB
;
import
com.topjohnwu.magisk.utils.FingerprintHelper
;
import
java.util.HashSet
;
...
...
app/src/full/java/com/topjohnwu/magisk/adapters/ReposAdapter.java
View file @
ff3d66a6
...
...
@@ -11,14 +11,14 @@ import android.widget.ImageView;
import
android.widget.LinearLayout
;
import
android.widget.TextView
;
import
com.topjohnwu.core.container.Module
;
import
com.topjohnwu.core.container.Repo
;
import
com.topjohnwu.core.database.RepoDatabaseHelper
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.asyncs.DownloadModule
;
import
com.topjohnwu.magisk.asyncs.MarkDownWindow
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.components.CustomAlertDialog
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.magisk.container.Repo
;
import
com.topjohnwu.magisk.database.RepoDatabaseHelper
;
import
com.topjohnwu.magisk.components.MarkDownWindow
;
import
com.topjohnwu.magisk.utils.DownloadModule
;
import
java.util.ArrayList
;
import
java.util.List
;
...
...
app/src/full/java/com/topjohnwu/magisk/adapters/SuLogAdapter.java
View file @
ff3d66a6
...
...
@@ -8,10 +8,10 @@ import android.view.animation.RotateAnimation;
import
android.widget.ImageView
;
import
android.widget.TextView
;
import
com.topjohnwu.core.container.SuLogEntry
;
import
com.topjohnwu.core.database.MagiskDB
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.components.ExpandableView
;
import
com.topjohnwu.magisk.container.SuLogEntry
;
import
com.topjohnwu.magisk.database.MagiskDB
;
import
java.util.Collections
;
import
java.util.HashSet
;
...
...
app/src/full/java/com/topjohnwu/magisk/asyncs/FlashZip.java
deleted
100644 → 0
View file @
006d28ab
package
com
.
topjohnwu
.
magisk
.
asyncs
;
import
android.app.Activity
;
import
android.net.Uri
;
import
android.view.View
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.FlashActivity
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.components.SnackbarMaker
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.ZipUtils
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.util.List
;
public
class
FlashZip
extends
ParallelTask
<
Void
,
Void
,
Integer
>
{
private
Uri
mUri
;
private
File
mCachedFile
;
private
List
<
String
>
console
,
logs
;
public
FlashZip
(
Activity
context
,
Uri
uri
,
List
<
String
>
console
,
List
<
String
>
logs
)
{
super
(
context
);
mUri
=
uri
;
this
.
console
=
console
;
this
.
logs
=
logs
;
mCachedFile
=
new
File
(
context
.
getCacheDir
(),
"install.zip"
);
}
private
boolean
unzipAndCheck
()
throws
Exception
{
ZipUtils
.
unzip
(
mCachedFile
,
mCachedFile
.
getParentFile
(),
"META-INF/com/google/android"
,
true
);
return
ShellUtils
.
fastCmdResult
(
"grep -q '#MAGISK' "
+
new
File
(
mCachedFile
.
getParentFile
(),
"updater-script"
));
}
@Override
protected
Integer
doInBackground
(
Void
...
voids
)
{
MagiskManager
mm
=
Data
.
MM
();
try
{
console
.
add
(
"- Copying zip to temp directory"
);
mCachedFile
.
delete
();
try
(
InputStream
in
=
mm
.
getContentResolver
().
openInputStream
(
mUri
);
OutputStream
out
=
new
BufferedOutputStream
(
new
FileOutputStream
(
mCachedFile
))
)
{
if
(
in
==
null
)
throw
new
FileNotFoundException
();
InputStream
buf
=
new
BufferedInputStream
(
in
);
ShellUtils
.
pump
(
buf
,
out
);
}
catch
(
FileNotFoundException
e
)
{
console
.
add
(
"! Invalid Uri"
);
throw
e
;
}
catch
(
IOException
e
)
{
console
.
add
(
"! Cannot copy to cache"
);
throw
e
;
}
if
(!
unzipAndCheck
())
return
0
;
console
.
add
(
"- Installing "
+
Utils
.
getNameFromUri
(
mm
,
mUri
));
if
(!
Shell
.
su
(
"cd "
+
mCachedFile
.
getParent
(),
"BOOTMODE=true sh update-binary dummy 1 "
+
mCachedFile
)
.
to
(
console
,
logs
)
.
exec
().
isSuccess
())
return
-
1
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
-
1
;
}
console
.
add
(
"- All done!"
);
return
1
;
}
// -1 = error, manual install; 0 = invalid zip; 1 = success
@Override
protected
void
onPostExecute
(
Integer
result
)
{
FlashActivity
activity
=
(
FlashActivity
)
getActivity
();
Shell
.
su
(
"rm -rf "
+
mCachedFile
.
getParent
(),
"rm -rf "
+
Const
.
TMP_FOLDER_PATH
).
submit
();
switch
(
result
)
{
case
-
1
:
console
.
add
(
"! Installation failed"
);
SnackbarMaker
.
showUri
(
getActivity
(),
mUri
);
break
;
case
0
:
console
.
add
(
"! This zip is not a Magisk Module!"
);
break
;
case
1
:
// Reload modules
Utils
.
loadModules
();
break
;
}
activity
.
reboot
.
setVisibility
(
result
>
0
?
View
.
VISIBLE
:
View
.
GONE
);
activity
.
buttonPanel
.
setVisibility
(
View
.
VISIBLE
);
}
}
app/src/full/java/com/topjohnwu/magisk/components/BaseActivity.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
components
;
import
android.Manifest
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.pm.PackageManager
;
...
...
@@ -8,13 +9,12 @@ import android.os.Bundle;
import
android.view.WindowManager
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.NoUIActivity
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.utils.LocaleManager
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.LocaleManager
;
import
com.topjohnwu.magisk.utils.Topic
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
...
...
@@ -26,12 +26,12 @@ import androidx.core.content.ContextCompat;
public
abstract
class
BaseActivity
extends
AppCompatActivity
implements
Topic
.
AutoSubscriber
{
public
static
final
String
INTENT_PERM
=
"perm_dialog"
;
private
static
Runnable
grantCallback
;
protected
static
Runnable
permissionGrantCallback
;
static
int
[]
EMPTY_INT_ARRAY
=
new
int
[
0
];
private
ActivityResultListener
activityResultListener
;
public
MagiskManager
mm
;
public
App
app
;
@Override
public
int
[]
getSubscribedTopics
()
{
...
...
@@ -49,7 +49,7 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Au
Configuration
config
=
base
.
getResources
().
getConfiguration
();
config
.
setLocale
(
LocaleManager
.
locale
);
applyOverrideConfiguration
(
config
);
mm
=
Data
.
MM
()
;
app
=
App
.
self
;
}
@Override
...
...
@@ -84,6 +84,14 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Au
}
}
public
void
runWithExternalRW
(
Runnable
callback
)
{
runWithPermission
(
new
String
[]
{
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
},
callback
);
}
public
void
runWithPermission
(
String
[]
permissions
,
Runnable
callback
)
{
runWithPermission
(
this
,
permissions
,
callback
);
}
public
static
void
runWithPermission
(
Context
context
,
String
[]
permissions
,
Runnable
callback
)
{
boolean
granted
=
true
;
for
(
String
perm
:
permissions
)
{
...
...
@@ -95,23 +103,13 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Au
callback
.
run
();
}
else
{
// Passed in context should be an activity if not granted, need to show dialog!
permissionGrantCallback
=
callback
;
if
(!(
context
instanceof
BaseActivity
))
{
// Start NoUIActivity to show dialog
Intent
intent
=
new
Intent
(
context
,
Data
.
classMap
.
get
(
NoUIActivity
.
class
));
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
);
intent
.
putExtra
(
INTENT_PERM
,
permissions
);
context
.
startActivity
(
intent
);
}
else
{
if
(
context
instanceof
BaseActivity
)
{
grantCallback
=
callback
;
ActivityCompat
.
requestPermissions
((
BaseActivity
)
context
,
permissions
,
0
);
}
}
}
public
void
runWithPermission
(
String
[]
permissions
,
Runnable
callback
)
{
runWithPermission
(
this
,
permissions
,
callback
);
}
@Override
protected
void
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
if
(
activityResultListener
!=
null
)
...
...
@@ -132,13 +130,13 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Au
grant
=
false
;
}
if
(
grant
)
{
if
(
permissionG
rantCallback
!=
null
)
{
permissionG
rantCallback
.
run
();
if
(
g
rantCallback
!=
null
)
{
g
rantCallback
.
run
();
}
}
else
{
Toast
.
makeText
(
this
,
R
.
string
.
no_rw_storage
,
Toast
.
LENGTH_LONG
).
show
();
}
permissionG
rantCallback
=
null
;
g
rantCallback
=
null
;
}
public
interface
ActivityResultListener
{
...
...
app/src/full/java/com/topjohnwu/magisk/components/BaseFragment.java
View file @
ff3d66a6
...
...
@@ -2,20 +2,19 @@ package com.topjohnwu.magisk.components;
import
android.content.Intent
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.utils.Topic
;
import
androidx.fragment.app.Fragment
;
import
butterknife.Unbinder
;
public
class
BaseFragment
extends
Fragment
implements
Topic
.
AutoSubscriber
{
public
MagiskManager
mm
;
public
App
app
;
protected
Unbinder
unbinder
=
null
;
public
BaseFragment
()
{
mm
=
Data
.
MM
()
;
app
=
App
.
self
;
}
@Override
...
...
app/src/full/java/com/topjohnwu/magisk/components/EnvFixDialog.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
components
;
import
android.app.Activity
;
import
android.app.ProgressDialog
;
import
android.widget.Toast
;
import
com.topjohnwu.core.tasks.MagiskInstaller
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.asyncs.InstallMagisk
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.io.SuFile
;
import
androidx.annotation.NonNull
;
...
...
@@ -14,7 +19,25 @@ public class EnvFixDialog extends CustomAlertDialog {
setTitle
(
R
.
string
.
env_fix_title
);
setMessage
(
R
.
string
.
env_fix_msg
);
setCancelable
(
true
);
setPositiveButton
(
R
.
string
.
yes
,
(
d
,
i
)
->
new
InstallMagisk
(
activity
).
exec
());
setPositiveButton
(
R
.
string
.
yes
,
(
d
,
i
)
->
{
ProgressDialog
pd
=
ProgressDialog
.
show
(
activity
,
activity
.
getString
(
R
.
string
.
setup_title
),
activity
.
getString
(
R
.
string
.
setup_msg
));
new
MagiskInstaller
()
{
@Override
protected
boolean
operations
()
{
installDir
=
new
SuFile
(
"/data/adb/magisk"
);
Shell
.
su
(
"rm -rf /data/adb/magisk/*"
).
exec
();
return
extractZip
()
&&
Shell
.
su
(
"fix_env"
).
exec
().
isSuccess
();
}
@Override
protected
void
onResult
(
boolean
success
)
{
pd
.
dismiss
();
Utils
.
toast
(
success
?
R
.
string
.
setup_done
:
R
.
string
.
setup_fail
,
Toast
.
LENGTH_LONG
);
}
}.
exec
();
});
setNegativeButton
(
R
.
string
.
no_thanks
,
null
);
}
}
app/src/full/java/com/topjohnwu/magisk/components/InstallMethodDialog.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
components
;
import
android.Manifest
;
import
android.app.Activity
;
import
android.content.Intent
;
import
android.widget.Toast
;
import
com.google.android.material.snackbar.Snackbar
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.FlashActivity
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.net.Networking
;
import
java.io.File
;
...
...
@@ -33,7 +33,7 @@ class InstallMethodDialog extends AlertDialog.Builder {
downloadOnly
(
activity
);
break
;
case
2
:
intent
=
new
Intent
(
activity
,
Data
.
c
lassMap
.
get
(
FlashActivity
.
class
))
intent
=
new
Intent
(
activity
,
C
lassMap
.
get
(
FlashActivity
.
class
))
.
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
FLASH_MAGISK
);
activity
.
startActivity
(
intent
);
break
;
...
...
@@ -48,13 +48,13 @@ class InstallMethodDialog extends AlertDialog.Builder {
private
void
patchBoot
(
BaseActivity
a
)
{
Utils
.
toast
(
R
.
string
.
boot_file_patch_msg
,
Toast
.
LENGTH_LONG
);
Intent
intent
=
new
Intent
(
Intent
.
ACTION_GET_CONTENT
).
setType
(
"*/*"
);
a
.
runWith
Permission
(
new
String
[]{
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
},
()
->
a
.
runWith
ExternalRW
(
()
->
a
.
startActivityForResult
(
intent
,
Const
.
ID
.
SELECT_BOOT
,
(
requestCode
,
resultCode
,
data
)
->
{
if
(
requestCode
==
Const
.
ID
.
SELECT_BOOT
&&
resultCode
==
Activity
.
RESULT_OK
&&
data
!=
null
)
{
Intent
i
=
new
Intent
(
a
,
Data
.
c
lassMap
.
get
(
FlashActivity
.
class
))
.
putExtra
(
Const
.
Key
.
FLASH_SET_BOOT
,
data
.
getData
())
Intent
i
=
new
Intent
(
a
,
C
lassMap
.
get
(
FlashActivity
.
class
))
.
setData
(
data
.
getData
())
.
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
PATCH_BOOT
);
a
.
startActivity
(
i
);
}
...
...
@@ -63,7 +63,7 @@ class InstallMethodDialog extends AlertDialog.Builder {
}
private
void
downloadOnly
(
BaseActivity
a
)
{
a
.
runWith
Permission
(
new
String
[]
{
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
},
()
->
{
a
.
runWith
ExternalRW
(
()
->
{
String
filename
=
Utils
.
fmt
(
"Magisk-v%s(%d).zip"
,
Data
.
remoteMagiskVersionString
,
Data
.
remoteMagiskVersionCode
);
File
zip
=
new
File
(
Const
.
EXTERNAL_PATH
,
filename
);
...
...
@@ -86,7 +86,7 @@ class InstallMethodDialog extends AlertDialog.Builder {
.
setMessage
(
R
.
string
.
install_inactive_slot_msg
)
.
setCancelable
(
true
)
.
setPositiveButton
(
R
.
string
.
yes
,
(
d
,
i
)
->
{
Intent
intent
=
new
Intent
(
activity
,
Data
.
c
lassMap
.
get
(
FlashActivity
.
class
))
Intent
intent
=
new
Intent
(
activity
,
C
lassMap
.
get
(
FlashActivity
.
class
))
.
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
FLASH_INACTIVE_SLOT
);
activity
.
startActivity
(
intent
);
})
...
...
app/src/full/java/com/topjohnwu/magisk/components/MagiskInstallDialog.java
View file @
ff3d66a6
...
...
@@ -3,11 +3,10 @@ package com.topjohnwu.magisk.components;
import
android.net.Uri
;
import
android.text.TextUtils
;
import
com.topjohnwu.
magisk
.Data
;
import
com.topjohnwu.
magisk.MagiskManager
;
import
com.topjohnwu.
core
.Data
;
import
com.topjohnwu.
core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.asyncs.MarkDownWindow
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.AppUtils
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
...
...
@@ -15,35 +14,34 @@ import java.util.ArrayList;
import
java.util.List
;
public
class
MagiskInstallDialog
extends
CustomAlertDialog
{
public
MagiskInstallDialog
(
BaseActivity
activity
)
{
super
(
activity
);
MagiskManager
mm
=
Data
.
MM
();
public
MagiskInstallDialog
(
BaseActivity
a
)
{
super
(
a
);
String
filename
=
Utils
.
fmt
(
"Magisk-v%s(%d).zip"
,
Data
.
remoteMagiskVersionString
,
Data
.
remoteMagiskVersionCode
);
setTitle
(
mm
.
getString
(
R
.
string
.
repo_install_title
,
mm
.
getString
(
R
.
string
.
magisk
)));
setMessage
(
mm
.
getString
(
R
.
string
.
repo_install_msg
,
filename
));
setTitle
(
a
.
getString
(
R
.
string
.
repo_install_title
,
a
.
getString
(
R
.
string
.
magisk
)));
setMessage
(
a
.
getString
(
R
.
string
.
repo_install_msg
,
filename
));
setCancelable
(
true
);
setPositiveButton
(
R
.
string
.
install
,
(
d
,
i
)
->
{
List
<
String
>
options
=
new
ArrayList
<>();
options
.
add
(
mm
.
getString
(
R
.
string
.
download_zip_only
));
options
.
add
(
mm
.
getString
(
R
.
string
.
patch_boot_file
));
options
.
add
(
a
.
getString
(
R
.
string
.
download_zip_only
));
options
.
add
(
a
.
getString
(
R
.
string
.
patch_boot_file
));
if
(
Shell
.
rootAccess
())
{
options
.
add
(
mm
.
getString
(
R
.
string
.
direct_install
));
options
.
add
(
a
.
getString
(
R
.
string
.
direct_install
));
String
s
=
ShellUtils
.
fastCmd
(
"grep_prop ro.build.ab_update"
);
if
(!
s
.
isEmpty
()
&&
Boolean
.
parseBoolean
(
s
))
{
options
.
add
(
mm
.
getString
(
R
.
string
.
install_inactive_slot
));
options
.
add
(
a
.
getString
(
R
.
string
.
install_inactive_slot
));
}
}
new
InstallMethodDialog
(
a
ctivity
,
options
).
show
();
new
InstallMethodDialog
(
a
,
options
).
show
();
});
setNegativeButton
(
R
.
string
.
no_thanks
,
null
);
if
(!
TextUtils
.
isEmpty
(
Data
.
magiskNoteLink
))
{
setNeutralButton
(
R
.
string
.
release_notes
,
(
d
,
i
)
->
{
if
(
Data
.
magiskNoteLink
.
contains
(
"forum.xda-developers"
))
{
// Open forum links in browser
Utils
.
openLink
(
activity
,
Uri
.
parse
(
Data
.
magiskNoteLink
));
AppUtils
.
openLink
(
a
,
Uri
.
parse
(
Data
.
magiskNoteLink
));
}
else
{
new
MarkDownWindow
(
a
ctivity
,
null
,
Data
.
magiskNoteLink
).
exec
();
new
MarkDownWindow
(
a
,
null
,
Data
.
magiskNoteLink
).
exec
();
}
});
}
...
...
app/src/full/java/com/topjohnwu/magisk/components/ManagerInstallDialog.java
View file @
ff3d66a6
...
...
@@ -2,30 +2,27 @@ package com.topjohnwu.magisk.components;
import
android.text.TextUtils
;
import
com.topjohnwu.
magisk
.Data
;
import
com.topjohnwu.
magisk.MagiskManager
;
import
com.topjohnwu.
core
.Data
;
import
com.topjohnwu.
core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.asyncs.MarkDownWindow
;
import
com.topjohnwu.magisk.utils.DlInstallManager
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.DownloadApp
;
import
androidx.annotation.NonNull
;
public
class
ManagerInstallDialog
extends
CustomAlertDialog
{
public
ManagerInstallDialog
(
@NonNull
BaseActivity
activity
)
{
super
(
activity
);
MagiskManager
mm
=
Data
.
MM
();
public
ManagerInstallDialog
(
@NonNull
BaseActivity
a
)
{
super
(
a
);
String
name
=
Utils
.
fmt
(
"MagiskManager v%s(%d)"
,
Data
.
remoteManagerVersionString
,
Data
.
remoteManagerVersionCode
);
setTitle
(
mm
.
getString
(
R
.
string
.
repo_install_title
,
mm
.
getString
(
R
.
string
.
app_name
)));
setMessage
(
mm
.
getString
(
R
.
string
.
repo_install_msg
,
name
));
setTitle
(
a
.
getString
(
R
.
string
.
repo_install_title
,
a
.
getString
(
R
.
string
.
app_name
)));
setMessage
(
a
.
getString
(
R
.
string
.
repo_install_msg
,
name
));
setCancelable
(
true
);
setPositiveButton
(
R
.
string
.
install
,
(
d
,
i
)
->
D
lInstallManager
.
upgrade
(
name
));
setPositiveButton
(
R
.
string
.
install
,
(
d
,
i
)
->
D
ownloadApp
.
upgrade
(
name
));
setNegativeButton
(
R
.
string
.
no_thanks
,
null
);
if
(!
TextUtils
.
isEmpty
(
Data
.
managerNoteLink
))
{
setNeutralButton
(
R
.
string
.
app_changelog
,
(
d
,
i
)
->
new
MarkDownWindow
(
a
ctivity
,
null
,
Data
.
managerNoteLink
).
exec
());
new
MarkDownWindow
(
a
,
null
,
Data
.
managerNoteLink
).
exec
());
}
}
}
app/src/full/java/com/topjohnwu/magisk/
async
s/MarkDownWindow.java
→
app/src/full/java/com/topjohnwu/magisk/
component
s/MarkDownWindow.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
async
s
;
package
com
.
topjohnwu
.
magisk
.
component
s
;
import
android.app.Activity
;
import
android.webkit.WebView
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.tasks.ParallelTask
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.ShellUtils
;
import
org.commonmark.node.Node
;
...
...
@@ -40,7 +41,7 @@ public class MarkDownWindow extends ParallelTask<Void, Void, String> {
@Override
protected
String
doInBackground
(
Void
...
voids
)
{
MagiskManager
mm
=
Data
.
MM
()
;
App
app
=
App
.
self
;
String
md
;
if
(
mUrl
!=
null
)
{
md
=
Utils
.
dlString
(
mUrl
);
...
...
@@ -55,14 +56,11 @@ public class MarkDownWindow extends ParallelTask<Void, Void, String> {
}
}
String
css
;
try
(
InputStream
in
=
mm
.
getResources
().
openRawResource
(
Data
.
isDarkTheme
?
R
.
raw
.
dark
:
R
.
raw
.
light
);
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
()
)
{
try
(
InputStream
in
=
app
.
getResources
()
.
openRawResource
(
Data
.
isDarkTheme
?
R
.
raw
.
dark
:
R
.
raw
.
light
);
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
())
{
ShellUtils
.
pump
(
in
,
out
);
css
=
out
.
toString
();
in
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
return
""
;
...
...
app/src/full/java/com/topjohnwu/magisk/components/Notifications.java
View file @
ff3d66a6
...
...
@@ -7,13 +7,14 @@ import android.content.Context;
import
android.content.Intent
;
import
android.os.Build
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.SplashActivity
;
import
com.topjohnwu.magisk.receivers.GeneralReceiver
;
import
com.topjohnwu.magisk.utils.Utils
;
import
androidx.core.app.NotificationCompat
;
import
androidx.core.app.NotificationManagerCompat
;
...
...
@@ -36,74 +37,74 @@ public class Notifications {
}
public
static
void
magiskUpdate
()
{
MagiskManager
mm
=
Data
.
MM
()
;
App
app
=
App
.
self
;
Intent
intent
=
new
Intent
(
mm
,
Data
.
c
lassMap
.
get
(
SplashActivity
.
class
));
Intent
intent
=
new
Intent
(
app
,
C
lassMap
.
get
(
SplashActivity
.
class
));
intent
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"magisk"
);
TaskStackBuilder
stackBuilder
=
TaskStackBuilder
.
create
(
mm
);
stackBuilder
.
addParentStack
(
Data
.
c
lassMap
.
get
(
SplashActivity
.
class
));
TaskStackBuilder
stackBuilder
=
TaskStackBuilder
.
create
(
app
);
stackBuilder
.
addParentStack
(
C
lassMap
.
get
(
SplashActivity
.
class
));
stackBuilder
.
addNextIntent
(
intent
);
PendingIntent
pendingIntent
=
stackBuilder
.
getPendingIntent
(
Const
.
ID
.
MAGISK_UPDATE_NOTIFICATION_ID
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
NotificationCompat
.
Builder
builder
=
new
NotificationCompat
.
Builder
(
mm
,
Const
.
ID
.
UPDATE_NOTIFICATION_CHANNEL
);
NotificationCompat
.
Builder
builder
=
new
NotificationCompat
.
Builder
(
app
,
Const
.
ID
.
UPDATE_NOTIFICATION_CHANNEL
);
builder
.
setSmallIcon
(
R
.
drawable
.
ic_magisk_outline
)
.
setContentTitle
(
mm
.
getString
(
R
.
string
.
magisk_update_title
))
.
setContentText
(
mm
.
getString
(
R
.
string
.
magisk_update_available
,
Data
.
remoteMagiskVersionString
))
.
setContentTitle
(
app
.
getString
(
R
.
string
.
magisk_update_title
))
.
setContentText
(
app
.
getString
(
R
.
string
.
magisk_update_available
,
Data
.
remoteMagiskVersionString
))
.
setVibrate
(
new
long
[]{
0
,
100
,
100
,
100
})
.
setAutoCancel
(
true
)
.
setContentIntent
(
pendingIntent
);
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
mm
);
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
app
);
mgr
.
notify
(
Const
.
ID
.
MAGISK_UPDATE_NOTIFICATION_ID
,
builder
.
build
());
}
public
static
void
managerUpdate
()
{
MagiskManager
mm
=
Data
.
MM
()
;
App
app
=
App
.
self
;
String
name
=
Utils
.
fmt
(
"MagiskManager v%s(%d)"
,
Data
.
remoteManagerVersionString
,
Data
.
remoteManagerVersionCode
);
Intent
intent
=
new
Intent
(
mm
,
Data
.
c
lassMap
.
get
(
GeneralReceiver
.
class
));
Intent
intent
=
new
Intent
(
app
,
C
lassMap
.
get
(
GeneralReceiver
.
class
));
intent
.
setAction
(
Const
.
Key
.
BROADCAST_MANAGER_UPDATE
);
intent
.
putExtra
(
Const
.
Key
.
INTENT_SET_LINK
,
Data
.
managerLink
);
intent
.
putExtra
(
Const
.
Key
.
INTENT_SET_NAME
,
name
);
PendingIntent
pendingIntent
=
PendingIntent
.
getBroadcast
(
mm
,
PendingIntent
pendingIntent
=
PendingIntent
.
getBroadcast
(
app
,
Const
.
ID
.
APK_UPDATE_NOTIFICATION_ID
,
intent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
NotificationCompat
.
Builder
builder
=
new
NotificationCompat
.
Builder
(
mm
,
Const
.
ID
.
UPDATE_NOTIFICATION_CHANNEL
);
NotificationCompat
.
Builder
builder
=
new
NotificationCompat
.
Builder
(
app
,
Const
.
ID
.
UPDATE_NOTIFICATION_CHANNEL
);
builder
.
setSmallIcon
(
R
.
drawable
.
ic_magisk_outline
)
.
setContentTitle
(
mm
.
getString
(
R
.
string
.
manager_update_title
))
.
setContentText
(
mm
.
getString
(
R
.
string
.
manager_download_install
))
.
setContentTitle
(
app
.
getString
(
R
.
string
.
manager_update_title
))
.
setContentText
(
app
.
getString
(
R
.
string
.
manager_download_install
))
.
setVibrate
(
new
long
[]{
0
,
100
,
100
,
100
})
.
setAutoCancel
(
true
)
.
setContentIntent
(
pendingIntent
);
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
mm
);
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
app
);
mgr
.
notify
(
Const
.
ID
.
APK_UPDATE_NOTIFICATION_ID
,
builder
.
build
());
}
public
static
void
dtboPatched
()
{
MagiskManager
mm
=
Data
.
MM
()
;
App
app
=
App
.
self
;
Intent
intent
=
new
Intent
(
mm
,
Data
.
c
lassMap
.
get
(
GeneralReceiver
.
class
))
Intent
intent
=
new
Intent
(
app
,
C
lassMap
.
get
(
GeneralReceiver
.
class
))
.
setAction
(
Const
.
Key
.
BROADCAST_REBOOT
);
PendingIntent
pendingIntent
=
PendingIntent
.
getBroadcast
(
mm
,
PendingIntent
pendingIntent
=
PendingIntent
.
getBroadcast
(
app
,
Const
.
ID
.
DTBO_NOTIFICATION_ID
,
intent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
NotificationCompat
.
Builder
builder
=
new
NotificationCompat
.
Builder
(
mm
,
Const
.
ID
.
UPDATE_NOTIFICATION_CHANNEL
);
NotificationCompat
.
Builder
builder
=
new
NotificationCompat
.
Builder
(
app
,
Const
.
ID
.
UPDATE_NOTIFICATION_CHANNEL
);
builder
.
setSmallIcon
(
R
.
drawable
.
ic_magisk_outline
)
.
setContentTitle
(
mm
.
getString
(
R
.
string
.
dtbo_patched_title
))
.
setContentText
(
mm
.
getString
(
R
.
string
.
dtbo_patched_reboot
))
.
setContentTitle
(
app
.
getString
(
R
.
string
.
dtbo_patched_title
))
.
setContentText
(
app
.
getString
(
R
.
string
.
dtbo_patched_reboot
))
.
setVibrate
(
new
long
[]{
0
,
100
,
100
,
100
})
.
addAction
(
R
.
drawable
.
ic_refresh
,
mm
.
getString
(
R
.
string
.
reboot
),
pendingIntent
);
.
addAction
(
R
.
drawable
.
ic_refresh
,
app
.
getString
(
R
.
string
.
reboot
),
pendingIntent
);
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
mm
);
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
app
);
mgr
.
notify
(
Const
.
ID
.
DTBO_NOTIFICATION_ID
,
builder
.
build
());
}
public
static
NotificationCompat
.
Builder
progress
(
String
title
)
{
MagiskManager
mm
=
Data
.
MM
()
;
NotificationCompat
.
Builder
builder
=
new
NotificationCompat
.
Builder
(
mm
,
Const
.
ID
.
PROGRESS_NOTIFICATION_CHANNEL
);
App
app
=
App
.
self
;
NotificationCompat
.
Builder
builder
=
new
NotificationCompat
.
Builder
(
app
,
Const
.
ID
.
PROGRESS_NOTIFICATION_CHANNEL
);
builder
.
setPriority
(
NotificationCompat
.
PRIORITY_LOW
)
.
setSmallIcon
(
android
.
R
.
drawable
.
stat_sys_download
)
.
setContentTitle
(
title
)
...
...
app/src/full/java/com/topjohnwu/magisk/components/ProgressNotification.java
View file @
ff3d66a6
...
...
@@ -2,10 +2,9 @@ package com.topjohnwu.magisk.components;
import
android.widget.Toast
;
import
com.topjohnwu.
magisk.Data
;
import
com.topjohnwu.
magisk.MagiskManager
;
import
com.topjohnwu.
core.App
;
import
com.topjohnwu.
core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.net.DownloadProgressListener
;
import
androidx.core.app.NotificationCompat
;
...
...
@@ -17,12 +16,11 @@ public class ProgressNotification implements DownloadProgressListener {
private
long
prevTime
;
public
ProgressNotification
(
String
title
)
{
MagiskManager
mm
=
Data
.
MM
();
mgr
=
NotificationManagerCompat
.
from
(
mm
);
mgr
=
NotificationManagerCompat
.
from
(
App
.
self
);
builder
=
Notifications
.
progress
(
title
);
prevTime
=
System
.
currentTimeMillis
();
update
();
Utils
.
toast
(
mm
.
getString
(
R
.
string
.
downloading_toast
,
title
),
Toast
.
LENGTH_SHORT
);
Utils
.
toast
(
App
.
self
.
getString
(
R
.
string
.
downloading_toast
,
title
),
Toast
.
LENGTH_SHORT
);
}
@Override
...
...
@@ -47,7 +45,7 @@ public class ProgressNotification implements DownloadProgressListener {
public
void
dlDone
()
{
builder
.
setProgress
(
0
,
0
,
false
)
.
setContentText
(
Data
.
MM
()
.
getString
(
R
.
string
.
download_complete
))
.
setContentText
(
App
.
self
.
getString
(
R
.
string
.
download_complete
))
.
setSmallIcon
(
R
.
drawable
.
ic_check_circle
)
.
setOngoing
(
false
);
update
();
...
...
@@ -55,7 +53,7 @@ public class ProgressNotification implements DownloadProgressListener {
public
void
dlFail
()
{
builder
.
setProgress
(
0
,
0
,
false
)
.
setContentText
(
Data
.
MM
()
.
getString
(
R
.
string
.
download_file_error
))
.
setContentText
(
App
.
self
.
getString
(
R
.
string
.
download_file_error
))
.
setSmallIcon
(
R
.
drawable
.
ic_cancel
)
.
setOngoing
(
false
);
update
();
...
...
app/src/full/java/com/topjohnwu/magisk/components/SnackbarMaker.java
View file @
ff3d66a6
...
...
@@ -6,8 +6,8 @@ import android.view.View;
import
android.widget.TextView
;
import
com.google.android.material.snackbar.Snackbar
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.Utils
;
import
androidx.annotation.StringRes
;
...
...
app/src/full/java/com/topjohnwu/magisk/components/UninstallDialog.java
View file @
ff3d66a6
...
...
@@ -7,11 +7,12 @@ import android.net.Uri;
import
android.text.TextUtils
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.FlashActivity
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.superuser.Shell
;
...
...
@@ -47,7 +48,7 @@ public class UninstallDialog extends CustomAlertDialog {
.
setErrorHandler
(((
conn
,
e
)
->
progress
.
dlFail
()))
.
getAsFile
(
f
->
{
progress
.
dismiss
();
Intent
intent
=
new
Intent
(
activity
,
Data
.
c
lassMap
.
get
(
FlashActivity
.
class
))
Intent
intent
=
new
Intent
(
activity
,
C
lassMap
.
get
(
FlashActivity
.
class
))
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
)
.
setData
(
Uri
.
fromFile
(
f
))
.
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
UNINSTALL
);
...
...
app/src/full/java/com/topjohnwu/magisk/fragments/MagiskFragment.java
View file @
ff3d66a6
...
...
@@ -15,13 +15,15 @@ import android.widget.ProgressBar;
import
android.widget.RelativeLayout
;
import
android.widget.TextView
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.tasks.CheckUpdates
;
import
com.topjohnwu.core.tasks.SafetyNet
;
import
com.topjohnwu.core.utils.ISafetyNetHelper
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MainActivity
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.asyncs.CheckUpdates
;
import
com.topjohnwu.magisk.asyncs.SafetyNet
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.components.BaseFragment
;
import
com.topjohnwu.magisk.components.CustomAlertDialog
;
...
...
@@ -31,8 +33,6 @@ import com.topjohnwu.magisk.components.MagiskInstallDialog;
import
com.topjohnwu.magisk.components.ManagerInstallDialog
;
import
com.topjohnwu.magisk.components.UninstallDialog
;
import
com.topjohnwu.magisk.utils.Download
;
import
com.topjohnwu.magisk.utils.ISafetyNetHelper
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
...
...
@@ -119,7 +119,7 @@ public class MagiskFragment extends BaseFragment
return
;
}
((
NotificationManager
)
mm
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)).
cancelAll
();
((
NotificationManager
)
app
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)).
cancelAll
();
new
MagiskInstallDialog
((
BaseActivity
)
getActivity
()).
show
();
}
...
...
@@ -169,7 +169,7 @@ public class MagiskFragment extends BaseFragment
shownDialog
=
false
;
// Trigger state check
if
(
Download
.
checkNetworkStatus
(
mm
))
{
if
(
Download
.
checkNetworkStatus
(
app
))
{
CheckUpdates
.
check
();
}
else
{
mSwipeRefreshLayout
.
setRefreshing
(
false
);
...
...
@@ -199,7 +199,7 @@ public class MagiskFragment extends BaseFragment
}
private
boolean
hasGms
()
{
PackageManager
pm
=
mm
.
getPackageManager
();
PackageManager
pm
=
app
.
getPackageManager
();
PackageInfo
info
;
try
{
info
=
pm
.
getPackageInfo
(
"com.google.android.gms"
,
0
);
...
...
@@ -212,13 +212,13 @@ public class MagiskFragment extends BaseFragment
private
void
updateUI
()
{
((
MainActivity
)
requireActivity
()).
checkHideSection
();
boolean
hasNetwork
=
Download
.
checkNetworkStatus
(
mm
);
boolean
hasNetwork
=
Download
.
checkNetworkStatus
(
app
);
boolean
hasRoot
=
Shell
.
rootAccess
();
magiskUpdate
.
setVisibility
(
hasNetwork
?
View
.
VISIBLE
:
View
.
GONE
);
installOptionCard
.
setVisibility
(
hasNetwork
?
View
.
VISIBLE
:
View
.
GONE
);
uninstallButton
.
setVisibility
(
hasRoot
?
View
.
VISIBLE
:
View
.
GONE
);
coreOnlyNotice
.
setVisibility
(
mm
.
prefs
.
getBoolean
(
Const
.
Key
.
COREONLY
,
false
)
?
View
.
VISIBLE
:
View
.
GONE
);
coreOnlyNotice
.
setVisibility
(
app
.
prefs
.
getBoolean
(
Const
.
Key
.
COREONLY
,
false
)
?
View
.
VISIBLE
:
View
.
GONE
);
int
image
,
color
;
...
...
app/src/full/java/com/topjohnwu/magisk/fragments/MagiskHideFragment.java
View file @
ff3d66a6
...
...
@@ -8,10 +8,10 @@ import android.view.View;
import
android.view.ViewGroup
;
import
android.widget.SearchView
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.adapters.ApplicationAdapter
;
import
com.topjohnwu.magisk.components.BaseFragment
;
import
com.topjohnwu.magisk.utils.Topic
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
...
...
app/src/full/java/com/topjohnwu/magisk/fragments/MagiskLogFragment.java
View file @
ff3d66a6
...
...
@@ -15,11 +15,11 @@ import android.widget.ScrollView;
import
android.widget.TextView
;
import
com.google.android.material.snackbar.Snackbar
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.components.BaseFragment
;
import
com.topjohnwu.magisk.components.SnackbarMaker
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
java.io.File
;
...
...
app/src/full/java/com/topjohnwu/magisk/fragments/ModulesFragment.java
View file @
ff3d66a6
...
...
@@ -12,15 +12,15 @@ import android.view.View;
import
android.view.ViewGroup
;
import
android.widget.TextView
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.container.Module
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.FlashActivity
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.adapters.ModulesAdapter
;
import
com.topjohnwu.magisk.components.BaseFragment
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
java.util.ArrayList
;
...
...
@@ -94,7 +94,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
public
void
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
if
(
requestCode
==
Const
.
ID
.
FETCH_ZIP
&&
resultCode
==
Activity
.
RESULT_OK
&&
data
!=
null
)
{
// Get the URI of the selected file
Intent
intent
=
new
Intent
(
getActivity
(),
Data
.
c
lassMap
.
get
(
FlashActivity
.
class
));
Intent
intent
=
new
Intent
(
getActivity
(),
C
lassMap
.
get
(
FlashActivity
.
class
));
intent
.
setData
(
data
.
getData
()).
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
FLASH_ZIP
);
startActivity
(
intent
);
}
...
...
app/src/full/java/com/topjohnwu/magisk/fragments/ReposFragment.java
View file @
ff3d66a6
...
...
@@ -11,14 +11,14 @@ import android.view.ViewGroup;
import
android.widget.SearchView
;
import
android.widget.TextView
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.container.Module
;
import
com.topjohnwu.core.tasks.UpdateRepos
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.adapters.ReposAdapter
;
import
com.topjohnwu.magisk.asyncs.UpdateRepos
;
import
com.topjohnwu.magisk.components.BaseFragment
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.magisk.utils.Topic
;
import
java.util.Map
;
...
...
@@ -70,8 +70,8 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
@Override
public
void
onPublish
(
int
topic
,
Object
[]
result
)
{
if
(
topic
==
Topic
.
MODULE_LOAD_DONE
)
{
adapter
=
new
ReposAdapter
(
mm
.
repoDB
,
(
Map
<
String
,
Module
>)
result
[
0
]);
mm
.
repoDB
.
registerAdapter
(
adapter
);
adapter
=
new
ReposAdapter
(
app
.
repoDB
,
(
Map
<
String
,
Module
>)
result
[
0
]);
app
.
repoDB
.
registerAdapterCallback
(
adapter:
:
notifyDBChanged
);
recyclerView
.
setAdapter
(
adapter
);
recyclerView
.
setVisibility
(
View
.
VISIBLE
);
emptyRv
.
setVisibility
(
View
.
GONE
);
...
...
@@ -108,7 +108,7 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
.
setTitle
(
R
.
string
.
sorting_order
)
.
setSingleChoiceItems
(
R
.
array
.
sorting_orders
,
Data
.
repoOrder
,
(
d
,
which
)
->
{
Data
.
repoOrder
=
which
;
mm
.
prefs
.
edit
().
putInt
(
Const
.
Key
.
REPO_ORDER
,
Data
.
repoOrder
).
apply
();
app
.
prefs
.
edit
().
putInt
(
Const
.
Key
.
REPO_ORDER
,
Data
.
repoOrder
).
apply
();
adapter
.
notifyDBChanged
();
d
.
dismiss
();
}).
show
();
...
...
@@ -119,6 +119,6 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
@Override
public
void
onDestroyView
()
{
super
.
onDestroyView
();
mm
.
repoDB
.
unregisterAdapter
();
app
.
repoDB
.
unregisterAdapterCallback
();
}
}
app/src/full/java/com/topjohnwu/magisk/fragments/SettingsFragment.java
View file @
ff3d66a6
...
...
@@ -10,19 +10,20 @@ import android.view.ViewGroup;
import
android.widget.EditText
;
import
android.widget.Toast
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.tasks.CheckUpdates
;
import
com.topjohnwu.core.utils.LocaleManager
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.asyncs.CheckUpdates
;
import
com.topjohnwu.magisk.asyncs.PatchAPK
;
import
com.topjohnwu.magisk.utils.DlInstallManager
;
import
com.topjohnwu.magisk.utils.AppUtils
;
import
com.topjohnwu.magisk.utils.Download
;
import
com.topjohnwu.magisk.utils.DownloadApp
;
import
com.topjohnwu.magisk.utils.FingerprintHelper
;
import
com.topjohnwu.magisk.utils.LocaleManager
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.PatchAPK
;
import
com.topjohnwu.superuser.Shell
;
import
java.io.IOException
;
...
...
@@ -43,7 +44,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
implements
SharedPreferences
.
OnSharedPreferenceChangeListener
,
Topic
.
Subscriber
,
Topic
.
AutoSubscriber
{
private
MagiskManager
mm
;
private
App
app
=
App
.
self
;
private
ListPreference
updateChannel
,
autoRes
,
suNotification
,
requestTimeout
,
rootConfig
,
multiuserConfig
,
nsConfig
;
...
...
@@ -52,10 +53,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
private
boolean
showSuperuser
;
private
void
prefsSync
()
{
rootState
=
mm
.
mDB
.
getSettings
(
Const
.
Key
.
ROOT_ACCESS
,
Const
.
Value
.
ROOT_ACCESS_APPS_AND_ADB
);
namespaceState
=
mm
.
mDB
.
getSettings
(
Const
.
Key
.
SU_MNT_NS
,
Const
.
Value
.
NAMESPACE_MODE_REQUESTER
);
rootState
=
app
.
mDB
.
getSettings
(
Const
.
Key
.
ROOT_ACCESS
,
Const
.
Value
.
ROOT_ACCESS_APPS_AND_ADB
);
namespaceState
=
app
.
mDB
.
getSettings
(
Const
.
Key
.
SU_MNT_NS
,
Const
.
Value
.
NAMESPACE_MODE_REQUESTER
);
showSuperuser
=
Utils
.
showSuperUser
();
mm
.
prefs
.
edit
()
app
.
prefs
.
edit
()
.
putString
(
Const
.
Key
.
ROOT_ACCESS
,
String
.
valueOf
(
rootState
))
.
putString
(
Const
.
Key
.
SU_MNT_NS
,
String
.
valueOf
(
namespaceState
))
.
putString
(
Const
.
Key
.
SU_MULTIUSER_MODE
,
String
.
valueOf
(
Data
.
multiuserState
))
...
...
@@ -65,7 +66,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
@Override
public
void
onCreatePreferences
(
Bundle
savedInstanceState
,
String
rootKey
)
{
mm
=
Data
.
MM
();
prefsSync
();
setPreferencesFromResource
(
R
.
xml
.
app_settings
,
rootKey
);
...
...
@@ -82,12 +82,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
});
Preference
restoreManager
=
findPreference
(
"restore"
);
restoreManager
.
setOnPreferenceClickListener
(
pref
->
{
D
lInstallManager
.
restore
();
D
ownloadApp
.
restore
();
return
true
;
});
findPreference
(
"clear"
).
setOnPreferenceClickListener
(
pref
->
{
mm
.
prefs
.
edit
().
remove
(
Const
.
Key
.
ETAG_KEY
).
apply
();
mm
.
repoDB
.
clearRepo
();
app
.
prefs
.
edit
().
remove
(
Const
.
Key
.
ETAG_KEY
).
apply
();
app
.
repoDB
.
clearRepo
();
Utils
.
toast
(
R
.
string
.
repo_cache_cleared
,
Toast
.
LENGTH_SHORT
);
return
true
;
});
...
...
@@ -114,17 +114,17 @@ public class SettingsFragment extends PreferenceFragmentCompat
if
(
channel
==
Const
.
Value
.
CUSTOM_CHANNEL
)
{
View
v
=
LayoutInflater
.
from
(
requireActivity
()).
inflate
(
R
.
layout
.
custom_channel_dialog
,
null
);
EditText
url
=
v
.
findViewById
(
R
.
id
.
custom_url
);
url
.
setText
(
mm
.
prefs
.
getString
(
Const
.
Key
.
CUSTOM_CHANNEL
,
""
));
url
.
setText
(
app
.
prefs
.
getString
(
Const
.
Key
.
CUSTOM_CHANNEL
,
""
));
new
AlertDialog
.
Builder
(
requireActivity
())
.
setTitle
(
R
.
string
.
settings_update_custom
)
.
setView
(
v
)
.
setPositiveButton
(
R
.
string
.
ok
,
(
d
,
i
)
->
mm
.
prefs
.
edit
().
putString
(
Const
.
Key
.
CUSTOM_CHANNEL
,
app
.
prefs
.
edit
().
putString
(
Const
.
Key
.
CUSTOM_CHANNEL
,
url
.
getText
().
toString
()).
apply
())
.
setNegativeButton
(
R
.
string
.
close
,
(
d
,
i
)
->
mm
.
prefs
.
edit
().
putString
(
Const
.
Key
.
UPDATE_CHANNEL
,
prev
).
apply
())
app
.
prefs
.
edit
().
putString
(
Const
.
Key
.
UPDATE_CHANNEL
,
prev
).
apply
())
.
setOnCancelListener
(
d
->
mm
.
prefs
.
edit
().
putString
(
Const
.
Key
.
UPDATE_CHANNEL
,
prev
).
apply
())
app
.
prefs
.
edit
().
putString
(
Const
.
Key
.
UPDATE_CHANNEL
,
prev
).
apply
())
.
show
();
}
return
true
;
...
...
@@ -152,10 +152,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
}
if
(
Shell
.
rootAccess
()
&&
Const
.
USER_ID
==
0
)
{
if
(
mm
.
getPackageName
().
equals
(
BuildConfig
.
APPLICATION_ID
))
{
if
(
app
.
getPackageName
().
equals
(
BuildConfig
.
APPLICATION_ID
))
{
generalCatagory
.
removePreference
(
restoreManager
);
}
else
{
if
(!
Download
.
checkNetworkStatus
(
mm
))
if
(!
Download
.
checkNetworkStatus
(
app
))
generalCatagory
.
removePreference
(
restoreManager
);
generalCatagory
.
removePreference
(
hideManager
);
}
...
...
@@ -191,7 +191,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
@Override
public
View
onCreateView
(
LayoutInflater
inflater
,
ViewGroup
container
,
Bundle
savedInstanceState
)
{
mm
.
prefs
.
registerOnSharedPreferenceChangeListener
(
this
);
app
.
prefs
.
registerOnSharedPreferenceChangeListener
(
this
);
Topic
.
subscribe
(
this
);
requireActivity
().
setTitle
(
R
.
string
.
settings
);
return
super
.
onCreateView
(
inflater
,
container
,
savedInstanceState
);
...
...
@@ -199,7 +199,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
@Override
public
void
onDestroyView
()
{
mm
.
prefs
.
unregisterOnSharedPreferenceChangeListener
(
this
);
app
.
prefs
.
unregisterOnSharedPreferenceChangeListener
(
this
);
Topic
.
unsubscribe
(
this
);
super
.
onDestroyView
();
}
...
...
@@ -210,7 +210,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
case
Const
.
Key
.
ROOT_ACCESS
:
case
Const
.
Key
.
SU_MULTIUSER_MODE
:
case
Const
.
Key
.
SU_MNT_NS
:
mm
.
mDB
.
setSettings
(
key
,
Utils
.
getPrefsInt
(
prefs
,
key
));
app
.
mDB
.
setSettings
(
key
,
Utils
.
getPrefsInt
(
prefs
,
key
));
break
;
}
switch
(
key
)
{
...
...
@@ -244,7 +244,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
}
break
;
case
Const
.
Key
.
LOCALE
:
LocaleManager
.
setLocale
(
mm
);
LocaleManager
.
setLocale
(
app
);
requireActivity
().
recreate
();
break
;
case
Const
.
Key
.
UPDATE_CHANNEL
:
...
...
@@ -252,7 +252,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
CheckUpdates
.
check
();
break
;
case
Const
.
Key
.
CHECK_UPDATES
:
Utils
.
setupUpdateCheck
();
App
Utils
.
setupUpdateCheck
();
break
;
}
Data
.
loadConfig
();
...
...
@@ -268,7 +268,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
((
SwitchPreference
)
preference
).
setChecked
(!
checked
);
FingerprintHelper
.
showAuthDialog
(
requireActivity
(),
()
->
{
((
SwitchPreference
)
preference
).
setChecked
(
checked
);
mm
.
mDB
.
setSettings
(
key
,
checked
?
1
:
0
);
app
.
mDB
.
setSettings
(
key
,
checked
?
1
:
0
);
});
break
;
}
...
...
@@ -286,7 +286,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
.
getStringArray
(
R
.
array
.
su_notification
)[
Data
.
suNotificationType
]);
requestTimeout
.
setSummary
(
getString
(
R
.
string
.
request_timeout_summary
,
mm
.
prefs
.
getString
(
Const
.
Key
.
SU_REQUEST_TIMEOUT
,
"10"
)));
app
.
prefs
.
getString
(
Const
.
Key
.
SU_REQUEST_TIMEOUT
,
"10"
)));
multiuserConfig
.
setSummary
(
getResources
()
.
getStringArray
(
R
.
array
.
multiuser_summary
)[
Data
.
multiuserState
]);
nsConfig
.
setSummary
(
getResources
()
...
...
app/src/full/java/com/topjohnwu/magisk/fragments/SuLogFragment.java
View file @
ff3d66a6
...
...
@@ -42,7 +42,7 @@ public class SuLogFragment extends BaseFragment {
// Inflate the layout for this fragment
View
v
=
inflater
.
inflate
(
R
.
layout
.
fragment_su_log
,
container
,
false
);
unbinder
=
new
SuLogFragment_ViewBinding
(
this
,
v
);
adapter
=
new
SuLogAdapter
(
mm
.
mDB
);
adapter
=
new
SuLogAdapter
(
app
.
mDB
);
recyclerView
.
setAdapter
(
adapter
);
updateList
();
...
...
@@ -69,7 +69,7 @@ public class SuLogFragment extends BaseFragment {
updateList
();
return
true
;
case
R
.
id
.
menu_clear
:
mm
.
mDB
.
clearLogs
();
app
.
mDB
.
clearLogs
();
updateList
();
return
true
;
default
:
...
...
app/src/full/java/com/topjohnwu/magisk/fragments/SuperuserFragment.java
View file @
ff3d66a6
...
...
@@ -7,10 +7,10 @@ import android.view.View;
import
android.view.ViewGroup
;
import
android.widget.TextView
;
import
com.topjohnwu.core.container.Policy
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.adapters.PolicyAdapter
;
import
com.topjohnwu.magisk.components.BaseFragment
;
import
com.topjohnwu.magisk.container.Policy
;
import
java.util.List
;
...
...
@@ -48,13 +48,13 @@ public class SuperuserFragment extends BaseFragment {
}
private
void
displayPolicyList
()
{
List
<
Policy
>
policyList
=
mm
.
mDB
.
getPolicyList
();
List
<
Policy
>
policyList
=
app
.
mDB
.
getPolicyList
();
if
(
policyList
.
size
()
==
0
)
{
emptyRv
.
setVisibility
(
View
.
VISIBLE
);
recyclerView
.
setVisibility
(
View
.
GONE
);
}
else
{
recyclerView
.
setAdapter
(
new
PolicyAdapter
(
policyList
,
mm
.
mDB
,
pm
));
recyclerView
.
setAdapter
(
new
PolicyAdapter
(
policyList
,
app
.
mDB
,
pm
));
emptyRv
.
setVisibility
(
View
.
GONE
);
recyclerView
.
setVisibility
(
View
.
VISIBLE
);
}
...
...
app/src/full/java/com/topjohnwu/magisk/receivers/GeneralReceiver.java
View file @
ff3d66a6
...
...
@@ -4,12 +4,13 @@ import android.content.BroadcastReceiver;
import
android.content.Context
;
import
android.content.Intent
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.SuRequestActivity
;
import
com.topjohnwu.magisk.services.OnBootService
;
import
com.topjohnwu.magisk.utils.D
lInstallManager
;
import
com.topjohnwu.magisk.utils.D
ownloadApp
;
import
com.topjohnwu.magisk.utils.SuConnector
;
import
com.topjohnwu.superuser.Shell
;
...
...
@@ -21,7 +22,7 @@ public class GeneralReceiver extends BroadcastReceiver {
@Override
public
void
onReceive
(
Context
context
,
Intent
intent
)
{
MagiskManager
mm
=
Data
.
MM
()
;
App
app
=
App
.
self
;
if
(
intent
==
null
)
return
;
String
action
=
intent
.
getAction
();
...
...
@@ -34,10 +35,10 @@ public class GeneralReceiver extends BroadcastReceiver {
bootAction
=
"boot"
;
switch
(
bootAction
)
{
case
"request"
:
Intent
i
=
new
Intent
(
mm
,
Data
.
c
lassMap
.
get
(
SuRequestActivity
.
class
))
Intent
i
=
new
Intent
(
app
,
C
lassMap
.
get
(
SuRequestActivity
.
class
))
.
putExtra
(
"socket"
,
intent
.
getStringExtra
(
"socket"
))
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
);
mm
.
startActivity
(
i
);
app
.
startActivity
(
i
);
break
;
case
"log"
:
SuConnector
.
handleLogs
(
intent
);
...
...
@@ -48,24 +49,24 @@ public class GeneralReceiver extends BroadcastReceiver {
case
"boot"
:
default
:
/* The actual on-boot trigger */
OnBootService
.
enqueueWork
(
mm
);
OnBootService
.
enqueueWork
(
app
);
break
;
}
break
;
case
Intent
.
ACTION_PACKAGE_REPLACED
:
// This will only work pre-O
if
(
mm
.
prefs
.
getBoolean
(
Const
.
Key
.
SU_REAUTH
,
false
))
{
mm
.
mDB
.
deletePolicy
(
getPkg
(
intent
));
if
(
app
.
prefs
.
getBoolean
(
Const
.
Key
.
SU_REAUTH
,
false
))
{
app
.
mDB
.
deletePolicy
(
getPkg
(
intent
));
}
break
;
case
Intent
.
ACTION_PACKAGE_FULLY_REMOVED
:
String
pkg
=
getPkg
(
intent
);
mm
.
mDB
.
deletePolicy
(
pkg
);
app
.
mDB
.
deletePolicy
(
pkg
);
Shell
.
su
(
"magiskhide --rm "
+
pkg
).
submit
();
break
;
case
Const
.
Key
.
BROADCAST_MANAGER_UPDATE
:
Data
.
managerLink
=
intent
.
getStringExtra
(
Const
.
Key
.
INTENT_SET_LINK
);
D
lInstallManager
.
upgrade
(
intent
.
getStringExtra
(
Const
.
Key
.
INTENT_SET_NAME
));
D
ownloadApp
.
upgrade
(
intent
.
getStringExtra
(
Const
.
Key
.
INTENT_SET_NAME
));
break
;
case
Const
.
Key
.
BROADCAST_REBOOT
:
Shell
.
su
(
"/system/bin/reboot"
).
submit
();
...
...
app/src/full/java/com/topjohnwu/magisk/receivers/ShortcutReceiver.java
View file @
ff3d66a6
...
...
@@ -8,12 +8,13 @@ import android.content.pm.ShortcutManager;
import
android.graphics.drawable.Icon
;
import
android.os.Build
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.SplashActivity
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
java.util.ArrayList
;
...
...
@@ -24,55 +25,54 @@ public class ShortcutReceiver extends BroadcastReceiver {
@Override
public
void
onReceive
(
Context
context
,
Intent
intent
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
N_MR1
)
{
MagiskManager
mm
=
Data
.
MM
();
ShortcutManager
manager
=
context
.
getSystemService
(
ShortcutManager
.
class
);
manager
.
setDynamicShortcuts
(
getShortCuts
(
mm
));
manager
.
setDynamicShortcuts
(
getShortCuts
(
App
.
self
));
}
}
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
N_MR1
)
private
ArrayList
<
ShortcutInfo
>
getShortCuts
(
MagiskManager
mm
)
{
private
ArrayList
<
ShortcutInfo
>
getShortCuts
(
App
app
)
{
ArrayList
<
ShortcutInfo
>
shortCuts
=
new
ArrayList
<>();
boolean
root
=
Shell
.
rootAccess
();
if
(
Utils
.
showSuperUser
())
{
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
mm
,
"superuser"
)
.
setShortLabel
(
mm
.
getString
(
R
.
string
.
superuser
))
.
setIntent
(
new
Intent
(
mm
,
Data
.
c
lassMap
.
get
(
SplashActivity
.
class
))
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
app
,
"superuser"
)
.
setShortLabel
(
app
.
getString
(
R
.
string
.
superuser
))
.
setIntent
(
new
Intent
(
app
,
C
lassMap
.
get
(
SplashActivity
.
class
))
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"superuser"
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
setIcon
(
Icon
.
createWithResource
(
mm
,
R
.
drawable
.
sc_superuser
))
.
setIcon
(
Icon
.
createWithResource
(
app
,
R
.
drawable
.
sc_superuser
))
.
setRank
(
0
)
.
build
());
}
if
(
root
&&
mm
.
prefs
.
getBoolean
(
Const
.
Key
.
MAGISKHIDE
,
false
))
{
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
mm
,
"magiskhide"
)
.
setShortLabel
(
mm
.
getString
(
R
.
string
.
magiskhide
))
.
setIntent
(
new
Intent
(
mm
,
Data
.
c
lassMap
.
get
(
SplashActivity
.
class
))
if
(
root
&&
app
.
prefs
.
getBoolean
(
Const
.
Key
.
MAGISKHIDE
,
false
))
{
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
app
,
"magiskhide"
)
.
setShortLabel
(
app
.
getString
(
R
.
string
.
magiskhide
))
.
setIntent
(
new
Intent
(
app
,
C
lassMap
.
get
(
SplashActivity
.
class
))
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"magiskhide"
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
setIcon
(
Icon
.
createWithResource
(
mm
,
R
.
drawable
.
sc_magiskhide
))
.
setIcon
(
Icon
.
createWithResource
(
app
,
R
.
drawable
.
sc_magiskhide
))
.
setRank
(
1
)
.
build
());
}
if
(!
mm
.
prefs
.
getBoolean
(
Const
.
Key
.
COREONLY
,
false
)
&&
root
&&
Data
.
magiskVersionCode
>=
0
)
{
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
mm
,
"modules"
)
.
setShortLabel
(
mm
.
getString
(
R
.
string
.
modules
))
.
setIntent
(
new
Intent
(
mm
,
Data
.
c
lassMap
.
get
(
SplashActivity
.
class
))
if
(!
app
.
prefs
.
getBoolean
(
Const
.
Key
.
COREONLY
,
false
)
&&
root
&&
Data
.
magiskVersionCode
>=
0
)
{
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
app
,
"modules"
)
.
setShortLabel
(
app
.
getString
(
R
.
string
.
modules
))
.
setIntent
(
new
Intent
(
app
,
C
lassMap
.
get
(
SplashActivity
.
class
))
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"modules"
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
setIcon
(
Icon
.
createWithResource
(
mm
,
R
.
drawable
.
sc_extension
))
.
setIcon
(
Icon
.
createWithResource
(
app
,
R
.
drawable
.
sc_extension
))
.
setRank
(
3
)
.
build
());
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
mm
,
"downloads"
)
.
setShortLabel
(
mm
.
getString
(
R
.
string
.
downloads
))
.
setIntent
(
new
Intent
(
mm
,
Data
.
c
lassMap
.
get
(
SplashActivity
.
class
))
shortCuts
.
add
(
new
ShortcutInfo
.
Builder
(
app
,
"downloads"
)
.
setShortLabel
(
app
.
getString
(
R
.
string
.
downloads
))
.
setIntent
(
new
Intent
(
app
,
C
lassMap
.
get
(
SplashActivity
.
class
))
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"downloads"
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
))
.
setIcon
(
Icon
.
createWithResource
(
mm
,
R
.
drawable
.
sc_cloud_download
))
.
setIcon
(
Icon
.
createWithResource
(
app
,
R
.
drawable
.
sc_cloud_download
))
.
setRank
(
2
)
.
build
());
}
...
...
app/src/full/java/com/topjohnwu/magisk/services/OnBootService.java
View file @
ff3d66a6
...
...
@@ -3,8 +3,8 @@ package com.topjohnwu.magisk.services;
import
android.content.Context
;
import
android.content.Intent
;
import
com.topjohnwu.
magisk
.Const
;
import
com.topjohnwu.magisk.
Data
;
import
com.topjohnwu.
core
.Const
;
import
com.topjohnwu.magisk.
ClassMap
;
import
com.topjohnwu.magisk.components.Notifications
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
...
...
@@ -15,7 +15,7 @@ import androidx.core.app.JobIntentService;
public
class
OnBootService
extends
JobIntentService
{
public
static
void
enqueueWork
(
Context
context
)
{
enqueueWork
(
context
,
Data
.
c
lassMap
.
get
(
OnBootService
.
class
),
Const
.
ID
.
ONBOOT_SERVICE_ID
,
new
Intent
());
enqueueWork
(
context
,
C
lassMap
.
get
(
OnBootService
.
class
),
Const
.
ID
.
ONBOOT_SERVICE_ID
,
new
Intent
());
}
@Override
...
...
app/src/full/java/com/topjohnwu/magisk/services/UpdateCheckService.java
View file @
ff3d66a6
...
...
@@ -3,7 +3,10 @@ package com.topjohnwu.magisk.services;
import
android.app.job.JobParameters
;
import
android.app.job.JobService
;
import
com.topjohnwu.magisk.asyncs.CheckUpdates
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.tasks.CheckUpdates
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.components.Notifications
;
import
com.topjohnwu.superuser.Shell
;
public
class
UpdateCheckService
extends
JobService
{
...
...
@@ -11,7 +14,14 @@ public class UpdateCheckService extends JobService {
@Override
public
boolean
onStartJob
(
JobParameters
params
)
{
Shell
.
getShell
();
CheckUpdates
.
check
(()
->
jobFinished
(
params
,
false
));
CheckUpdates
.
check
(()
->
{
if
(
BuildConfig
.
VERSION_CODE
<
Data
.
remoteManagerVersionCode
)
{
Notifications
.
managerUpdate
();
}
else
if
(
Data
.
magiskVersionCode
<
Data
.
remoteMagiskVersionCode
)
{
Notifications
.
magiskUpdate
();
}
jobFinished
(
params
,
false
);
});
return
true
;
}
...
...
app/src/full/java/com/topjohnwu/magisk/utils/AppUtils.java
0 → 100644
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
utils
;
import
android.app.job.JobInfo
;
import
android.app.job.JobScheduler
;
import
android.content.ComponentName
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.widget.Toast
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.services.UpdateCheckService
;
public
class
AppUtils
{
public
static
void
setupUpdateCheck
()
{
App
app
=
App
.
self
;
JobScheduler
scheduler
=
(
JobScheduler
)
app
.
getSystemService
(
Context
.
JOB_SCHEDULER_SERVICE
);
if
(
app
.
prefs
.
getBoolean
(
Const
.
Key
.
CHECK_UPDATES
,
true
))
{
if
(
scheduler
.
getAllPendingJobs
().
isEmpty
()
||
Const
.
UPDATE_SERVICE_VER
>
app
.
prefs
.
getInt
(
Const
.
Key
.
UPDATE_SERVICE_VER
,
-
1
))
{
ComponentName
service
=
new
ComponentName
(
app
,
ClassMap
.
get
(
UpdateCheckService
.
class
));
JobInfo
info
=
new
JobInfo
.
Builder
(
Const
.
ID
.
UPDATE_SERVICE_ID
,
service
)
.
setRequiredNetworkType
(
JobInfo
.
NETWORK_TYPE_ANY
)
.
setPersisted
(
true
)
.
setPeriodic
(
8
*
60
*
60
*
1000
)
.
build
();
scheduler
.
schedule
(
info
);
}
}
else
{
scheduler
.
cancel
(
Const
.
UPDATE_SERVICE_VER
);
}
}
public
static
void
openLink
(
Context
context
,
Uri
link
)
{
Intent
intent
=
new
Intent
(
Intent
.
ACTION_VIEW
,
link
);
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
);
if
(
intent
.
resolveActivity
(
context
.
getPackageManager
())
!=
null
)
{
context
.
startActivity
(
intent
);
}
else
{
Utils
.
toast
(
R
.
string
.
open_link_failed_toast
,
Toast
.
LENGTH_SHORT
);
}
}
}
\ No newline at end of file
app/src/full/java/com/topjohnwu/magisk/utils/D
lInstallManager
.java
→
app/src/full/java/com/topjohnwu/magisk/utils/D
ownloadApp
.java
View file @
ff3d66a6
...
...
@@ -2,11 +2,12 @@ package com.topjohnwu.magisk.utils;
import
android.os.AsyncTask
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.utils.RootUtils
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.asyncs.PatchAPK
;
import
com.topjohnwu.magisk.components.ProgressNotification
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.net.ResponseListener
;
...
...
@@ -18,7 +19,7 @@ import java.io.BufferedOutputStream;
import
java.io.File
;
import
java.io.FileOutputStream
;
public
class
D
lInstallManager
{
public
class
D
ownloadApp
{
public
static
void
upgrade
(
String
name
)
{
dlInstall
(
name
,
new
PatchPackageName
());
...
...
@@ -31,8 +32,7 @@ public class DlInstallManager {
}
private
static
void
dlInstall
(
String
name
,
ManagerDownloadListener
listener
)
{
MagiskManager
mm
=
Data
.
MM
();
File
apk
=
new
File
(
mm
.
getFilesDir
(),
"manager.apk"
);
File
apk
=
new
File
(
App
.
self
.
getFilesDir
(),
"manager.apk"
);
ProgressNotification
progress
=
new
ProgressNotification
(
name
);
listener
.
setProgressNotification
(
progress
);
Networking
.
get
(
Data
.
managerLink
)
...
...
@@ -63,23 +63,23 @@ public class DlInstallManager {
@Override
public
void
onDownloadComplete
(
File
apk
,
ProgressNotification
progress
)
{
File
patched
=
apk
;
MagiskManager
mm
=
Data
.
MM
()
;
if
(!
mm
.
getPackageName
().
equals
(
BuildConfig
.
APPLICATION_ID
))
{
App
app
=
App
.
self
;
if
(!
App
.
self
.
getPackageName
().
equals
(
BuildConfig
.
APPLICATION_ID
))
{
progress
.
getNotification
()
.
setProgress
(
0
,
0
,
true
)
.
setContentTitle
(
mm
.
getString
(
R
.
string
.
hide_manager_title
))
.
setContentTitle
(
app
.
getString
(
R
.
string
.
hide_manager_title
))
.
setContentText
(
""
);
progress
.
update
();
patched
=
new
File
(
apk
.
getParent
(),
"patched.apk"
);
try
{
JarMap
jarMap
=
new
JarMap
(
apk
);
PatchAPK
.
patch
(
jarMap
,
mm
.
getPackageName
());
PatchAPK
.
patch
(
jarMap
,
app
.
getPackageName
());
SignAPK
.
sign
(
jarMap
,
new
BufferedOutputStream
(
new
FileOutputStream
(
patched
)));
}
catch
(
Exception
e
)
{
return
;
}
}
APKInstall
.
install
(
mm
,
patched
);
APKInstall
.
install
(
app
,
patched
);
progress
.
dismiss
();
}
}
...
...
@@ -88,17 +88,17 @@ public class DlInstallManager {
@Override
public
void
onDownloadComplete
(
File
apk
,
ProgressNotification
progress
)
{
MagiskManager
mm
=
Data
.
MM
()
;
App
app
=
App
.
self
;
progress
.
getNotification
()
.
setProgress
(
0
,
0
,
true
)
.
setContentTitle
(
mm
.
getString
(
R
.
string
.
restore_img_msg
))
.
setContentTitle
(
app
.
getString
(
R
.
string
.
restore_img_msg
))
.
setContentText
(
""
);
progress
.
update
();
Data
.
exportPrefs
();
// Make it world readable
apk
.
setReadable
(
true
,
false
);
if
(
ShellUtils
.
fastCmdResult
(
"pm install "
+
apk
))
RootUtils
.
rmAndLaunch
(
mm
.
getPackageName
(),
BuildConfig
.
APPLICATION_ID
);
RootUtils
.
rmAndLaunch
(
app
.
getPackageName
(),
BuildConfig
.
APPLICATION_ID
);
progress
.
dismiss
();
}
}
...
...
app/src/full/java/com/topjohnwu/magisk/
async
s/DownloadModule.java
→
app/src/full/java/com/topjohnwu/magisk/
util
s/DownloadModule.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
async
s
;
package
com
.
topjohnwu
.
magisk
.
util
s
;
import
android.Manifest
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.os.AsyncTask
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.container.Repo
;
import
com.topjohnwu.magisk.ClassMap
;
import
com.topjohnwu.magisk.FlashActivity
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.components.ProgressNotification
;
import
com.topjohnwu.magisk.container.Repo
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.superuser.ShellUtils
;
...
...
@@ -28,26 +27,25 @@ import java.util.zip.ZipOutputStream;
public
class
DownloadModule
{
public
static
void
exec
(
BaseActivity
activity
,
Repo
repo
,
boolean
install
)
{
activity
.
runWith
Permission
(
new
String
[]
{
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
},
()
->
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
dlProcessInstall
(
repo
,
install
)));
activity
.
runWith
ExternalRW
(()
->
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(
()
->
dlProcessInstall
(
repo
,
install
)));
}
private
static
void
dlProcessInstall
(
Repo
repo
,
boolean
install
)
{
File
output
=
new
File
(
Const
.
EXTERNAL_PATH
,
repo
.
getDownloadFilename
());
ProgressNotification
progress
=
new
ProgressNotification
(
output
.
getName
());
try
{
MagiskManager
mm
=
Data
.
MM
();
InputStream
in
=
Networking
.
get
(
repo
.
getZipUrl
())
.
setDownloadProgressListener
(
progress
)
.
execForInputStream
().
getResult
();
removeTopFolder
(
in
,
new
BufferedOutputStream
(
new
FileOutputStream
(
output
)));
if
(
install
)
{
progress
.
dismiss
();
Intent
intent
=
new
Intent
(
mm
,
Data
.
c
lassMap
.
get
(
FlashActivity
.
class
));
Intent
intent
=
new
Intent
(
App
.
self
,
C
lassMap
.
get
(
FlashActivity
.
class
));
intent
.
setData
(
Uri
.
fromFile
(
output
))
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
)
.
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
FLASH_ZIP
);
mm
.
startActivity
(
intent
);
App
.
self
.
startActivity
(
intent
);
}
else
{
progress
.
getNotification
().
setContentTitle
(
output
.
getName
());
progress
.
dlDone
();
...
...
app/src/full/java/com/topjohnwu/magisk/utils/FingerprintHelper.java
View file @
ff3d66a6
...
...
@@ -16,9 +16,9 @@ import android.security.keystore.KeyProperties;
import
android.view.Gravity
;
import
android.widget.Toast
;
import
com.topjohnwu.
magisk.Const
;
import
com.topjohnwu.
magisk.Data
;
import
com.topjohnwu.
magisk.MagiskManager
;
import
com.topjohnwu.
core.App
;
import
com.topjohnwu.
core.Const
;
import
com.topjohnwu.
core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.components.CustomAlertDialog
;
...
...
@@ -36,10 +36,9 @@ public abstract class FingerprintHelper {
private
CancellationSignal
cancel
;
public
static
boolean
useFingerPrint
()
{
MagiskManager
mm
=
Data
.
MM
();
boolean
fp
=
mm
.
mDB
.
getSettings
(
Const
.
Key
.
SU_FINGERPRINT
,
0
)
!=
0
;
boolean
fp
=
App
.
self
.
mDB
.
getSettings
(
Const
.
Key
.
SU_FINGERPRINT
,
0
)
!=
0
;
if
(
fp
&&
!
canUseFingerprint
())
{
mm
.
mDB
.
setSettings
(
Const
.
Key
.
SU_FINGERPRINT
,
0
);
App
.
self
.
mDB
.
setSettings
(
Const
.
Key
.
SU_FINGERPRINT
,
0
);
fp
=
false
;
}
return
fp
;
...
...
@@ -48,9 +47,8 @@ public abstract class FingerprintHelper {
public
static
boolean
canUseFingerprint
()
{
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
M
)
return
false
;
MagiskManager
mm
=
Data
.
MM
();
KeyguardManager
km
=
mm
.
getSystemService
(
KeyguardManager
.
class
);
FingerprintManager
fm
=
mm
.
getSystemService
(
FingerprintManager
.
class
);
KeyguardManager
km
=
App
.
self
.
getSystemService
(
KeyguardManager
.
class
);
FingerprintManager
fm
=
App
.
self
.
getSystemService
(
FingerprintManager
.
class
);
return
km
.
isKeyguardSecure
()
&&
fm
!=
null
&&
fm
.
isHardwareDetected
()
&&
fm
.
hasEnrolledFingerprints
();
}
...
...
@@ -106,7 +104,7 @@ public abstract class FingerprintHelper {
protected
FingerprintHelper
()
throws
Exception
{
KeyStore
keyStore
=
KeyStore
.
getInstance
(
"AndroidKeyStore"
);
manager
=
Data
.
MM
()
.
getSystemService
(
FingerprintManager
.
class
);
manager
=
App
.
self
.
getSystemService
(
FingerprintManager
.
class
);
cipher
=
Cipher
.
getInstance
(
KeyProperties
.
KEY_ALGORITHM_AES
+
"/"
+
KeyProperties
.
BLOCK_MODE_CBC
+
"/"
+
KeyProperties
.
ENCRYPTION_PADDING_PKCS7
);
...
...
app/src/full/java/com/topjohnwu/magisk/
async
s/PatchAPK.java
→
app/src/full/java/com/topjohnwu/magisk/
util
s/PatchAPK.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
async
s
;
package
com
.
topjohnwu
.
magisk
.
util
s
;
import
android.os.AsyncTask
;
import
android.widget.Toast
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.utils.RootUtils
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.components.Notifications
;
import
com.topjohnwu.magisk.utils.RootUtils
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.ShellUtils
;
import
com.topjohnwu.utils.JarMap
;
import
com.topjohnwu.utils.SignAPK
;
...
...
@@ -95,14 +95,14 @@ public class PatchAPK {
}
private
static
boolean
patchAndHide
()
{
MagiskManager
mm
=
Data
.
MM
()
;
App
app
=
App
.
self
;
// Generate a new app with random package name
File
repack
=
new
File
(
mm
.
getFilesDir
(),
"patched.apk"
);
File
repack
=
new
File
(
app
.
getFilesDir
(),
"patched.apk"
);
String
pkg
=
genPackageName
(
"com."
,
BuildConfig
.
APPLICATION_ID
.
length
());
try
{
JarMap
apk
=
new
JarMap
(
mm
.
getPackageCodePath
());
JarMap
apk
=
new
JarMap
(
app
.
getPackageCodePath
());
if
(!
patch
(
apk
,
pkg
))
return
false
;
SignAPK
.
sign
(
apk
,
new
BufferedOutputStream
(
new
FileOutputStream
(
repack
)));
...
...
@@ -115,7 +115,7 @@ public class PatchAPK {
if
(!
ShellUtils
.
fastCmdResult
(
"pm install "
+
repack
))
return
false
;;
mm
.
mDB
.
setStrings
(
Const
.
Key
.
SU_MANAGER
,
pkg
);
app
.
mDB
.
setStrings
(
Const
.
Key
.
SU_MANAGER
,
pkg
);
Data
.
exportPrefs
();
RootUtils
.
rmAndLaunch
(
BuildConfig
.
APPLICATION_ID
,
pkg
);
...
...
@@ -143,10 +143,10 @@ public class PatchAPK {
public
static
void
hideManager
()
{
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
MagiskManager
mm
=
Data
.
MM
()
;
App
app
=
App
.
self
;
NotificationCompat
.
Builder
progress
=
Notifications
.
progress
(
mm
.
getString
(
R
.
string
.
hide_manager_title
));
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
mm
);
Notifications
.
progress
(
app
.
getString
(
R
.
string
.
hide_manager_title
));
NotificationManagerCompat
mgr
=
NotificationManagerCompat
.
from
(
app
);
mgr
.
notify
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
,
progress
.
build
());
boolean
b
=
patchAndHide
();
mgr
.
cancel
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
);
...
...
app/src/full/java/com/topjohnwu/magisk/utils/SuConnector.java
View file @
ff3d66a6
...
...
@@ -9,12 +9,13 @@ import android.os.Process;
import
android.text.TextUtils
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.container.Policy
;
import
com.topjohnwu.core.container.SuLogEntry
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.container.Policy
;
import
com.topjohnwu.magisk.container.SuLogEntry
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
...
...
@@ -76,8 +77,8 @@ public abstract class SuConnector {
if
(
fromUid
<
0
)
return
;
if
(
fromUid
==
Process
.
myUid
())
return
;
MagiskManager
mm
=
Data
.
MM
()
;
PackageManager
pm
=
mm
.
getPackageManager
();
App
app
=
App
.
self
;
PackageManager
pm
=
app
.
getPackageManager
();
Policy
policy
;
boolean
notify
;
...
...
@@ -91,7 +92,7 @@ public abstract class SuConnector {
}
}
else
{
// Doesn't report whether notify or not, check database ourselves
policy
=
mm
.
mDB
.
getPolicy
(
fromUid
);
policy
=
app
.
mDB
.
getPolicy
(
fromUid
);
if
(
policy
==
null
)
return
;
notify
=
policy
.
notification
;
...
...
@@ -116,24 +117,22 @@ public abstract class SuConnector {
log
.
fromPid
=
pid
;
log
.
command
=
command
;
log
.
date
=
new
Date
();
mm
.
mDB
.
addLog
(
log
);
app
.
mDB
.
addLog
(
log
);
}
private
static
void
handleNotify
(
Policy
policy
)
{
MagiskManager
mm
=
Data
.
MM
();
String
message
=
mm
.
getString
(
policy
.
policy
==
Policy
.
ALLOW
?
String
message
=
App
.
self
.
getString
(
policy
.
policy
==
Policy
.
ALLOW
?
R
.
string
.
su_allow_toast
:
R
.
string
.
su_deny_toast
,
policy
.
appName
);
if
(
policy
.
notification
&&
Data
.
suNotificationType
==
Const
.
Value
.
NOTIFICATION_TOAST
)
Utils
.
toast
(
message
,
Toast
.
LENGTH_SHORT
);
}
public
static
void
handleNotify
(
Intent
intent
)
{
MagiskManager
mm
=
Data
.
MM
();
int
fromUid
=
intent
.
getIntExtra
(
"from.uid"
,
-
1
);
if
(
fromUid
<
0
)
return
;
if
(
fromUid
==
Process
.
myUid
())
return
;
try
{
Policy
policy
=
new
Policy
(
fromUid
,
mm
.
getPackageManager
());
Policy
policy
=
new
Policy
(
fromUid
,
App
.
self
.
getPackageManager
());
policy
.
policy
=
intent
.
getIntExtra
(
"policy"
,
-
1
);
if
(
policy
.
policy
>=
0
)
handleNotify
(
policy
);
...
...
app/src/main/java/com/topjohnwu/magisk/utils/Download.java
View file @
ff3d66a6
...
...
@@ -6,12 +6,6 @@ import android.net.NetworkInfo;
public
class
Download
{
public
static
String
getLegalFilename
(
CharSequence
filename
)
{
return
filename
.
toString
().
replace
(
" "
,
"_"
).
replace
(
"'"
,
""
).
replace
(
"\""
,
""
)
.
replace
(
"$"
,
""
).
replace
(
"`"
,
""
).
replace
(
"*"
,
""
).
replace
(
"/"
,
"_"
)
.
replace
(
"#"
,
""
).
replace
(
"@"
,
""
).
replace
(
"\\"
,
"_"
);
}
public
static
boolean
checkNetworkStatus
(
Context
context
)
{
ConnectivityManager
manager
=
(
ConnectivityManager
)
context
.
getSystemService
(
Context
.
CONNECTIVITY_SERVICE
);
...
...
build.py
View file @
ff3d66a6
...
...
@@ -242,7 +242,7 @@ def build_apk(args, flavor):
def
build_app
(
args
):
source
=
os
.
path
.
join
(
'scripts'
,
'util_functions.sh'
)
target
=
os
.
path
.
join
(
'
app'
,
'src'
,
'full
'
,
'res'
,
'raw'
,
'util_functions.sh'
)
target
=
os
.
path
.
join
(
'
core'
,
'src'
,
'main
'
,
'res'
,
'raw'
,
'util_functions.sh'
)
cp
(
source
,
target
)
build_apk
(
args
,
'Full'
)
...
...
core/.gitignore
0 → 100644
View file @
ff3d66a6
/build
src/main/res/raw/util_functions.sh
core/build.gradle
0 → 100644
View file @
ff3d66a6
apply
plugin:
'com.android.library'
android
{
compileSdkVersion
rootProject
.
ext
.
compileSdkVersion
buildToolsVersion
rootProject
.
ext
.
buildToolsVersion
defaultConfig
{
minSdkVersion
16
targetSdkVersion
rootProject
.
ext
.
compileSdkVersion
versionCode
1
versionName
"1.0"
}
compileOptions
{
sourceCompatibility
JavaVersion
.
VERSION_1_8
targetCompatibility
JavaVersion
.
VERSION_1_8
}
buildTypes
{
release
{
minifyEnabled
false
proguardFiles
getDefaultProguardFile
(
'proguard-android.txt'
),
'proguard-rules.pro'
}
}
}
dependencies
{
implementation
fileTree
(
dir:
'libs'
,
include:
[
'*.jar'
])
implementation
project
(
':net'
)
implementation
project
(
':utils'
)
implementation
'com.github.topjohnwu:libsu:2.1.2'
implementation
'org.kamranzafar:jtar:2.3'
}
core/proguard-rules.pro
0 → 100644
View file @
ff3d66a6
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
core/src/main/AndroidManifest.xml
0 → 100644
View file @
ff3d66a6
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"com.topjohnwu.core"
/>
app/src/full/java/com/topjohnwu/magisk/MagiskManager
.java
→
core/src/main/java/com/topjohnwu/core/App
.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
;
package
com
.
topjohnwu
.
core
;
import
android.content.SharedPreferences
;
import
android.content.res.Configuration
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.preference.PreferenceManager
;
import
com.topjohnwu.
magisk
.database.MagiskDB
;
import
com.topjohnwu.
magisk
.database.RepoDatabaseHelper
;
import
com.topjohnwu.
magisk
.utils.LocaleManager
;
import
com.topjohnwu.
magisk
.utils.RootUtils
;
import
com.topjohnwu.
core
.database.MagiskDB
;
import
com.topjohnwu.
core
.database.RepoDatabaseHelper
;
import
com.topjohnwu.
core
.utils.LocaleManager
;
import
com.topjohnwu.
core
.utils.RootUtils
;
import
com.topjohnwu.superuser.ContainerApp
;
import
com.topjohnwu.superuser.Shell
;
import
java.lang.ref.WeakReference
;
public
class
App
extends
ContainerApp
{
public
class
MagiskManager
extends
ContainerApp
{
// Info
public
boolean
hasInit
=
false
;
public
static
App
self
;
public
static
Handler
mainHandler
=
new
Handler
(
Looper
.
getMainLooper
());
public
boolean
init
=
false
;
// Global resources
public
SharedPreferences
prefs
;
public
RepoDatabaseHelper
repoDB
;
public
MagiskDB
mDB
;
public
RepoDatabaseHelper
repoDB
;
public
MagiskManager
()
{
Data
.
weakApp
=
new
WeakReference
<>(
this
)
;
public
App
()
{
self
=
this
;
}
@Override
...
...
@@ -37,8 +38,8 @@ public class MagiskManager extends ContainerApp {
Shell
.
Config
.
setTimeout
(
2
);
prefs
=
PreferenceManager
.
getDefaultSharedPreferences
(
this
);
repoDB
=
new
RepoDatabaseHelper
(
this
);
mDB
=
new
MagiskDB
(
this
);
repoDB
=
new
RepoDatabaseHelper
(
this
);
LocaleManager
.
setLocale
(
this
);
Data
.
loadConfig
();
...
...
app/src/full/java/com/topjohnwu/magisk
/Const.java
→
core/src/main/java/com/topjohnwu/core
/Const.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
;
package
com
.
topjohnwu
.
core
;
import
android.os.Environment
;
import
android.os.Process
;
...
...
@@ -39,7 +39,7 @@ public class Const {
/* A list of apps that should not be shown as hide-able */
public
static
final
List
<
String
>
HIDE_BLACKLIST
=
Arrays
.
asList
(
Data
.
MM
()
.
getPackageName
(),
App
.
self
.
getPackageName
(),
"com.google.android.gms"
);
...
...
app/src/full/java/com/topjohnwu/magisk
/Data.java
→
core/src/main/java/com/topjohnwu/core
/Data.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
;
package
com
.
topjohnwu
.
core
;
import
android.content.SharedPreferences
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.util.Xml
;
import
com.topjohnwu.magisk.components.AboutCardRow
;
import
com.topjohnwu.magisk.receivers.GeneralReceiver
;
import
com.topjohnwu.magisk.receivers.ShortcutReceiver
;
import
com.topjohnwu.magisk.services.OnBootService
;
import
com.topjohnwu.magisk.services.UpdateCheckService
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
import
com.topjohnwu.superuser.io.SuFile
;
...
...
@@ -21,15 +14,8 @@ import org.xmlpull.v1.XmlPullParserException;
import
java.io.File
;
import
java.io.IOException
;
import
java.lang.ref.WeakReference
;
import
java.util.HashMap
;
import
java.util.Map
;
public
class
Data
{
// Global app instance
public
static
WeakReference
<
MagiskManager
>
weakApp
;
public
static
Handler
mainHandler
=
new
Handler
(
Looper
.
getMainLooper
());
public
static
Map
<
Class
,
Class
>
classMap
=
new
HashMap
<>();
// Current status
public
static
String
magiskVersionString
;
...
...
@@ -55,29 +41,12 @@ public class Data {
// Configs
public
static
boolean
isDarkTheme
;
public
static
int
suRequestTimeout
;
public
static
int
suLogTimeout
=
14
;
public
static
int
multiuserState
=
-
1
;
public
static
int
suResponseType
;
public
static
int
suNotificationType
;
public
static
int
updateChannel
;
public
static
int
repoOrder
;
static
{
classMap
.
put
(
MagiskManager
.
class
,
a
.
q
.
class
);
classMap
.
put
(
MainActivity
.
class
,
a
.
b
.
class
);
classMap
.
put
(
SplashActivity
.
class
,
a
.
c
.
class
);
classMap
.
put
(
AboutActivity
.
class
,
a
.
d
.
class
);
classMap
.
put
(
DonationActivity
.
class
,
a
.
e
.
class
);
classMap
.
put
(
FlashActivity
.
class
,
a
.
f
.
class
);
classMap
.
put
(
NoUIActivity
.
class
,
a
.
g
.
class
);
classMap
.
put
(
GeneralReceiver
.
class
,
a
.
h
.
class
);
classMap
.
put
(
ShortcutReceiver
.
class
,
a
.
i
.
class
);
classMap
.
put
(
OnBootService
.
class
,
a
.
j
.
class
);
classMap
.
put
(
UpdateCheckService
.
class
,
a
.
k
.
class
);
classMap
.
put
(
AboutCardRow
.
class
,
a
.
l
.
class
);
classMap
.
put
(
SuRequestActivity
.
class
,
a
.
m
.
class
);
}
public
static
int
suLogTimeout
=
14
;
public
static
void
loadMagiskInfo
()
{
try
{
...
...
@@ -87,24 +56,19 @@ public class Data {
}
catch
(
NumberFormatException
ignored
)
{}
}
public
static
MagiskManager
MM
()
{
return
weakApp
.
get
();
}
public
static
void
exportPrefs
()
{
// Flush prefs to disk
MagiskManager
mm
=
MM
()
;
mm
.
prefs
.
edit
().
commit
();
File
xml
=
new
File
(
mm
.
getFilesDir
().
getParent
()
+
"/shared_prefs"
,
mm
.
getPackageName
()
+
"_preferences.xml"
);
App
app
=
App
.
self
;
app
.
prefs
.
edit
().
commit
();
File
xml
=
new
File
(
app
.
getFilesDir
().
getParent
()
+
"/shared_prefs"
,
app
.
getPackageName
()
+
"_preferences.xml"
);
Shell
.
su
(
Utils
.
fmt
(
"cat %s > /data/user/0/%s"
,
xml
,
Const
.
MANAGER_CONFIGS
)).
exec
();
}
public
static
void
importPrefs
()
{
MagiskManager
mm
=
MM
();
SuFile
config
=
new
SuFile
(
"/data/user/0/"
+
Const
.
MANAGER_CONFIGS
);
if
(
config
.
exists
())
{
SharedPreferences
.
Editor
editor
=
mm
.
prefs
.
edit
();
SharedPreferences
.
Editor
editor
=
App
.
self
.
prefs
.
edit
();
try
{
SuFileInputStream
is
=
new
SuFileInputStream
(
config
);
XmlPullParser
parser
=
Xml
.
newPullParser
();
...
...
@@ -162,20 +126,20 @@ public class Data {
}
public
static
void
loadConfig
()
{
MagiskManager
mm
=
MM
()
;
App
app
=
App
.
self
;
// su
suRequestTimeout
=
Utils
.
getPrefsInt
(
mm
.
prefs
,
Const
.
Key
.
SU_REQUEST_TIMEOUT
,
Const
.
Value
.
timeoutList
[
2
]);
suResponseType
=
Utils
.
getPrefsInt
(
mm
.
prefs
,
Const
.
Key
.
SU_AUTO_RESPONSE
,
Const
.
Value
.
SU_PROMPT
);
suNotificationType
=
Utils
.
getPrefsInt
(
mm
.
prefs
,
Const
.
Key
.
SU_NOTIFICATION
,
Const
.
Value
.
NOTIFICATION_TOAST
);
suRequestTimeout
=
Utils
.
getPrefsInt
(
app
.
prefs
,
Const
.
Key
.
SU_REQUEST_TIMEOUT
,
Const
.
Value
.
timeoutList
[
2
]);
suResponseType
=
Utils
.
getPrefsInt
(
app
.
prefs
,
Const
.
Key
.
SU_AUTO_RESPONSE
,
Const
.
Value
.
SU_PROMPT
);
suNotificationType
=
Utils
.
getPrefsInt
(
app
.
prefs
,
Const
.
Key
.
SU_NOTIFICATION
,
Const
.
Value
.
NOTIFICATION_TOAST
);
// config
isDarkTheme
=
mm
.
prefs
.
getBoolean
(
Const
.
Key
.
DARK_THEME
,
false
);
updateChannel
=
Utils
.
getPrefsInt
(
mm
.
prefs
,
Const
.
Key
.
UPDATE_CHANNEL
,
Const
.
Value
.
STABLE_CHANNEL
);
repoOrder
=
mm
.
prefs
.
getInt
(
Const
.
Key
.
REPO_ORDER
,
Const
.
Value
.
ORDER_DATE
);
isDarkTheme
=
app
.
prefs
.
getBoolean
(
Const
.
Key
.
DARK_THEME
,
false
);
updateChannel
=
Utils
.
getPrefsInt
(
app
.
prefs
,
Const
.
Key
.
UPDATE_CHANNEL
,
Const
.
Value
.
STABLE_CHANNEL
);
repoOrder
=
app
.
prefs
.
getInt
(
Const
.
Key
.
REPO_ORDER
,
Const
.
Value
.
ORDER_DATE
);
}
public
static
void
writeConfig
()
{
MM
()
.
prefs
.
edit
()
App
.
self
.
prefs
.
edit
()
.
putBoolean
(
Const
.
Key
.
DARK_THEME
,
isDarkTheme
)
.
putBoolean
(
Const
.
Key
.
MAGISKHIDE
,
magiskHide
)
.
putBoolean
(
Const
.
Key
.
COREONLY
,
Const
.
MAGISK_DISABLE_FILE
.
exists
())
...
...
app/src/full/java/com/topjohnwu/magisk
/container/BaseModule.java
→
core/src/main/java/com/topjohnwu/core
/container/BaseModule.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
container
;
package
com
.
topjohnwu
.
core
.
container
;
import
android.content.ContentValues
;
import
android.database.Cursor
;
...
...
app/src/full/java/com/topjohnwu/magisk
/container/Module.java
→
core/src/main/java/com/topjohnwu/core
/container/Module.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
container
;
package
com
.
topjohnwu
.
core
.
container
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.io.SuFile
;
...
...
app/src/full/java/com/topjohnwu/magisk
/container/Policy.java
→
core/src/main/java/com/topjohnwu/core
/container/Policy.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
container
;
package
com
.
topjohnwu
.
core
.
container
;
import
android.content.ContentValues
;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.PackageManager
;
import
com.topjohnwu.
magisk
.utils.Utils
;
import
com.topjohnwu.
core
.utils.Utils
;
import
androidx.annotation.NonNull
;
...
...
app/src/full/java/com/topjohnwu/magisk
/container/Repo.java
→
core/src/main/java/com/topjohnwu/core
/container/Repo.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
container
;
package
com
.
topjohnwu
.
core
.
container
;
import
android.content.ContentValues
;
import
android.database.Cursor
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.utils.Download
;
import
com.topjohnwu.magisk.utils.Logger
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.utils.Logger
;
import
com.topjohnwu.core.utils.Utils
;
import
java.text.DateFormat
;
import
java.util.Date
;
...
...
@@ -73,7 +72,7 @@ public class Repo extends BaseModule {
}
public
String
getDownloadFilename
()
{
return
Download
.
getLegalFilename
(
getName
()
+
"-"
+
getVersion
()
+
".zip"
);
return
Utils
.
getLegalFilename
(
getName
()
+
"-"
+
getVersion
()
+
".zip"
);
}
public
class
IllegalRepoException
extends
Exception
{
...
...
app/src/full/java/com/topjohnwu/magisk
/container/SuLogEntry.java
→
core/src/main/java/com/topjohnwu/core
/container/SuLogEntry.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
container
;
package
com
.
topjohnwu
.
core
.
container
;
import
android.content.ContentValues
;
import
com.topjohnwu.
magisk
.utils.LocaleManager
;
import
com.topjohnwu.
core
.utils.LocaleManager
;
import
java.text.DateFormat
;
import
java.text.SimpleDateFormat
;
...
...
app/src/full/java/com/topjohnwu/magisk
/container/TarEntry.java
→
core/src/main/java/com/topjohnwu/core
/container/TarEntry.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
container
;
package
com
.
topjohnwu
.
core
.
container
;
import
org.kamranzafar.jtar.TarHeader
;
...
...
app/src/full/java/com/topjohnwu/magisk
/container/ValueSortedMap.java
→
core/src/main/java/com/topjohnwu/core
/container/ValueSortedMap.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
container
;
package
com
.
topjohnwu
.
core
.
container
;
import
java.util.ArrayList
;
import
java.util.Collection
;
...
...
app/src/full/java/com/topjohnwu/magisk
/database/MagiskDB.java
→
core/src/main/java/com/topjohnwu/core
/database/MagiskDB.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
database
;
package
com
.
topjohnwu
.
core
.
database
;
import
android.content.ContentValues
;
import
android.content.Context
;
import
android.content.pm.PackageManager
;
import
android.text.TextUtils
;
import
com.topjohnwu.
magisk
.Const
;
import
com.topjohnwu.
magisk
.Data
;
import
com.topjohnwu.
magisk
.container.Policy
;
import
com.topjohnwu.
magisk
.container.SuLogEntry
;
import
com.topjohnwu.
magisk
.utils.LocaleManager
;
import
com.topjohnwu.
magisk
.utils.Utils
;
import
com.topjohnwu.
core
.Const
;
import
com.topjohnwu.
core
.Data
;
import
com.topjohnwu.
core
.container.Policy
;
import
com.topjohnwu.
core
.container.SuLogEntry
;
import
com.topjohnwu.
core
.utils.LocaleManager
;
import
com.topjohnwu.
core
.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
java.text.DateFormat
;
...
...
@@ -23,7 +23,7 @@ import java.util.Map;
public
class
MagiskDB
{
private
static
final
String
POLICY_TABLE
=
"policies"
;
private
static
final
String
LOG_TABLE
=
"
logs
"
;
private
static
final
String
LOG_TABLE
=
"
err
"
;
private
static
final
String
SETTINGS_TABLE
=
"settings"
;
private
static
final
String
STRINGS_TABLE
=
"strings"
;
...
...
app/src/full/java/com/topjohnwu/magisk
/database/RepoDatabaseHelper.java
→
core/src/main/java/com/topjohnwu/core
/database/RepoDatabaseHelper.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
database
;
package
com
.
topjohnwu
.
core
.
database
;
import
android.content.Context
;
import
android.database.Cursor
;
import
android.database.sqlite.SQLiteDatabase
;
import
android.database.sqlite.SQLiteOpenHelper
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.adapters.ReposAdapter
;
import
com.topjohnwu.magisk.container.Repo
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.container.Repo
;
import
java.util.HashSet
;
import
java.util.Set
;
...
...
@@ -20,12 +19,10 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
private
static
final
String
TABLE_NAME
=
"repos"
;
private
SQLiteDatabase
mDb
;
private
MagiskManager
mm
;
private
ReposAdapter
adapter
;
private
Runnable
adapterCb
;
public
RepoDatabaseHelper
(
Context
context
)
{
super
(
context
,
"repo.db"
,
null
,
DATABASE_VER
);
mm
=
Data
.
MM
();
mDb
=
getWritableDatabase
();
// Remove outdated repos
...
...
@@ -46,7 +43,7 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
"CREATE TABLE IF NOT EXISTS "
+
TABLE_NAME
+
" "
+
"(id TEXT, name TEXT, version TEXT, versionCode INT, minMagisk INT, "
+
"author TEXT, description TEXT, last_update INT, PRIMARY KEY(id))"
);
mm
.
prefs
.
edit
().
remove
(
Const
.
Key
.
ETAG_KEY
).
apply
();
App
.
self
.
prefs
.
edit
().
remove
(
Const
.
Key
.
ETAG_KEY
).
apply
();
}
}
...
...
@@ -120,17 +117,17 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
return
set
;
}
public
void
registerAdapter
(
ReposAdapter
a
)
{
adapter
=
a
;
public
void
registerAdapter
Callback
(
Runnable
cb
)
{
adapter
Cb
=
cb
;
}
public
void
unregisterAdapter
()
{
adapter
=
null
;
public
void
unregisterAdapter
Callback
()
{
adapter
Cb
=
null
;
}
private
void
notifyAdapter
()
{
if
(
adapter
!=
null
)
{
Data
.
mainHandler
.
post
(
adapter:
:
notifyDBChanged
);
if
(
adapter
Cb
!=
null
)
{
App
.
mainHandler
.
post
(
adapterCb
);
}
}
}
app/src/full/java/com/topjohnwu/magisk/async
s/CheckUpdates.java
→
core/src/main/java/com/topjohnwu/core/task
s/CheckUpdates.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
async
s
;
package
com
.
topjohnwu
.
core
.
task
s
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.components.Notifications
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.net.ResponseListener
;
...
...
@@ -51,7 +50,7 @@ public class CheckUpdates {
url
=
Const
.
Url
.
BETA_URL
;
break
;
case
Const
.
Value
.
CUSTOM_CHANNEL
:
url
=
Data
.
MM
()
.
prefs
.
getString
(
Const
.
Key
.
CUSTOM_CHANNEL
,
""
);
url
=
App
.
self
.
prefs
.
getString
(
Const
.
Key
.
CUSTOM_CHANNEL
,
""
);
break
;
default
:
return
;
...
...
@@ -89,15 +88,10 @@ public class CheckUpdates {
JSONObject
uninstaller
=
getJson
(
json
,
"uninstaller"
);
Data
.
uninstallerLink
=
getString
(
uninstaller
,
"link"
,
null
);
if
(
cb
!=
null
)
{
if
(
BuildConfig
.
VERSION_CODE
<
Data
.
remoteManagerVersionCode
)
{
Notifications
.
managerUpdate
();
}
else
if
(
Data
.
magiskVersionCode
<
Data
.
remoteMagiskVersionCode
)
{
Notifications
.
magiskUpdate
();
}
cb
.
run
();
}
Topic
.
publish
(
Topic
.
UPDATE_CHECK_DONE
);
if
(
cb
!=
null
)
cb
.
run
();
}
}
}
core/src/main/java/com/topjohnwu/core/tasks/FlashZip.java
0 → 100644
View file @
ff3d66a6
package
com
.
topjohnwu
.
core
.
tasks
;
import
android.net.Uri
;
import
android.os.AsyncTask
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.core.utils.ZipUtils
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.util.List
;
public
abstract
class
FlashZip
{
private
Uri
mUri
;
private
File
tmpFile
;
private
List
<
String
>
console
,
logs
;
public
FlashZip
(
Uri
uri
,
List
<
String
>
out
,
List
<
String
>
err
)
{
mUri
=
uri
;
console
=
out
;
logs
=
err
;
tmpFile
=
new
File
(
App
.
self
.
getCacheDir
(),
"install.zip"
);
}
private
boolean
unzipAndCheck
()
throws
IOException
{
ZipUtils
.
unzip
(
tmpFile
,
tmpFile
.
getParentFile
(),
"META-INF/com/google/android"
,
true
);
return
ShellUtils
.
fastCmdResult
(
"grep -q '#MAGISK' "
+
new
File
(
tmpFile
.
getParentFile
(),
"updater-script"
));
}
private
boolean
flash
()
throws
IOException
{
console
.
add
(
"- Copying zip to temp directory"
);
try
(
InputStream
in
=
App
.
self
.
getContentResolver
().
openInputStream
(
mUri
);
OutputStream
out
=
new
BufferedOutputStream
(
new
FileOutputStream
(
tmpFile
)))
{
if
(
in
==
null
)
throw
new
FileNotFoundException
();
InputStream
buf
=
new
BufferedInputStream
(
in
);
ShellUtils
.
pump
(
buf
,
out
);
}
catch
(
FileNotFoundException
e
)
{
console
.
add
(
"! Invalid Uri"
);
throw
e
;
}
catch
(
IOException
e
)
{
console
.
add
(
"! Cannot copy to cache"
);
throw
e
;
}
try
{
if
(!
unzipAndCheck
())
{
console
.
add
(
"! This zip is not a Magisk Module!"
);
return
false
;
}
}
catch
(
IOException
e
)
{
console
.
add
(
"! Unzip error"
);
throw
e
;
}
console
.
add
(
"- Installing "
+
Utils
.
getNameFromUri
(
App
.
self
,
mUri
));
return
Shell
.
su
(
"cd "
+
tmpFile
.
getParent
(),
"BOOTMODE=true sh update-binary dummy 1 "
+
tmpFile
)
.
to
(
console
,
logs
)
.
exec
().
isSuccess
();
}
public
void
exec
()
{
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
boolean
success
=
false
;
try
{
success
=
flash
();
}
catch
(
IOException
ignored
)
{}
Shell
.
su
(
"cd /"
,
"rm -rf "
+
tmpFile
.
getParent
()
+
" "
+
Const
.
TMP_FOLDER_PATH
).
submit
();
onResult
(
success
);
});
}
protected
abstract
void
onResult
(
boolean
success
);
}
app/src/full/java/com/topjohnwu/magisk/asyncs/InstallMagisk
.java
→
core/src/main/java/com/topjohnwu/core/tasks/MagiskInstaller
.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
async
s
;
package
com
.
topjohnwu
.
core
.
task
s
;
import
android.app.Activity
;
import
android.app.ProgressDialog
;
import
android.net.Uri
;
import
android.os.AsyncTask
;
import
android.os.Build
;
import
android.text.TextUtils
;
import
android.view.View
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.FlashActivity
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.container.TarEntry
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.ZipUtils
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.R
;
import
com.topjohnwu.core.container.TarEntry
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.net.DownloadProgressListener
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.superuser.Shell
;
...
...
@@ -40,50 +35,19 @@ import java.io.InputStream;
import
java.io.OutputStream
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipInputStream
;
public
class
InstallMagisk
extends
ParallelTask
<
Void
,
Void
,
Boolean
>
{
import
androidx.annotation.MainThread
;
import
androidx.annotation.WorkerThread
;
private
static
final
int
PATCH_MODE
=
0
;
public
static
final
int
DIRECT_MODE
=
1
;
private
static
final
int
FIX_ENV_MODE
=
2
;
public
static
final
int
SECOND_SLOT_MODE
=
3
;
public
abstract
class
MagiskInstaller
{
private
Uri
bootUri
;
private
List
<
String
>
console
,
logs
;
private
String
mBoot
;
private
int
mode
;
private
File
installDir
;
private
ProgressDialog
dialog
;
private
MagiskManager
mm
;
protected
String
srcBoot
;
protected
File
installDir
;
public
InstallMagisk
(
Activity
context
)
{
super
(
context
);
mm
=
Data
.
MM
();
mode
=
FIX_ENV_MODE
;
}
public
InstallMagisk
(
Activity
context
,
List
<
String
>
console
,
List
<
String
>
logs
,
int
mode
)
{
this
(
context
);
this
.
console
=
console
;
this
.
logs
=
logs
;
this
.
mode
=
mode
;
}
public
InstallMagisk
(
FlashActivity
context
,
List
<
String
>
console
,
List
<
String
>
logs
,
Uri
boot
)
{
this
(
context
,
console
,
logs
,
PATCH_MODE
);
bootUri
=
boot
;
}
@Override
protected
void
onPreExecute
()
{
if
(
mode
==
FIX_ENV_MODE
)
{
Activity
a
=
getActivity
();
dialog
=
ProgressDialog
.
show
(
a
,
a
.
getString
(
R
.
string
.
setup_title
),
a
.
getString
(
R
.
string
.
setup_msg
));
console
=
NOPList
.
getInstance
();
}
}
class
ProgressLog
implements
DownloadProgressListener
{
private
class
ProgressLog
implements
DownloadProgressListener
{
private
int
prev
=
-
1
;
private
int
location
;
...
...
@@ -102,8 +66,31 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
}
}
private
void
extractFiles
(
String
arch
)
throws
IOException
{
File
zip
=
new
File
(
mm
.
getFilesDir
(),
"magisk.zip"
);
protected
MagiskInstaller
()
{
console
=
NOPList
.
getInstance
();
logs
=
NOPList
.
getInstance
();
}
public
MagiskInstaller
(
List
<
String
>
out
,
List
<
String
>
err
)
{
console
=
out
;
logs
=
err
;
installDir
=
new
File
(
Utils
.
getDEContext
().
getFilesDir
().
getParent
(),
"install"
);
Shell
.
sh
(
"rm -rf "
+
installDir
).
exec
();
installDir
.
mkdirs
();
}
protected
boolean
extractZip
()
{
String
arch
;
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
LOLLIPOP
)
{
List
<
String
>
abis
=
Arrays
.
asList
(
Build
.
SUPPORTED_ABIS
);
arch
=
abis
.
contains
(
"x86"
)
?
"x86"
:
"arm"
;
}
else
{
arch
=
TextUtils
.
equals
(
Build
.
CPU_ABI
,
"x86"
)
?
"x86"
:
"arm"
;
}
console
.
add
(
"- Device platform: "
+
Build
.
CPU_ABI
);
File
zip
=
new
File
(
App
.
self
.
getFilesDir
(),
"magisk.zip"
);
if
(!
ShellUtils
.
checkSum
(
"MD5"
,
zip
,
Data
.
magiskMD5
))
{
console
.
add
(
"- Downloading zip"
);
...
...
@@ -114,37 +101,56 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
console
.
add
(
"- Existing zip found"
);
}
BufferedInputStream
buf
=
new
BufferedInputStream
(
new
FileInputStream
(
zip
),
(
int
)
zip
.
length
());
buf
.
mark
((
int
)
zip
.
length
()
+
1
);
console
.
add
(
"- Extracting files"
);
try
(
InputStream
in
=
buf
)
{
ZipUtils
.
unzip
(
in
,
installDir
,
arch
+
"/"
,
true
);
in
.
reset
();
ZipUtils
.
unzip
(
in
,
installDir
,
"common/"
,
true
);
in
.
reset
();
ZipUtils
.
unzip
(
in
,
installDir
,
"chromeos/"
,
false
);
in
.
reset
();
ZipUtils
.
unzip
(
in
,
installDir
,
"META-INF/com/google/android/update-binary"
,
true
);
try
{
ZipInputStream
zi
=
new
ZipInputStream
(
new
BufferedInputStream
(
new
FileInputStream
(
zip
),
(
int
)
zip
.
length
()));
ZipEntry
ze
;
while
((
ze
=
zi
.
getNextEntry
())
!=
null
)
{
if
(
ze
.
isDirectory
())
continue
;
String
name
=
null
;
String
[]
names
=
{
arch
+
"/"
,
"common/"
,
"META-INF/com/google/android/update-binary"
};
for
(
String
n
:
names
)
{
if
(
ze
.
getName
().
startsWith
(
n
))
{
name
=
ze
.
getName
().
substring
(
ze
.
getName
().
lastIndexOf
(
'/'
)
+
1
);
break
;
}
}
if
(
name
==
null
&&
ze
.
getName
().
startsWith
(
"chromeos/"
))
name
=
ze
.
getName
();
if
(
name
==
null
)
continue
;
File
dest
;
if
(
installDir
instanceof
SuFile
)
{
dest
=
new
SuFile
(
installDir
,
name
);
}
else
{
dest
=
new
File
(
installDir
,
name
);
}
dest
.
getParentFile
().
mkdirs
();
try
(
OutputStream
out
=
new
SuFileOutputStream
(
dest
))
{
ShellUtils
.
pump
(
zi
,
out
);
}
}
}
catch
(
IOException
e
)
{
console
.
add
(
"! Cannot unzip zip"
);
throw
e
;
return
fals
e
;
}
Shell
.
sh
(
Utils
.
fmt
(
"chmod -R 755 %s/*; %s/magiskinit -x magisk %s/magisk"
,
installDir
,
installDir
,
installDir
)).
exec
();
return
true
;
}
private
boolean
dumpBoot
()
{
protected
boolean
copyBoot
(
Uri
bootUri
)
{
srcBoot
=
new
File
(
installDir
,
"boot.img"
).
getPath
();
console
.
add
(
"- Copying image to cache"
);
// Copy boot image to local
try
(
InputStream
in
=
mm
.
getContentResolver
().
openInputStream
(
bootUri
);
OutputStream
out
=
new
FileOutputStream
(
mBoot
)
)
{
try
(
InputStream
in
=
App
.
self
.
getContentResolver
().
openInputStream
(
bootUri
);
OutputStream
out
=
new
FileOutputStream
(
srcBoot
))
{
if
(
in
==
null
)
throw
new
FileNotFoundException
();
InputStream
src
;
if
(
Utils
.
getNameFromUri
(
mm
,
bootUri
).
endsWith
(
".tar"
))
{
if
(
Utils
.
getNameFromUri
(
App
.
self
,
bootUri
).
endsWith
(
".tar"
))
{
// Extract boot.img from tar
TarInputStream
tar
=
new
TarInputStream
(
new
BufferedInputStream
(
in
));
org
.
kamranzafar
.
jtar
.
TarEntry
entry
;
...
...
@@ -168,24 +174,24 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
return
true
;
}
pr
ivate
File
patchBoot
()
throws
IOException
{
pr
otected
boolean
patchBoot
()
{
boolean
isSigned
;
try
(
InputStream
in
=
new
SuFileInputStream
(
m
Boot
))
{
try
(
InputStream
in
=
new
SuFileInputStream
(
src
Boot
))
{
isSigned
=
SignBoot
.
verifySignature
(
in
,
null
);
if
(
isSigned
)
{
console
.
add
(
"- Boot image is signed with AVB 1.0"
);
}
}
catch
(
IOException
e
)
{
console
.
add
(
"! Unable to check signature"
);
throw
e
;
return
fals
e
;
}
// Patch boot image
if
(!
Shell
.
sh
(
"cd "
+
installDir
,
Utils
.
fmt
(
"KEEPFORCEENCRYPT=%b KEEPVERITY=%b
sh update-binary indep boot_patch.sh %s"
,
Data
.
keepEnc
,
Data
.
keepVerity
,
m
Boot
))
if
(!
Shell
.
sh
(
Utils
.
fmt
(
"cd %s; KEEPFORCEENCRYPT=%b KEEPVERITY=%b "
+
"
sh update-binary indep boot_patch.sh %s"
,
installDir
,
Data
.
keepEnc
,
Data
.
keepVerity
,
src
Boot
))
.
to
(
console
,
logs
).
exec
().
isSuccess
())
return
null
;
return
false
;
Shell
.
Job
job
=
Shell
.
sh
(
"mv bin/busybox busybox"
,
"rm -rf magisk.apk bin boot.img update-binary"
,
...
...
@@ -196,159 +202,87 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
console
.
add
(
"- Signing boot image with test keys"
);
File
signed
=
new
File
(
installDir
,
"signed.img"
);
try
(
InputStream
in
=
new
SuFileInputStream
(
patched
);
OutputStream
out
=
new
BufferedOutputStream
(
new
FileOutputStream
(
signed
))
)
{
OutputStream
out
=
new
BufferedOutputStream
(
new
FileOutputStream
(
signed
)))
{
SignBoot
.
doSignature
(
"/boot"
,
in
,
out
,
null
,
null
);
}
catch
(
IOException
e
)
{
return
false
;
}
job
.
add
(
"mv -f "
+
signed
+
" "
+
patched
);
}
job
.
exec
();
return
patched
;
return
true
;
}
private
boolean
outputBoot
(
File
patched
)
throws
IOException
{
switch
(
mode
)
{
case
PATCH_MODE:
String
fmt
=
mm
.
prefs
.
getString
(
Const
.
Key
.
BOOT_FORMAT
,
".img"
);
File
dest
=
new
File
(
Const
.
EXTERNAL_PATH
,
"patched_boot"
+
fmt
);
dest
.
getParentFile
().
mkdirs
();
OutputStream
out
;
switch
(
fmt
)
{
case
".img.tar"
:
out
=
new
TarOutputStream
(
new
BufferedOutputStream
(
new
FileOutputStream
(
dest
)));
((
TarOutputStream
)
out
).
putNextEntry
(
new
TarEntry
(
patched
,
"boot.img"
));
break
;
default
:
case
".img"
:
out
=
new
BufferedOutputStream
(
new
FileOutputStream
(
dest
));
break
;
}
try
(
InputStream
in
=
new
SuFileInputStream
(
patched
))
{
ShellUtils
.
pump
(
in
,
out
);
out
.
close
();
}
Shell
.
sh
(
"rm -f "
+
patched
).
exec
();
console
.
add
(
""
);
console
.
add
(
"****************************"
);
console
.
add
(
" Patched image is placed in "
);
console
.
add
(
" "
+
dest
+
" "
);
console
.
add
(
"****************************"
);
break
;
case
SECOND_SLOT_MODE:
case
DIRECT_MODE:
if
(!
Shell
.
su
(
Utils
.
fmt
(
"direct_install %s %s"
,
installDir
,
mBoot
))
.
to
(
console
,
logs
).
exec
().
isSuccess
())
return
false
;
if
(!
Data
.
keepVerity
)
Shell
.
su
(
"find_dtbo_image"
,
"patch_dtbo_image"
).
to
(
console
,
logs
).
exec
();
break
;
protected
boolean
flashBoot
()
{
if
(!
Shell
.
su
(
Utils
.
fmt
(
"direct_install %s %s"
,
installDir
,
srcBoot
))
.
to
(
console
,
logs
).
exec
().
isSuccess
())
return
false
;
if
(!
Data
.
keepVerity
)
Shell
.
su
(
"find_dtbo_image"
,
"patch_dtbo_image"
).
to
(
console
,
logs
).
exec
();
return
true
;
}
protected
boolean
storeBoot
()
{
File
patched
=
new
File
(
installDir
,
"new-boot.img"
);
String
fmt
=
App
.
self
.
prefs
.
getString
(
Const
.
Key
.
BOOT_FORMAT
,
".img"
);
File
dest
=
new
File
(
Const
.
EXTERNAL_PATH
,
"patched_boot"
+
fmt
);
dest
.
getParentFile
().
mkdirs
();
OutputStream
os
;
try
{
switch
(
fmt
)
{
case
".img.tar"
:
os
=
new
TarOutputStream
(
new
BufferedOutputStream
(
new
FileOutputStream
(
dest
)));
((
TarOutputStream
)
os
).
putNextEntry
(
new
TarEntry
(
patched
,
"boot.img"
));
break
;
default
:
case
".img"
:
os
=
new
BufferedOutputStream
(
new
FileOutputStream
(
dest
));
break
;
}
try
(
InputStream
in
=
new
SuFileInputStream
(
patched
))
{
ShellUtils
.
pump
(
in
,
os
);
os
.
close
();
}
}
catch
(
IOException
e
)
{
console
.
add
(
"! Failed to store boot to "
+
dest
);
return
false
;
}
Shell
.
sh
(
"rm -f "
+
patched
).
exec
();
console
.
add
(
""
);
console
.
add
(
"****************************"
);
console
.
add
(
" Patched image is placed in "
);
console
.
add
(
" "
+
dest
+
" "
);
console
.
add
(
"****************************"
);
return
true
;
}
pr
ivate
void
postOTA
()
{
pr
otected
boolean
postOTA
()
{
SuFile
bootctl
=
new
SuFile
(
Const
.
MAGISK_PATH
+
"/.core/bootctl"
);
try
(
InputStream
in
=
mm
.
getResources
().
openRawResource
(
R
.
raw
.
bootctl
);
try
(
InputStream
in
=
App
.
self
.
getResources
().
openRawResource
(
R
.
raw
.
bootctl
);
OutputStream
out
=
new
SuFileOutputStream
(
bootctl
))
{
ShellUtils
.
pump
(
in
,
out
);
Shell
.
su
(
"post_ota "
+
bootctl
.
getParent
()).
exec
();
console
.
add
(
"***************************************"
);
console
.
add
(
" Next reboot will boot to second slot!"
);
console
.
add
(
"***************************************"
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
@Override
protected
Boolean
doInBackground
(
Void
...
voids
)
{
if
(
mode
==
FIX_ENV_MODE
)
{
installDir
=
new
File
(
"/data/adb/magisk"
);
Shell
.
su
(
"rm -rf /data/adb/magisk/*"
).
exec
();
}
else
{
installDir
=
new
File
(
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
N
?
mm
.
createDeviceProtectedStorageContext
()
:
mm
)
.
getFilesDir
().
getParent
()
,
"install"
);
Shell
.
sh
(
"rm -rf "
+
installDir
).
exec
();
installDir
.
mkdirs
();
}
switch
(
mode
)
{
case
PATCH_MODE:
mBoot
=
new
File
(
installDir
,
"boot.img"
).
getAbsolutePath
();
if
(!
dumpBoot
())
return
false
;
break
;
case
DIRECT_MODE:
console
.
add
(
"- Detecting target image"
);
mBoot
=
ShellUtils
.
fastCmd
(
"find_boot_image"
,
"echo \"$BOOTIMAGE\""
);
break
;
case
SECOND_SLOT_MODE:
String
slot
=
ShellUtils
.
fastCmd
(
"echo $SLOT"
);
String
target
=
(
TextUtils
.
equals
(
slot
,
"_a"
)
?
"_b"
:
"_a"
);
console
.
add
(
"- Target slot: "
+
target
);
console
.
add
(
"- Detecting target image"
);
mBoot
=
ShellUtils
.
fastCmd
(
"SLOT="
+
target
,
"find_boot_image"
,
"SLOT="
+
slot
,
"echo \"$BOOTIMAGE\""
);
break
;
case
FIX_ENV_MODE:
mBoot
=
""
;
break
;
}
if
(
mBoot
==
null
)
{
console
.
add
(
"! Unable to detect target image"
);
return
false
;
}
Shell
.
su
(
"post_ota "
+
bootctl
.
getParent
()).
exec
();
console
.
add
(
"***************************************"
);
console
.
add
(
" Next reboot will boot to second slot!"
);
console
.
add
(
"***************************************"
);
return
true
;
}
if
(
mode
==
DIRECT_MODE
||
mode
==
SECOND_SLOT_MODE
)
console
.
add
(
"- Target image: "
+
mBoot
);
List
<
String
>
abis
=
Arrays
.
asList
(
Build
.
SUPPORTED_ABIS
);
String
arch
=
abis
.
contains
(
"x86"
)
?
"x86"
:
"arm"
;
@WorkerThread
protected
abstract
boolean
operations
();
console
.
add
(
"- Device platform: "
+
Build
.
SUPPORTED_ABIS
[
0
]);
@MainThread
protected
abstract
void
onResult
(
boolean
success
);
try
{
extractFiles
(
arch
);
if
(
mode
==
FIX_ENV_MODE
)
{
Shell
.
su
(
"fix_env"
).
exec
();
}
else
{
File
patched
=
patchBoot
();
if
(
patched
==
null
)
return
false
;
if
(!
outputBoot
(
patched
))
return
false
;
if
(
mode
==
SECOND_SLOT_MODE
)
postOTA
();
console
.
add
(
"- All done!"
);
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
false
;
}
return
true
;
public
void
exec
()
{
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
boolean
b
=
operations
();
App
.
mainHandler
.
post
(()
->
onResult
(
b
));
});
}
@Override
protected
void
onPostExecute
(
Boolean
result
)
{
if
(
mode
==
FIX_ENV_MODE
)
{
dialog
.
dismiss
();
Utils
.
toast
(
result
?
R
.
string
.
setup_done
:
R
.
string
.
setup_fail
,
Toast
.
LENGTH_LONG
);
}
else
{
// Running in FlashActivity
FlashActivity
activity
=
(
FlashActivity
)
getActivity
();
if
(!
result
)
{
Shell
.
sh
(
"rm -rf "
+
installDir
).
submit
();
console
.
add
(
"! Installation failed"
);
activity
.
reboot
.
setVisibility
(
View
.
GONE
);
}
activity
.
buttonPanel
.
setVisibility
(
View
.
VISIBLE
);
}
}
}
app/src/full/java/com/topjohnwu/magisk/async
s/ParallelTask.java
→
core/src/main/java/com/topjohnwu/core/task
s/ParallelTask.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
async
s
;
package
com
.
topjohnwu
.
core
.
task
s
;
import
android.app.Activity
;
import
android.os.AsyncTask
;
...
...
app/src/full/java/com/topjohnwu/magisk/async
s/SafetyNet.java
→
core/src/main/java/com/topjohnwu/core/task
s/SafetyNet.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
async
s
;
package
com
.
topjohnwu
.
core
.
task
s
;
import
android.app.Activity
;
import
com.topjohnwu.
magisk.Const
;
import
com.topjohnwu.
magisk.Data
;
import
com.topjohnwu.
magisk
.utils.ISafetyNetHelper
;
import
com.topjohnwu.
magisk
.utils.Topic
;
import
com.topjohnwu.
core.App
;
import
com.topjohnwu.
core.Const
;
import
com.topjohnwu.
core
.utils.ISafetyNetHelper
;
import
com.topjohnwu.
core
.utils.Topic
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.superuser.Shell
;
...
...
@@ -16,7 +16,7 @@ import dalvik.system.DexClassLoader;
public
class
SafetyNet
{
public
static
final
File
EXT_APK
=
new
File
(
Data
.
MM
()
.
getFilesDir
().
getParent
()
+
"/snet"
,
"snet.apk"
);
new
File
(
App
.
self
.
getFilesDir
().
getParent
()
+
"/snet"
,
"snet.apk"
);
private
static
void
dyRun
(
Activity
activity
)
throws
Exception
{
DexClassLoader
loader
=
new
DexClassLoader
(
EXT_APK
.
getPath
(),
EXT_APK
.
getParent
(),
...
...
app/src/full/java/com/topjohnwu/magisk/async
s/UpdateRepos.java
→
core/src/main/java/com/topjohnwu/core/task
s/UpdateRepos.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
async
s
;
package
com
.
topjohnwu
.
core
.
task
s
;
import
android.database.Cursor
;
import
android.os.AsyncTask
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.container.Repo
;
import
com.topjohnwu.magisk.utils.Logger
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.container.Repo
;
import
com.topjohnwu.core.utils.Logger
;
import
com.topjohnwu.core.utils.Topic
;
import
com.topjohnwu.core.utils.Utils
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.net.Request
;
...
...
@@ -35,7 +34,7 @@ public class UpdateRepos {
private
static
final
int
CORE_POOL_SIZE
=
Math
.
max
(
2
,
CPU_COUNT
-
1
);
private
static
final
DateFormat
dateFormat
;
private
MagiskManager
mm
;
private
App
app
=
App
.
self
;
private
Set
<
String
>
cached
;
private
ExecutorService
threadPool
;
...
...
@@ -44,10 +43,6 @@ public class UpdateRepos {
dateFormat
.
setTimeZone
(
TimeZone
.
getTimeZone
(
"UTC"
));
}
public
UpdateRepos
()
{
mm
=
Data
.
MM
();
}
private
void
waitTasks
()
{
threadPool
.
shutdown
();
while
(
true
)
{
...
...
@@ -64,17 +59,17 @@ public class UpdateRepos {
String
id
=
rawRepo
.
getString
(
"name"
);
Date
date
=
dateFormat
.
parse
(
rawRepo
.
getString
(
"pushed_at"
));
threadPool
.
execute
(()
->
{
Repo
repo
=
mm
.
repoDB
.
getRepo
(
id
);
Repo
repo
=
app
.
repoDB
.
getRepo
(
id
);
try
{
if
(
repo
==
null
)
repo
=
new
Repo
(
id
);
else
cached
.
remove
(
id
);
repo
.
update
(
date
);
mm
.
repoDB
.
addRepo
(
repo
);
app
.
repoDB
.
addRepo
(
repo
);
}
catch
(
Repo
.
IllegalRepoException
e
)
{
Logger
.
debug
(
e
.
getMessage
());
mm
.
repoDB
.
removeRepo
(
id
);
app
.
repoDB
.
removeRepo
(
id
);
}
});
}
...
...
@@ -86,7 +81,7 @@ public class UpdateRepos {
private
boolean
loadPage
(
int
page
)
{
Request
req
=
Networking
.
get
(
Utils
.
fmt
(
Const
.
Url
.
REPO_URL
,
page
+
1
));
if
(
page
==
0
)
{
String
etag
=
mm
.
prefs
.
getString
(
Const
.
Key
.
ETAG_KEY
,
null
);
String
etag
=
app
.
prefs
.
getString
(
Const
.
Key
.
ETAG_KEY
,
null
);
if
(
etag
!=
null
)
req
.
addHeaders
(
Const
.
Key
.
IF_NONE_MATCH
,
etag
);
}
...
...
@@ -115,7 +110,7 @@ public class UpdateRepos {
String
etag
=
res
.
getConnection
().
getHeaderField
(
Const
.
Key
.
ETAG_KEY
);
if
(
etag
!=
null
)
{
etag
=
etag
.
substring
(
etag
.
indexOf
(
'\"'
),
etag
.
lastIndexOf
(
'\"'
)
+
1
);
mm
.
prefs
.
edit
().
putString
(
Const
.
Key
.
ETAG_KEY
,
etag
).
apply
();
app
.
prefs
.
edit
().
putString
(
Const
.
Key
.
ETAG_KEY
,
etag
).
apply
();
}
}
...
...
@@ -128,16 +123,16 @@ public class UpdateRepos {
}
private
void
fullReload
()
{
Cursor
c
=
mm
.
repoDB
.
getRawCursor
();
Cursor
c
=
app
.
repoDB
.
getRawCursor
();
while
(
c
.
moveToNext
())
{
Repo
repo
=
new
Repo
(
c
);
threadPool
.
execute
(()
->
{
try
{
repo
.
update
();
mm
.
repoDB
.
addRepo
(
repo
);
app
.
repoDB
.
addRepo
(
repo
);
}
catch
(
Repo
.
IllegalRepoException
e
)
{
Logger
.
debug
(
e
.
getMessage
());
mm
.
repoDB
.
removeRepo
(
repo
);
app
.
repoDB
.
removeRepo
(
repo
);
}
});
}
...
...
@@ -147,13 +142,13 @@ public class UpdateRepos {
public
void
exec
(
boolean
force
)
{
Topic
.
reset
(
Topic
.
REPO_LOAD_DONE
);
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
cached
=
Collections
.
synchronizedSet
(
mm
.
repoDB
.
getRepoIDSet
());
cached
=
Collections
.
synchronizedSet
(
app
.
repoDB
.
getRepoIDSet
());
threadPool
=
Executors
.
newFixedThreadPool
(
CORE_POOL_SIZE
);
if
(
loadPages
())
{
waitTasks
();
// The leftover cached means they are removed from online repo
mm
.
repoDB
.
removeRepo
(
cached
);
app
.
repoDB
.
removeRepo
(
cached
);
}
else
if
(
force
)
{
fullReload
();
}
...
...
app/src/full/java/com/topjohnwu/magisk
/utils/BootSigner.java
→
core/src/main/java/com/topjohnwu/core
/utils/BootSigner.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
utils
;
package
com
.
topjohnwu
.
core
.
utils
;
import
com.topjohnwu.utils.SignBoot
;
...
...
app/src/full/java/com/topjohnwu/magisk
/utils/ISafetyNetHelper.java
→
core/src/main/java/com/topjohnwu/core
/utils/ISafetyNetHelper.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
utils
;
package
com
.
topjohnwu
.
core
.
utils
;
public
interface
ISafetyNetHelper
{
...
...
app/src/full/java/com/topjohnwu/magisk
/utils/LocaleManager.java
→
core/src/main/java/com/topjohnwu/core
/utils/LocaleManager.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
utils
;
package
com
.
topjohnwu
.
core
.
utils
;
import
android.content.res.Configuration
;
import
android.content.res.Resources
;
import
android.os.AsyncTask
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
java.util.ArrayList
;
import
java.util.Collections
;
...
...
@@ -22,15 +20,15 @@ public class LocaleManager {
public
final
static
Locale
defaultLocale
=
Locale
.
getDefault
();
public
static
List
<
Locale
>
locales
;
public
static
void
setLocale
(
MagiskManager
mm
)
{
String
localeConfig
=
mm
.
prefs
.
getString
(
Const
.
Key
.
LOCALE
,
""
);
public
static
void
setLocale
(
App
app
)
{
String
localeConfig
=
app
.
prefs
.
getString
(
Const
.
Key
.
LOCALE
,
""
);
if
(
localeConfig
.
isEmpty
())
{
locale
=
defaultLocale
;
}
else
{
locale
=
Locale
.
forLanguageTag
(
localeConfig
);
}
Locale
.
setDefault
(
locale
);
Resources
res
=
mm
.
getResources
();
Resources
res
=
app
.
getResources
();
Configuration
config
=
res
.
getConfiguration
();
config
.
setLocale
(
locale
);
res
.
updateConfiguration
(
config
,
res
.
getDisplayMetrics
());
...
...
@@ -39,18 +37,16 @@ public class LocaleManager {
public
static
String
getString
(
Locale
locale
,
@StringRes
int
id
)
{
Configuration
config
=
new
Configuration
();
config
.
setLocale
(
locale
);
return
Data
.
MM
()
.
createConfigurationContext
(
config
).
getString
(
id
);
return
App
.
self
.
createConfigurationContext
(
config
).
getString
(
id
);
}
public
static
void
loadAvailableLocales
()
{
public
static
void
loadAvailableLocales
(
@StringRes
int
compareId
)
{
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
locales
=
new
ArrayList
<>();
HashSet
<
String
>
set
=
new
HashSet
<>();
Resources
res
=
Data
.
MM
()
.
getResources
();
Resources
res
=
App
.
self
.
getResources
();
Locale
locale
;
@StringRes
int
compareId
=
R
.
string
.
download_file_error
;
// Add default locale
locales
.
add
(
Locale
.
ENGLISH
);
set
.
add
(
getString
(
Locale
.
ENGLISH
,
compareId
));
...
...
app/src/full/java/com/topjohnwu/magisk
/utils/Logger.java
→
core/src/main/java/com/topjohnwu/core
/utils/Logger.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
utils
;
package
com
.
topjohnwu
.
core
.
utils
;
import
android.util.Log
;
import
com.topjohnwu.
magisk
.BuildConfig
;
import
com.topjohnwu.
magisk
.Const
;
import
com.topjohnwu.
core
.BuildConfig
;
import
com.topjohnwu.
core
.Const
;
public
class
Logger
{
...
...
app/src/full/java/com/topjohnwu/magisk
/utils/RootUtils.java
→
core/src/main/java/com/topjohnwu/core
/utils/RootUtils.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
utils
;
package
com
.
topjohnwu
.
core
.
utils
;
import
android.content.Context
;
import
com.topjohnwu.
magisk
.Const
;
import
com.topjohnwu.
magisk
.Data
;
import
com.topjohnwu.
magisk
.R
;
import
com.topjohnwu.
core
.Const
;
import
com.topjohnwu.
core
.Data
;
import
com.topjohnwu.
core
.R
;
import
com.topjohnwu.superuser.BusyBox
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
...
...
app/src/full/java/com/topjohnwu/magisk
/utils/Topic.java
→
core/src/main/java/com/topjohnwu/core
/utils/Topic.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
utils
;
package
com
.
topjohnwu
.
core
.
utils
;
import
com.topjohnwu.
magisk.Data
;
import
com.topjohnwu.
core.App
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
...
...
@@ -67,7 +67,7 @@ public class Topic {
topicList
[
topic
].
published
=
true
;
}
for
(
Subscriber
sub
:
topicList
[
topic
].
subscribers
)
{
Data
.
mainHandler
.
post
(()
->
sub
.
onPublish
(
topic
,
results
));
App
.
mainHandler
.
post
(()
->
sub
.
onPublish
(
topic
,
results
));
}
}
...
...
app/src/full/java/com/topjohnwu/magisk
/utils/Utils.java
→
core/src/main/java/com/topjohnwu/core
/utils/Utils.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
utils
;
package
com
.
topjohnwu
.
core
.
utils
;
import
android.app.job.JobInfo
;
import
android.app.job.JobScheduler
;
import
android.content.ComponentName
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.SharedPreferences
;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.PackageManager
;
...
...
@@ -13,16 +9,15 @@ import android.content.res.Resources;
import
android.database.Cursor
;
import
android.net.Uri
;
import
android.os.AsyncTask
;
import
android.os.Build
;
import
android.provider.OpenableColumns
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.magisk.container.ValueSortedMap
;
import
com.topjohnwu.magisk.services.UpdateCheckService
;
import
com.topjohnwu.core.App
;
import
com.topjohnwu.core.Const
;
import
com.topjohnwu.core.Data
;
import
com.topjohnwu.core.container.Module
;
import
com.topjohnwu.core.container.ValueSortedMap
;
import
com.topjohnwu.net.Networking
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.io.SuFile
;
...
...
@@ -32,6 +27,19 @@ import java.util.Map;
public
class
Utils
{
public
static
void
toast
(
CharSequence
msg
,
int
duration
)
{
App
.
mainHandler
.
post
(()
->
Toast
.
makeText
(
App
.
self
,
msg
,
duration
).
show
());
}
public
static
void
toast
(
int
resId
,
int
duration
)
{
App
.
mainHandler
.
post
(()
->
Toast
.
makeText
(
App
.
self
,
resId
,
duration
).
show
());
}
public
static
String
dlString
(
String
url
)
{
String
s
=
Networking
.
get
(
url
).
execForString
().
getResult
();
return
s
==
null
?
""
:
s
;
}
public
static
int
getPrefsInt
(
SharedPreferences
prefs
,
String
key
,
int
def
)
{
return
Integer
.
parseInt
(
prefs
.
getString
(
key
,
String
.
valueOf
(
def
)));
}
...
...
@@ -59,7 +67,7 @@ public class Utils {
}
public
static
int
dpInPx
(
int
dp
)
{
float
scale
=
Data
.
MM
()
.
getResources
().
getDisplayMetrics
().
density
;
float
scale
=
App
.
self
.
getResources
().
getDisplayMetrics
().
density
;
return
(
int
)
(
dp
*
scale
+
0.5
);
}
...
...
@@ -67,51 +75,23 @@ public class Utils {
return
String
.
format
(
Locale
.
US
,
fmt
,
args
);
}
public
static
String
dos2unix
(
String
s
)
{
String
newString
=
s
.
replace
(
"\r\n"
,
"\n"
);
if
(!
newString
.
endsWith
(
"\n"
))
{
return
newString
+
"\n"
;
}
else
{
return
newString
;
}
}
public
static
void
setupUpdateCheck
()
{
MagiskManager
mm
=
Data
.
MM
();
JobScheduler
scheduler
=
(
JobScheduler
)
mm
.
getSystemService
(
Context
.
JOB_SCHEDULER_SERVICE
);
if
(
mm
.
prefs
.
getBoolean
(
Const
.
Key
.
CHECK_UPDATES
,
true
))
{
if
(
scheduler
.
getAllPendingJobs
().
isEmpty
()
||
Const
.
UPDATE_SERVICE_VER
>
mm
.
prefs
.
getInt
(
Const
.
Key
.
UPDATE_SERVICE_VER
,
-
1
))
{
ComponentName
service
=
new
ComponentName
(
mm
,
Data
.
classMap
.
get
(
UpdateCheckService
.
class
));
JobInfo
info
=
new
JobInfo
.
Builder
(
Const
.
ID
.
UPDATE_SERVICE_ID
,
service
)
.
setRequiredNetworkType
(
JobInfo
.
NETWORK_TYPE_ANY
)
.
setPersisted
(
true
)
.
setPeriodic
(
8
*
60
*
60
*
1000
)
.
build
();
scheduler
.
schedule
(
info
);
public
static
String
getAppLabel
(
ApplicationInfo
info
,
PackageManager
pm
)
{
try
{
if
(
info
.
labelRes
>
0
)
{
Resources
res
=
pm
.
getResourcesForApplication
(
info
);
Configuration
config
=
new
Configuration
();
config
.
setLocale
(
LocaleManager
.
locale
);
res
.
updateConfiguration
(
config
,
res
.
getDisplayMetrics
());
return
res
.
getString
(
info
.
labelRes
);
}
}
else
{
scheduler
.
cancel
(
Const
.
UPDATE_SERVICE_VER
);
}
}
public
static
void
openLink
(
Context
context
,
Uri
link
)
{
Intent
intent
=
new
Intent
(
Intent
.
ACTION_VIEW
,
link
);
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
);
if
(
intent
.
resolveActivity
(
context
.
getPackageManager
())
!=
null
)
{
context
.
startActivity
(
intent
);
}
else
{
toast
(
R
.
string
.
open_link_failed_toast
,
Toast
.
LENGTH_SHORT
);
}
}
public
static
void
toast
(
CharSequence
msg
,
int
duration
)
{
Data
.
mainHandler
.
post
(()
->
Toast
.
makeText
(
Data
.
MM
(),
msg
,
duration
).
show
());
}
catch
(
Exception
ignored
)
{}
return
info
.
loadLabel
(
pm
).
toString
();
}
public
static
void
toast
(
int
resId
,
int
duration
)
{
Data
.
mainHandler
.
post
(()
->
Toast
.
makeText
(
Data
.
MM
(),
resId
,
duration
).
show
());
public
static
String
getLegalFilename
(
CharSequence
filename
)
{
return
filename
.
toString
().
replace
(
" "
,
"_"
).
replace
(
"'"
,
""
).
replace
(
"\""
,
""
)
.
replace
(
"$"
,
""
).
replace
(
"`"
,
""
).
replace
(
"*"
,
""
).
replace
(
"/"
,
"_"
)
.
replace
(
"#"
,
""
).
replace
(
"@"
,
""
).
replace
(
"\\"
,
"_"
);
}
public
static
void
loadModules
()
{
...
...
@@ -130,29 +110,16 @@ public class Utils {
});
}
public
static
String
getAppLabel
(
ApplicationInfo
info
,
PackageManager
pm
)
{
try
{
if
(
info
.
labelRes
>
0
)
{
Resources
res
=
pm
.
getResourcesForApplication
(
info
);
Configuration
config
=
new
Configuration
();
config
.
setLocale
(
LocaleManager
.
locale
);
res
.
updateConfiguration
(
config
,
res
.
getDisplayMetrics
());
return
res
.
getString
(
info
.
labelRes
);
}
}
catch
(
Exception
ignored
)
{}
return
info
.
loadLabel
(
pm
).
toString
();
}
public
static
boolean
showSuperUser
()
{
if
(
Data
.
multiuserState
<
0
)
Data
.
multiuserState
=
Data
.
MM
()
.
mDB
.
getSettings
(
Const
.
Key
.
SU_MULTIUSER_MODE
,
Data
.
multiuserState
=
App
.
self
.
mDB
.
getSettings
(
Const
.
Key
.
SU_MULTIUSER_MODE
,
Const
.
Value
.
MULTIUSER_MODE_OWNER_ONLY
);
return
Shell
.
rootAccess
()
&&
(
Const
.
USER_ID
==
0
||
Data
.
multiuserState
!=
Const
.
Value
.
MULTIUSER_MODE_OWNER_MANAGED
);
}
public
static
String
dlString
(
String
url
)
{
String
s
=
Networking
.
get
(
url
).
execForString
().
getResult
();
return
s
==
null
?
""
:
s
;
public
static
Context
getDEContext
(
)
{
return
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
N
?
App
.
self
.
createDeviceProtectedStorageContext
()
:
App
.
self
;
}
}
\ No newline at end of file
}
app/src/full/java/com/topjohnwu/magisk
/utils/ZipUtils.java
→
core/src/main/java/com/topjohnwu/core
/utils/ZipUtils.java
View file @
ff3d66a6
package
com
.
topjohnwu
.
magisk
.
utils
;
package
com
.
topjohnwu
.
core
.
utils
;
import
com.topjohnwu.superuser.ShellUtils
;
import
com.topjohnwu.superuser.io.SuFile
;
...
...
app/src/full
/res/raw/bootctl
→
core/src/main
/res/raw/bootctl
View file @
ff3d66a6
File moved
app/src/full
/res/raw/nonroot_utils.sh
→
core/src/main
/res/raw/nonroot_utils.sh
View file @
ff3d66a6
File moved
app/src/full
/res/raw/utils.sh
→
core/src/main
/res/raw/utils.sh
View file @
ff3d66a6
...
...
@@ -63,9 +63,9 @@ restore_imgs() {
post_ota
()
{
cd
$1
chmod
755 bootctl
./bootctl hal-info
||
return
[
`
./bootctl get-current-slot
`
-eq
0
]
&&
SLOT_NUM
=
1
||
SLOT_NUM
=
0
./bootctl set-active-boot-slot
$SLOT_NUM
.
./../../../../app/src/full/res/raw
/bootctl hal-info
||
return
[
`
.
./../../../../app/src/full/res/raw
/bootctl get-current-slot
`
-eq
0
]
&&
SLOT_NUM
=
1
||
SLOT_NUM
=
0
.
./../../../../app/src/full/res/raw
/bootctl set-active-boot-slot
$SLOT_NUM
echo
'${0%/*}/../bootctl mark-boot-successful;rm -f ${0%/*}/../bootctl $0'
>
post-fs-data.d/post_ota.sh
chmod
755 post-fs-data.d/post_ota.sh
cd
/
...
...
settings.gradle
View file @
ff3d66a6
include
':app'
,
':native'
,
':utils'
,
':snet'
,
':net'
include
':app'
,
':native'
,
':utils'
,
':snet'
,
':net'
,
':core'
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