1
mirror of https://github.com/topjohnwu/Magisk synced 2025-10-26 02:22:14 +01:00

Compare commits

...

181 Commits

Author SHA1 Message Date
topjohnwu
1adf331268 Bump version 2017-12-29 04:03:05 +08:00
topjohnwu
349b3e961b More robust sudb handling 2017-12-29 04:01:39 +08:00
topjohnwu
96650c06f0 Fix the issue that installation configs won't stick 2017-12-29 03:21:51 +08:00
dark-basic #DarkBasic BasicHD
26038a0a07 Update strings.xml 2017-12-29 01:44:36 +08:00
topjohnwu
6a148b5dd9 Add sorting repo by update time 2017-12-27 01:07:33 +08:00
topjohnwu
0e109ef979 Remove snet version checkpoint, always check by code 2017-12-26 18:24:43 +08:00
topjohnwu
de2285d5e9 Bump version 2017-12-26 03:59:28 +08:00
topjohnwu
b2483ba437 Add version check within binary 2017-12-26 03:59:28 +08:00
topjohnwu
a82a5e5a49 Update snet.apk 2017-12-26 03:57:22 +08:00
topjohnwu
d161a02e71 Fix bug in sudb init 2017-12-25 01:38:38 +08:00
Ilya Kushnir
d2b6a700b1 Update RU strings 2017-12-25 01:37:05 +08:00
Matthias Urhahn
af203cef24 Update strings.xml
Improved german translation.
2017-12-25 01:36:52 +08:00
Madis
673e917e76 et: Missing strings and improvements 2017-12-25 01:36:38 +08:00
RoySchutte
a3bd41db54 Update strings.xml 2017-12-25 01:36:20 +08:00
topjohnwu
0d9527921a Fix su time limits 2017-12-22 06:43:55 +08:00
topjohnwu
f0e4aec0af Bump version 2017-12-22 02:36:26 +08:00
topjohnwu
b0d65b5edd Improve compatibility 2017-12-22 02:36:26 +08:00
topjohnwu
75532ef591 Add recommended KEEPVERITY and KEEPFORCEENCRYPT flags 2017-12-22 02:36:20 +08:00
topjohnwu
9a6d1bd700 Add self package into blacklist 2017-12-22 02:36:20 +08:00
topjohnwu
a7ed6c15d3 More precise sudb management 2017-12-22 02:36:15 +08:00
vvb2060
5ee49ba065 Update zh-rCN translation 2017-12-22 00:40:38 +08:00
topjohnwu
d34bd47bea Read full css into memory for MarkdownWindow 2017-12-20 00:40:19 +08:00
topjohnwu
f17792380b Update Trad. Chinese translation 2017-12-19 23:07:33 +08:00
topjohnwu
c11920110e Update German Translation
Credit: @GuepardoApps
2017-12-19 23:03:09 +08:00
Oliver Cervera
ec5a993fea Update Italian strings
* 2 new strings have been added
2017-12-19 23:01:17 +08:00
linar10
d250c2cc89 Update strings.xml 2017-12-19 23:01:01 +08:00
Grammatopoulos Apostolos
767e73f40c Greek translation updates 2017-12-19 23:00:44 +08:00
Small_Ku
3f699c9d2f Fix a minor translation mistake 2017-12-19 22:59:54 +08:00
dark-basic #DarkBasic BasicHD
50dbd9befd Update Strings.xml 2017-12-19 22:59:16 +08:00
Matthias Sweertvaegher
760e01bf92 request focus for grant button to enable dpad nav
if no buttons have focus, it is impossible to use
on android tv without hooking up a mouse
2017-12-19 22:56:10 +08:00
topjohnwu
543f435b1e Massive improvement of Magisk Manager repackaging 2017-12-19 20:59:59 +08:00
topjohnwu
91337218b3 Update snet configs 2017-12-19 15:46:54 +08:00
topjohnwu
afff3c0a49 Update snet.apk 2017-12-19 15:44:39 +08:00
topjohnwu
a1871e4bc3 Fix install commands 2017-12-18 03:02:19 +08:00
topjohnwu
3aa0294cd4 Fix strings.xml 2017-12-16 23:15:01 +08:00
topjohnwu
310b266251 Fix installation on FBE devices 2017-12-16 04:31:31 +08:00
Grammatopoulos Apostolos
21b1b5098e Greek translation update and fixes 2017-12-16 03:38:41 +08:00
dark-basic #DarkBasic BasicHD
a3a4a5d8a5 Update Strings.xml
It has been compared with strings.xml in English and I have updated based on the new restructuring of the project
2017-12-16 03:38:29 +08:00
Oliver Cervera
270536f33c Update Italian strings
- Now based on new project restructure
- New strings have been added and translated
- Some strings have been revised and updated based on feedback
2017-12-16 03:37:21 +08:00
linar10
66bb433cc6 Update strings.xml 2017-12-16 03:36:58 +08:00
Fatih Fırıncı
bd4ef1a03a Update strings.xml 2017-12-16 03:36:42 +08:00
topjohnwu
aa2d9a3bf1 Support installing to new path 2017-12-16 02:01:04 +08:00
topjohnwu
fd6cbb138c Change new magisk database 2017-12-12 02:35:00 +08:00
topjohnwu
aa75c8e5e4 Fix issues of repackaging with multiuser 2017-12-08 23:38:03 +08:00
topjohnwu
c461fc6daa Adapt with new Magisk installation 2017-12-07 04:20:15 +08:00
topjohnwu
96eaa833f5 Update README.md 2017-12-04 22:59:06 +08:00
topjohnwu
863b13a694 Massive project restructure 2017-12-04 14:21:55 +08:00
Igor Sorocean
e6fea4e6dd Update romanian translation 2017-12-04 13:45:47 +08:00
vvb2060
83bfc13056 Update zh-rCN translation 2017-12-04 13:45:18 +08:00
dark-basic #DarkBasic BasicHD
bc4f09209b Update strings.xml
New Lines Added. --> Add reboot menu
Updated Translations --> Add Changelogs
New Line Added ---> Cleanup prefs
2017-12-04 13:45:05 +08:00
topjohnwu
967ca17238 Fix custom channel dialog 2017-12-03 15:43:07 +08:00
topjohnwu
595c72147c Add dark theme to superuser request 2017-12-03 15:15:00 +08:00
topjohnwu
f3c3b5a649 Cleanup prefs 2017-12-03 04:18:22 +08:00
topjohnwu
1cd2c5e653 Add changelogs 2017-12-03 04:18:22 +08:00
topjohnwu
b2873dd44b Add reboot menu 2017-12-02 22:50:59 +08:00
topjohnwu
bb80ab4026 Support migrating settings after repackage 2017-12-02 02:35:07 +08:00
topjohnwu
80cabb338b Java has native inputstream wrapper 2017-12-01 11:42:05 +08:00
topjohnwu
2c69e2c151 Update SignAPK to use less memory 2017-12-01 11:19:38 +08:00
linar10
c1dd23f5e0 Update strings.xml 2017-11-30 00:08:14 +08:00
Jonas Schubert
f93624a41c updated german translation 2017-11-30 00:08:04 +08:00
Albert I
9f4559a059 Initial Indonesian translations
This brings Indonesian language support to Magisk Manager.

Signed-off-by: Albert I <krascgq@outlook.co.id>
2017-11-30 00:07:52 +08:00
Igor Sorocean
fd05cad303 Update romanian translation 2017-11-30 00:07:37 +08:00
Madis
d58b06e493 Estonian update
New strings and better wording
2017-11-30 00:07:22 +08:00
Mevlüt TOPÇU
2f0b549027 Update strings.xml 2017-11-25 00:31:58 +08:00
Ilya Kushnir
87dbd7e541 Update RU strings 2017-11-25 00:31:50 +08:00
topjohnwu
96e5da36be Update snet.apk link 2017-11-24 22:25:42 +08:00
topjohnwu
43745edac0 Fix crashes when Google Play Service require update 2017-11-24 22:15:46 +08:00
topjohnwu
f5ceee547c Bump version 2017-11-23 23:34:46 +08:00
topjohnwu
b612bce779 Add FLAG_ACTIVITY_NEW_TASK flag for updates 2017-11-23 23:26:06 +08:00
topjohnwu
2e88e5e9c7 Fix strings 2017-11-23 23:19:31 +08:00
Primokorn
9a7aa25c90 Update FR strings.xml 2017-11-23 23:18:13 +08:00
uvera
c4420fe932 Create values-sr
Serbian translation
2017-11-23 23:18:04 +08:00
Oliver Cervera
a5260f3a95 Update Italian strings 2017-11-23 23:17:47 +08:00
topjohnwu
47ccf4b1f5 Bump version 2017-11-23 01:06:19 +08:00
topjohnwu
a356b21895 Prevent hiding Magisk Manager on old Magisk versions 2017-11-23 01:06:18 +08:00
dark-basic #DarkBasic BasicHD
614a36c888 Update strings.xml
New Lines added.
2017-11-23 00:12:23 +08:00
topjohnwu
f520fe36bd Update to use new paths 2017-11-22 14:03:15 +08:00
vvb2060
7273a1c34d Update zh-rCN translation 2017-11-21 21:49:40 +08:00
Oliver Cervera
dc45cbce37 Update Italians strings
All new strings translated + clean-up!
2017-11-21 21:49:28 +08:00
topjohnwu
708d8f75c0 Notify su db corruption 2017-11-21 02:21:37 +08:00
dark-basic #DarkBasic BasicHD
bd37d90228 Update strings.xml 2017-11-21 02:15:14 +08:00
topjohnwu
b1ad691464 Several small fixes 2017-11-21 02:15:13 +08:00
topjohnwu
f4e7baf31e Update snet.apk link 2017-11-21 00:43:13 +08:00
topjohnwu
c0e60c41f2 Update snet extension pack 2017-11-21 00:40:05 +08:00
topjohnwu
c8dad43e00 Fix boot patching 2017-11-21 00:34:25 +08:00
topjohnwu
a8f124704d Allow custom update channels 2017-11-20 03:09:08 +08:00
vvb2060
eed2816491 Update zh-rCN translation 2017-11-19 22:48:29 +08:00
linar10
a6334b3e35 Update strings.xml 2017-11-19 22:48:20 +08:00
topjohnwu
334beebfeb Not all devices work well with streaming 2017-11-19 06:17:31 +08:00
topjohnwu
13dad848bd Fix download progress bug for modules larger than 20MB 2017-11-18 14:17:26 +08:00
topjohnwu
e518f4cef8 Crash proof database: reset if error occurs 2017-11-18 05:17:06 +08:00
topjohnwu
c8fd5da2da Remove unused strings 2017-11-18 05:17:06 +08:00
topjohnwu
3a74729ecc Add saving logs feature for installation 2017-11-18 05:17:06 +08:00
topjohnwu
49c672ac4d Add STDERR support 2017-11-18 05:17:06 +08:00
topjohnwu
b570cb5b77 Extract external path 2017-11-18 05:17:06 +08:00
topjohnwu
97bf388471 Support new module specification 2017-11-18 05:17:05 +08:00
topjohnwu
1a32aaea6f Drawer rearrangement 2017-11-18 05:17:05 +08:00
topjohnwu
4635883dec Update to use adaptive icons 2017-11-18 03:56:34 +08:00
topjohnwu
3ba6db4a50 Update Trad. Chinese translation 2017-11-17 02:28:51 +08:00
Xorok
2f1de25747 Fix color of LogFragment menu items when using dark theme
I set the color directly in the ic_*.xml files instead of using android:iconTint in menu_log.xml (as seen in fragment_magisk.xml) because iconTint is API26+.
2017-11-17 02:14:13 +08:00
daveyannihilation
f60fd42ac0 Expose Flashing colours for themes 2017-11-17 02:03:35 +08:00
RoySchutte
ecc8f9c792 Update strings.xml 2017-11-17 01:45:05 +08:00
dark-basic #DarkBasic BasicHD
e295dfdcf7 Update strings.xml 2017-11-17 01:44:56 +08:00
Oliver Cervera
fc42c25390 Update IT translation for new strings
Updating Italian translation for new strings that have just been pushed.
2017-11-17 01:44:47 +08:00
topjohnwu
27d5858e06 Fix file selection for module install 2017-11-17 01:39:34 +08:00
Generator
e1ef732b60 update pt_PT translation 2017-11-15 05:44:13 +08:00
RoySchutte
9840b95c21 Update strings.xml 2017-11-15 05:44:05 +08:00
linar10
a6f8446d81 Update strings.xml 2017-11-15 05:43:56 +08:00
Oliver Cervera
c1c844c830 Update strings Italian
Urgent correction!
Many strings contain the following character
'
It needs a backslash \ typed in front, otherwise sentences are cut!
2017-11-15 05:43:46 +08:00
topjohnwu
389299afd1 Remove apps from hidelist if uninstalled 2017-11-15 05:36:57 +08:00
topjohnwu
826543a291 Fully support dtbo.img patching 2017-11-15 05:36:57 +08:00
topjohnwu
4ac83cfded Small UI improvement 2017-11-15 00:38:38 +08:00
topjohnwu
64c363ce53 Update repo download progress report 2017-11-09 02:12:55 +08:00
topjohnwu
cca4347bf9 Use handler instead of weird callbacks 2017-11-09 01:43:29 +08:00
topjohnwu
3ae3d4926a Small adjustments to UI 2017-11-09 01:11:50 +08:00
topjohnwu
36025d6d9f Use direct path 2017-11-09 00:03:37 +08:00
topjohnwu
e171362e3e Improve snet.apk downloading 2017-11-07 00:39:48 +08:00
topjohnwu
3e0bf2ae15 Bump version 2017-11-06 23:21:05 +08:00
dark-basic #DarkBasic BasicHD
07aa9f4b8b Update strings.xml
new lines added
2017-11-06 23:04:59 +08:00
Oliver Cervera
b2d9f3fc64 Update Italian IT strings 2017-11-06 23:04:46 +08:00
Taras Korzhak
5fb3e9167e Updated Ukrainian translation 2017-11-06 23:04:28 +08:00
topjohnwu
99c74b31be Improve dynamic permissions 2017-11-06 05:40:41 +08:00
topjohnwu
ce5b13824e Organize application initialization 2017-11-06 04:47:24 +08:00
topjohnwu
c39170c42e Organize constants 2017-11-06 04:41:23 +08:00
topjohnwu
fd19fbf300 Improve Magisk direct install 2017-11-04 04:01:58 +08:00
topjohnwu
166469827f Support new sha1 location 2017-11-03 05:02:14 +08:00
topjohnwu
a34ed538b6 Fix potential bug 2017-11-03 02:25:42 +08:00
topjohnwu
5f22d3e055 Support new xml binary format 2017-10-31 22:48:48 +08:00
topjohnwu
fdd700f3e5 Update boot signing in InstallMagisk 2017-10-31 16:31:58 +08:00
topjohnwu
adf930f126 Finalize bootsigner commandline 2017-10-31 02:55:50 +08:00
topjohnwu
05f41928cd Add boot signing 2017-10-30 03:45:22 +08:00
topjohnwu
2ee0829871 Fix strings.xml 2017-10-30 03:44:03 +08:00
Dmitry Val'd
743560825d Update RU translation
Added new lines from original + corrected mistakes of the previous version of translation
2017-10-29 19:05:22 +08:00
Antoine
e3d84ac349 Update french translation 2017-10-29 19:05:12 +08:00
Dino Dugandžija
266c832b30 Created Croatian translation
I've translated the Magisk Manager app strings.xml to Croatian language. If anything else is needed, please let me know.
2017-10-29 19:04:55 +08:00
topjohnwu
f5374a024e Improve dynamic loading snet package 2017-10-29 14:43:43 +08:00
topjohnwu
4956d826fb Fix UID stored in multiuser mode 2017-10-28 16:19:53 +08:00
topjohnwu
f5cc2af5d0 Repackage Magisk Manager for hiding 2017-10-28 16:19:53 +08:00
topjohnwu
5880d4a6ec Use global su database 2017-10-28 15:50:17 +08:00
topjohnwu
ae05dce958 Improve Shell and logging 2017-10-21 02:28:44 +08:00
topjohnwu
9ebe372a9a Simplify flash log screen 2017-10-21 02:28:44 +08:00
topjohnwu
e6e04cc5b3 Add reference ASAP 2017-10-16 11:51:34 +08:00
topjohnwu
12352510fd Fix strings 2017-10-16 11:47:07 +08:00
vvb2060
2b3d927937 Update zh-rCN translation 2017-10-16 11:11:27 +08:00
Madis
a8890740f5 Created Estonian translation
I translated Magisk Manager to Estonian with the help of an app called Stringlate.
2017-10-16 11:11:19 +08:00
dark-basic #DarkBasic BasicHD
f60d7ee54b Fix Strings.xml
Translation Mistakes corrected.
2017-10-16 11:11:10 +08:00
topjohnwu
896ca2ef6b Cleanup contexts 2017-10-16 00:54:48 +08:00
topjohnwu
c036f6d529 Cleanup Utils 2017-10-15 23:54:34 +08:00
topjohnwu
6f457c0c59 Refactor shell (again) 2017-10-15 23:02:44 +08:00
Dmitry Val'd
13bf1b27b4 Update strings.xml
Added new lines from original
2017-10-15 03:15:39 +08:00
topjohnwu
f742bb1c47 Hot fix for detecting MagiskHide 2017-10-15 03:12:13 +08:00
topjohnwu
aa0b9e2db2 Bump version 2017-10-14 04:18:14 +08:00
topjohnwu
c10076f7ed Remove debug logs 2017-10-14 04:05:41 +08:00
topjohnwu
bcd92499f2 Massive improvement on Online Repo fetching 2017-10-14 04:05:41 +08:00
topjohnwu
b2bb0d4f72 Fix some external storage permission issues 2017-10-14 00:36:10 +08:00
topjohnwu
e140481f14 Wrap wrapper with buffer 2017-10-13 20:47:14 +08:00
topjohnwu
186bd11463 Reconnect until we got content length 2017-10-13 03:25:56 +08:00
topjohnwu
a0490d6687 Update Trad. Chinese translation 2017-10-13 03:10:35 +08:00
killer7mod
beef740ade update strings.xml for PT-BR 2017-10-13 02:45:02 +08:00
Frieder Bluemle
2ac7786a90 Update commonmark to 0.10.0 2017-10-13 02:44:42 +08:00
Frieder Bluemle
a3fb5e910f Update bouncycastle libs to 1.58 2017-10-13 02:44:42 +08:00
Frieder Bluemle
319afe86b5 Update Gradle wrapper to 4.2.1 2017-10-13 02:44:42 +08:00
Frieder Bluemle
762ab66b86 Fix Lint errors 2017-10-13 02:44:42 +08:00
topjohnwu
0c239a42de Allow secondary users to control Superuser settings except multiuser options 2017-10-13 02:41:43 +08:00
dark-basic #DarkBasic BasicHD
e9322fba26 Update strings.xml
New Lines Added
2017-10-07 23:44:10 +08:00
RoySchutte
39b6df27b3 Update strings.xml 2017-10-07 20:55:00 +08:00
topjohnwu
b1ee284e7f Rename resource -> common 2017-10-07 20:48:45 +08:00
topjohnwu
e986332bf2 Several small snet fixes 2017-10-07 20:47:44 +08:00
topjohnwu
48f9b27381 Seperate JarSigner and add task for host 2017-10-07 20:31:49 +08:00
topjohnwu
42a6e0dd10 Seperate Google proprietary code 2017-10-07 17:12:36 +08:00
topjohnwu
d4798b02ac Move functions 2017-10-04 22:27:14 +08:00
topjohnwu
963edfe8ab Add InputStream mode for signing zips 2017-10-04 22:09:59 +08:00
topjohnwu
53237f3ae0 Update Android Studio and Proguard configs 2017-10-04 15:23:08 +08:00
topjohnwu
64da9281a4 Show progress while downloading modules 2017-10-01 02:38:25 +08:00
topjohnwu
ab7fd9799d Remove cache module exception 2017-10-01 01:38:25 +08:00
topjohnwu
f6bcc84251 Improve repo fetching 2017-10-01 01:28:50 +08:00
topjohnwu
35dc3d9df9 Update WebService 2017-10-01 01:12:45 +08:00
topjohnwu
566714a75d Use override functions 2017-09-30 03:25:50 +08:00
topjohnwu
c92f30b122 Re-organize classes 2017-09-30 03:04:23 +08:00
topjohnwu
294ad094c4 Show repo loading progress by showing repos already loaded 2017-09-30 01:15:34 +08:00
topjohnwu
c1a0f520f9 Prevent flash screen close when tapping outside 2017-09-29 13:20:34 +08:00
247 changed files with 6562 additions and 6343 deletions

2
.gitignore vendored
View File

@@ -5,7 +5,7 @@
/build
app/release
*.hprof
app/.externalNativeBuild/
.externalNativeBuild/
*.sh
public.certificate.x509.pem
private.key.pk8

View File

@@ -1,7 +1,2 @@
# Magisk Manager
This is one of the submodules used in Magisk. The project is licensed under GPL v3 (or newer).
More info are written in the [Magisk Main Repo](https://github.com/topjohnwu/Magisk)
## Building Notes
You need to install CMake and NDK to build the zipadjust library.
There are several files required to let Magisk Manager work properly, and they can be copied by using the build script in the [Magisk Main Repo](https://github.com/topjohnwu/Magisk). These files are: `magisk_uninstaller.sh`, `util_functions.sh`, `public.certificate.x509.pem`, and `private.key.pk8` under the `app/src/main/assets` folder.
This repo is no longer an independent component. It is a submodule of the [Magisk Project](https://github.com/topjohnwu/Magisk).

1
app/.gitignore vendored
View File

@@ -1 +0,0 @@
/build

View File

@@ -1,68 +0,0 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.topjohnwu.magisk"
minSdkVersion 21
targetSdkVersion 26
versionCode 55
versionName "5.3.5"
ndk {
moduleName 'zipadjust'
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
javaCompileOptions {
annotationProcessorOptions {
argument('butterknife.debuggable', 'false')
}
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dexOptions {
preDexLibraries true
javaMaxHeapSize "2g"
}
externalNativeBuild {
cmake {
path 'src/main/jni/CMakeLists.txt'
}
}
lintOptions {
disable 'MissingTranslation'
}
}
repositories {
jcenter()
maven { url "https://jitpack.io" }
maven { url "https://maven.google.com" }
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation project(':resource')
implementation 'com.android.support:recyclerview-v7:26.1.0'
implementation 'com.android.support:cardview-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'
implementation 'com.android.support:support-v4:26.1.0'
implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'com.atlassian.commonmark:commonmark:0.9.0'
implementation 'org.bouncycastle:bcprov-jdk15on:1.57'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.57'
implementation 'org.kamranzafar:jtar:2.3'
implementation 'com.google.android.gms:play-services-safetynet:9.0.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

View File

@@ -1,133 +0,0 @@
package com.topjohnwu.magisk;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.TextView;
import com.topjohnwu.magisk.components.AboutCardRow;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import java.io.IOException;
import java.io.InputStream;
import butterknife.BindView;
import butterknife.ButterKnife;
public class AboutActivity extends Activity {
private static final String DONATION_URL = "https://www.paypal.me/topjohnwu";
private static final String XDA_THREAD = "http://forum.xda-developers.com/showthread.php?t=3432382";
private static final String SOURCE_CODE_URL = "https://github.com/topjohnwu/MagiskManager";
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.app_version_info) AboutCardRow appVersionInfo;
@BindView(R.id.app_changelog) AboutCardRow appChangelog;
@BindView(R.id.app_developers) AboutCardRow appDevelopers;
@BindView(R.id.app_translators) AboutCardRow appTranslators;
@BindView(R.id.app_source_code) AboutCardRow appSourceCode;
@BindView(R.id.support_thread) AboutCardRow supportThread;
@BindView(R.id.donation) AboutCardRow donation;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getMagiskManager().isDarkTheme) {
setTheme(R.style.AppTheme_Transparent_Dark);
}
setContentView(R.layout.activity_about);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(view -> finish());
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setTitle(R.string.about);
ab.setDisplayHomeAsUpEnabled(true);
}
appVersionInfo.setSummary(BuildConfig.VERSION_NAME);
String changes = null;
try (InputStream is = getAssets().open("changelog.html")) {
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
changes = new String(buffer);
} catch (IOException ignored) {
}
appChangelog.removeSummary();
if (changes == null) {
appChangelog.setVisibility(View.GONE);
} else {
Spanned result;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
result = Html.fromHtml(changes, Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE);
} else {
result = Html.fromHtml(changes);
}
appChangelog.setOnClickListener(v -> {
AlertDialog d = new AlertDialogBuilder(this)
.setTitle(R.string.app_changelog)
.setMessage(result)
.setPositiveButton(android.R.string.ok, null)
.show();
//noinspection ConstantConditions
((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
});
}
appDevelopers.removeSummary();
appDevelopers.setOnClickListener(view -> {
Spanned result;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
result = Html.fromHtml(getString(R.string.app_developers_), Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE);
} else {
result = Html.fromHtml(getString(R.string.app_developers_));
}
AlertDialog d = new AlertDialogBuilder(this)
.setTitle(R.string.app_developers)
.setMessage(result)
.setPositiveButton(android.R.string.ok, null)
.create();
d.show();
//noinspection ConstantConditions
((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
});
String translators = getString(R.string.translators);
if (TextUtils.isEmpty(translators)) {
appTranslators.setVisibility(View.GONE);
} else {
appTranslators.setSummary(translators);
}
appSourceCode.removeSummary();
appSourceCode.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(SOURCE_CODE_URL))));
supportThread.removeSummary();
supportThread.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(XDA_THREAD))));
donation.removeSummary();
donation.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(DONATION_URL))));
setFloating();
}
}

View File

@@ -1,151 +0,0 @@
package com.topjohnwu.magisk;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.asyncs.FlashZip;
import com.topjohnwu.magisk.asyncs.InstallMagisk;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.utils.AdaptiveList;
import com.topjohnwu.magisk.utils.Shell;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class FlashActivity extends Activity {
public static final String SET_ACTION = "action";
public static final String SET_BOOT = "boot";
public static final String SET_ENC = "enc";
public static final String SET_VERITY = "verity";
public static final String FLASH_ZIP = "flash";
public static final String PATCH_BOOT = "patch";
public static final String FLASH_MAGISK = "magisk";
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.flash_logs) RecyclerView flashLogs;
@BindView(R.id.button_panel) LinearLayout buttonPanel;
@BindView(R.id.reboot) Button reboot;
@OnClick(R.id.no_thanks)
public void dismiss() {
finish();
}
@OnClick(R.id.reboot)
public void reboot() {
getShell().su_raw("reboot");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flash);
ButterKnife.bind(this);
AdaptiveList<String> rootShellOutput = new AdaptiveList<>(flashLogs);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setTitle(R.string.flashing);
}
setFloating();
if (!Shell.rootAccess())
reboot.setVisibility(View.GONE);
flashLogs.setAdapter(new FlashLogAdapter(rootShellOutput));
// We must receive a Uri of the target zip
Intent intent = getIntent();
Uri uri = intent.getData();
boolean keepEnc = intent.getBooleanExtra(SET_ENC, false);
boolean keepVerity = intent.getBooleanExtra(SET_VERITY, false);
switch (getIntent().getStringExtra(SET_ACTION)) {
case FLASH_ZIP:
new FlashZip(this, uri, rootShellOutput)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
break;
case PATCH_BOOT:
new InstallMagisk(this, rootShellOutput, uri, keepEnc, keepVerity, (Uri) intent.getParcelableExtra(SET_BOOT))
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
break;
case FLASH_MAGISK:
String boot = intent.getStringExtra(SET_BOOT);
if (getMagiskManager().remoteMagiskVersionCode < 1370) {
// Use legacy installation method
getShell().su_raw(
"echo \"BOOTIMAGE=" + boot + "\" > /dev/.magisk",
"echo \"KEEPFORCEENCRYPT=" + keepEnc + "\" >> /dev/.magisk",
"echo \"KEEPVERITY=" + keepVerity + "\" >> /dev/.magisk"
);
new FlashZip(this, uri, rootShellOutput)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
} else {
// Use new installation method
new InstallMagisk(this, rootShellOutput, uri, keepEnc, keepVerity, boot)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
}
break;
}
}
@Override
public void onBackPressed() {
// Prevent user accidentally press back button
}
private static class FlashLogAdapter extends RecyclerView.Adapter<ViewHolder> {
private List<String> mList;
FlashLogAdapter(List<String> list) {
mList = list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_flashlog, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.text.setText(mList.get(position));
}
@Override
public int getItemCount() {
return mList.size();
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.textView) TextView text;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +0,0 @@
package com.topjohnwu.magisk;
import android.content.Intent;
import android.os.Bundle;
import com.topjohnwu.magisk.components.Activity;
public class SplashActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getMagiskManager().startup();
Intent intent = new Intent(this, MainActivity.class);
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);
if (section != null) {
intent.putExtra(MagiskManager.INTENT_SECTION, section);
}
startActivity(intent);
finish();
}
}

View File

@@ -1,65 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.os.Build;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class DownloadBusybox extends ParallelTask<Void, Void, Void> {
private static final String BUSYBOX_ARM = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-arm";
private static final String BUSYBOX_X86 = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-x86";
private File busybox;
public DownloadBusybox(Context context) {
super(context);
busybox = new File(context.getCacheDir(), "busybox");
}
@Override
protected Void doInBackground(Void... voids) {
Context context = getMagiskManager();
Utils.removeItem(getShell(), context.getApplicationInfo().dataDir + "/busybox");
try {
FileOutputStream out = new FileOutputStream(busybox);
InputStream in = WebService.request(WebService.GET,
Build.SUPPORTED_32_BIT_ABIS[0].contains("x86") ?
BUSYBOX_X86 :
BUSYBOX_ARM,
null
);
if (in == null) throw new IOException();
BufferedInputStream bis = new BufferedInputStream(in);
byte[] buffer = new byte[4096];
int len;
while ((len = bis.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
if (busybox.exists()) {
getShell().su(
"rm -rf " + MagiskManager.BUSYBOXPATH,
"mkdir -p " + MagiskManager.BUSYBOXPATH,
"cp " + busybox + " " + MagiskManager.BUSYBOXPATH,
"chmod -R 755 " + MagiskManager.BUSYBOXPATH,
MagiskManager.BUSYBOXPATH + "/busybox --install -s " + MagiskManager.BUSYBOXPATH
);
busybox.delete();
}
return null;
}
}

View File

@@ -1,74 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.superuser.Policy;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
import java.io.File;
import java.util.List;
public class HideManager extends ParallelTask<Void, Void, Boolean> {
public HideManager(Context context) {
super(context);
}
@Override
protected void onPreExecute() {
getMagiskManager().toast(R.string.hide_manager_toast, Toast.LENGTH_SHORT);
}
@Override
protected Boolean doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null)
return false;
// Generate a new unhide app with random package name
File unhideAPK = new File(Environment.getExternalStorageDirectory() + "/MagiskManager", "unhide.apk");
unhideAPK.getParentFile().mkdirs();
String pkg = ZipUtils.generateUnhide(mm, unhideAPK);
// Install the application
List<String> ret = getShell().su("pm install " + unhideAPK + ">/dev/null && echo true || echo false");
unhideAPK.delete();
if (!Utils.isValidShellResponse(ret) || !Boolean.parseBoolean(ret.get(0)))
return false;
try {
// Allow the application to gain root by default
PackageManager pm = mm.getPackageManager();
int uid = pm.getApplicationInfo(pkg, 0).uid;
Policy policy = new Policy(uid, pm);
policy.policy = Policy.ALLOW;
policy.notification = false;
policy.logging = false;
mm.suDB.addPolicy(policy);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
// Hide myself!
getShell().su_raw("pm hide " + mm.getPackageName());
return true;
}
@Override
protected void onPostExecute(Boolean b) {
MagiskManager mm = getMagiskManager();
if (mm == null)
return;
if (!b) {
mm.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG);
}
super.onPostExecute(b);
}
}

View File

@@ -1,230 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.AdaptiveList;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.TarEntry;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
import org.kamranzafar.jtar.TarInputStream;
import org.kamranzafar.jtar.TarOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
private static final int PATCH_MODE = 0;
private static final int DIRECT_MODE = 1;
private Uri mBootImg, mZip;
private AdaptiveList<String> mList;
private String mBootLocation;
private boolean mKeepEnc, mKeepVerity;
private int mode;
private InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity) {
super(context);
mList = list;
mZip = zip;
mKeepEnc = enc;
mKeepVerity = verity;
}
public InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity, Uri boot) {
this(context, list, zip, enc, verity);
mBootImg = boot;
mode = PATCH_MODE;
}
public InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity, String boot) {
this(context, list, zip, enc, verity);
mBootLocation = boot;
mode = DIRECT_MODE;
}
@Override
protected void onPreExecute() {
// UI updates must run in the UI thread
mList.setCallback(this::publishProgress);
}
@Override
protected void onProgressUpdate(Void... values) {
mList.updateView();
}
@Override
protected Boolean doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null) return false;
File install = new File(Utils.getEncContext(mm).getFilesDir().getParent(), "install");
getShell().sh_raw("rm -rf " + install);
List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
String arch;
if (abis.contains("x86_64")) arch = "x64";
else if (abis.contains("arm64-v8a")) arch = "arm64";
else if (abis.contains("x86")) arch = "x86";
else arch = "arm";
mList.add("- Device platform: " + arch);
try {
// Unzip files
mList.add("- Extracting files");
try (InputStream in = mm.getContentResolver().openInputStream(mZip)) {
if (in == null) throw new FileNotFoundException();
BufferedInputStream buf = new BufferedInputStream(in);
buf.mark(Integer.MAX_VALUE);
ZipUtils.unzip(buf, install, arch + "/", true);
buf.reset();
ZipUtils.unzip(buf, install, "common/", true);
buf.reset();
ZipUtils.unzip(buf, install, "chromeos/", false);
buf.reset();
ZipUtils.unzip(buf, install, "META-INF/com/google/android/update-binary", true);
} catch (FileNotFoundException e) {
mList.add("! Invalid Uri");
throw e;
} catch (Exception e) {
mList.add("! Cannot unzip zip");
throw e;
}
File boot;
switch (mode) {
case PATCH_MODE:
boot = new File(install, "boot.img");
// Copy boot image to local
try (
InputStream in = mm.getContentResolver().openInputStream(mBootImg);
OutputStream out = new FileOutputStream(boot)
) {
InputStream source;
if (in == null) throw new FileNotFoundException();
if (Utils.getNameFromUri(mm, mBootImg).endsWith(".tar")) {
// Extract boot.img from tar
TarInputStream tar = new TarInputStream(new BufferedInputStream(in));
org.kamranzafar.jtar.TarEntry entry;
while ((entry = tar.getNextEntry()) != null) {
if (entry.getName().equals("boot.img"))
break;
}
source = tar;
} else {
// Direct copy raw image
source = new BufferedInputStream(in);
}
byte buffer[] = new byte[1024];
int length;
while ((length = source.read(buffer)) > 0)
out.write(buffer, 0, length);
} catch (FileNotFoundException e) {
mList.add("! Invalid Uri");
throw e;
} catch (IOException e) {
mList.add("! Copy failed");
throw e;
}
break;
case DIRECT_MODE:
boot = new File(mBootLocation);
break;
default:
return false;
}
mList.add("- Use boot image: " + boot);
Shell shell;
if (mode == PATCH_MODE && Shell.rootAccess()) {
// Force non-root shell
shell = Shell.getShell("sh");
} else {
shell = getShell();
}
// Patch boot image
shell.sh(mList,
"cd " + install,
"KEEPFORCEENCRYPT=" + mKeepEnc + " KEEPVERITY=" + mKeepVerity + " sh " +
"update-binary indep boot_patch.sh " + boot +
" && echo 'Success!' || echo 'Failed!'"
);
if (!TextUtils.equals(mList.get(mList.size() - 1), "Success!"))
return false;
File patched_boot = new File(install, "new-boot.img");
mList.add("");
switch (mode) {
case PATCH_MODE:
File dest = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/patched_boot" + mm.bootFormat);
dest.getParentFile().mkdirs();
switch (mm.bootFormat) {
case ".img":
getShell().sh_raw("cp -f " + patched_boot + " " + dest);
break;
case ".img.tar":
TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
tar.putNextEntry(new TarEntry(patched_boot, "boot.img"));
byte buffer[] = new byte[4096];
BufferedInputStream in = new BufferedInputStream(new FileInputStream(patched_boot));
int len;
while ((len = in.read(buffer)) != -1) {
tar.write(buffer, 0, len);
}
tar.flush();
tar.close();
in.close();
break;
}
mList.add("*********************************");
mList.add(" Patched Boot Image is placed in ");
mList.add(" " + dest + " ");
mList.add("*********************************");
break;
case DIRECT_MODE:
// Direct flash boot image
getShell().su(mList, "flash_boot_image " + patched_boot + " " + mBootLocation);
break;
default:
return false;
}
// Finals
getShell().sh_raw(
"cd " + install,
"mv bin/busybox busybox",
"rm -rf bin *.img update-binary",
"cd /");
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
}
}

View File

@@ -1,45 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.module.BaseModule;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ValueSortedMap;
public class LoadModules extends ParallelTask<Void, Void, Void> {
public LoadModules(Context context) {
super(context);
}
@Override
protected Void doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null) return null;
Logger.dev("LoadModules: Loading modules");
mm.moduleMap = new ValueSortedMap<>();
for (String path : Utils.getModList(getShell(), MagiskManager.MAGISK_PATH)) {
Logger.dev("LoadModules: Adding modules from " + path);
try {
Module module = new Module(getShell(), path);
mm.moduleMap.put(module.getId(), module);
} catch (BaseModule.CacheModException ignored) {}
}
Logger.dev("LoadModules: Data load done");
return null;
}
@Override
protected void onPostExecute(Void v) {
MagiskManager mm = getMagiskManager();
if (mm == null) return;
mm.moduleLoadDone.publish();
super.onPostExecute(v);
}
}

View File

@@ -1,47 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.support.v7.app.AlertDialog;
import android.webkit.WebView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.WebService;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
public class MarkDownWindow extends ParallelTask<Void, Void, String> {
private String mTitle, mUrl;
public MarkDownWindow(Activity context, String title, String url) {
super(context);
mTitle = title;
mUrl = url;
}
@Override
protected String doInBackground(Void... voids) {
String md = WebService.getString(mUrl);
Parser parser = Parser.builder().build();
HtmlRenderer renderer = HtmlRenderer.builder().build();
Node doc = parser.parse(md);
return String.format(
"<link rel='stylesheet' type='text/css' href='file:///android_asset/%s.css'/> %s",
getMagiskManager().isDarkTheme ? "dark" : "light", renderer.render(doc));
}
@Override
protected void onPostExecute(String html) {
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setTitle(mTitle);
WebView wv = new WebView(getActivity());
wv.loadDataWithBaseURL("fake://", html, "text/html", "UTF-8", null);
alert.setView(wv);
alert.setNegativeButton(R.string.close, (dialog, id) -> dialog.dismiss());
alert.show();
}
}

View File

@@ -1,133 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.widget.Toast;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
import com.topjohnwu.magisk.utils.ZipUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class ProcessRepoZip extends ParallelTask<Void, Void, Boolean> {
private ProgressDialog progressDialog;
private boolean mInstall;
private String mLink;
private File mFile;
public ProcessRepoZip(Activity context, String link, String filename, boolean install) {
super(context);
mLink = link;
mFile = new File(Environment.getExternalStorageDirectory() + "/MagiskManager", filename);
mFile.getParentFile().mkdirs();
mInstall = install;
}
@Override
protected void onPreExecute() {
Activity activity = getActivity();
progressDialog = ProgressDialog.show(activity,
activity.getString(R.string.zip_download_title),
activity.getString(R.string.zip_download_msg));
}
@Override
protected void onProgressUpdate(Void... values) {
progressDialog.setTitle(R.string.zip_process_title);
progressDialog.setMessage(getActivity().getString(R.string.zip_process_msg));
}
@Override
protected Boolean doInBackground(Void... params) {
Activity activity = getActivity();
if (activity == null) return null;
try {
// Request zip from Internet
InputStream in = WebService.request(WebService.GET, mLink, null);
if (in == null) return false;
in = new BufferedInputStream(in);
// Temp files
File temp1 = new File(activity.getCacheDir(), "1.zip");
File temp2 = new File(temp1.getParentFile(), "2.zip");
temp1.getParentFile().mkdir();
// First remove top folder in Github source zip, Web -> temp1
ZipUtils.removeTopFolder(in, temp1);
publishProgress();
// Then sign the zip for the first time, temp1 -> temp2
ZipUtils.signZip(activity, temp1, temp2, false);
// Adjust the zip to prevent unzip issues, temp2 -> temp1
ZipUtils.zipAdjust(temp2.getPath(), temp1.getPath());
// Finally, sign the whole zip file again, temp1 -> temp2
ZipUtils.signZip(activity, temp1, temp2, true);
// Write it to the target zip, temp2 -> file
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(mFile));
InputStream source = new BufferedInputStream(new FileInputStream(temp2))
) {
byte[] buffer = new byte[4096];
int length;
while ((length = source.read(buffer)) > 0)
out.write(buffer, 0, length);
}
// Delete temp files
temp1.delete();
temp2.delete();
return true;
} catch (Exception e) {
Logger.error("ProcessRepoZip: Error!");
e.printStackTrace();
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
Activity activity = getActivity();
if (activity == null) return;
progressDialog.dismiss();
Uri uri = Uri.fromFile(mFile);
if (result) {
if (Shell.rootAccess() && mInstall) {
Intent intent = new Intent(getActivity(), FlashActivity.class);
intent.setData(uri).putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_ZIP);
activity.startActivity(intent);
} else {
Utils.showUriSnack(activity, uri);
}
} else {
Utils.getMagiskManager(activity).toast(R.string.process_error, Toast.LENGTH_LONG);
}
super.onPostExecute(result);
}
@Override
public ParallelTask<Void, Void, Boolean> exec(Void... voids) {
Utils.runWithPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> super.exec(voids));
return this;
}
}

View File

@@ -1,40 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.widget.Toast;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Utils;
import java.util.List;
public class RestoreStockBoot extends ParallelTask<Void, Void, Boolean> {
private String mBoot;
public RestoreStockBoot(Context context, String boot) {
super(context);
mBoot = boot;
}
@Override
protected Boolean doInBackground(Void... voids) {
List<String> ret = getShell().su("cat /init.magisk.rc | grep STOCKSHA1");
if (!Utils.isValidShellResponse(ret))
return false;
String stock_boot = "/data/stock_boot_" + ret.get(0).substring(ret.get(0).indexOf('=') + 1) + ".img.gz";
if (!Utils.itemExist(getShell(), stock_boot))
return false;
getShell().su_raw("flash_boot_image " + stock_boot + " " + mBoot);
return true;
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
getMagiskManager().toast(R.string.restore_done, Toast.LENGTH_SHORT);
} else {
getMagiskManager().toast(R.string.restore_fail, Toast.LENGTH_LONG);
}
}
}

View File

@@ -1,190 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.module.BaseModule;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.WebService;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class UpdateRepos extends ParallelTask<Void, Void, Void> {
public static final String ETAG_KEY = "ETag";
private static final String REPO_URL = "https://api.github.com/users/Magisk-Modules-Repo/repos?per_page=100&page=%d";
private static final String IF_NONE_MATCH = "If-None-Match";
private static final String LINK_KEY = "Link";
private static final int CHECK_ETAG = 0;
private static final int LOAD_NEXT = 1;
private static final int LOAD_PREV = 2;
private List<String> etags;
private List<String> cached;
private RepoDatabaseHelper repoDB;
private SharedPreferences prefs;
public UpdateRepos(Context context) {
super(context);
prefs = getMagiskManager().prefs;
repoDB = getMagiskManager().repoDB;
String prefsPath = context.getApplicationInfo().dataDir + "/shared_prefs";
// Legacy data cleanup
File old = new File(prefsPath, "RepoMap.xml");
if (old.exists() || !prefs.getString("repomap", "empty").equals("empty")) {
old.delete();
prefs.edit().remove("version").remove("repomap").remove(ETAG_KEY).apply();
repoDB.clearRepo();
}
etags = new ArrayList<>(
Arrays.asList(prefs.getString(ETAG_KEY, "").split(",")));
}
private void loadJSON(String jsonString) throws Exception {
JSONArray jsonArray = new JSONArray(jsonString);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonobject = jsonArray.getJSONObject(i);
String id = jsonobject.getString("description");
String name = jsonobject.getString("name");
String lastUpdate = jsonobject.getString("pushed_at");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
Date updatedDate = format.parse(lastUpdate);
Repo repo = repoDB.getRepo(id);
try {
Boolean updated;
if (repo == null) {
Logger.dev("UpdateRepos: Create new repo " + id);
repo = new Repo(name, updatedDate);
updated = true;
} else {
// Popout from cached
cached.remove(id);
updated = repo.update(updatedDate);
}
if (updated) {
repoDB.addRepo(repo);
}
} catch (BaseModule.CacheModException ignored) {}
}
}
private boolean loadPage(int page, String url, int mode) {
Logger.dev("UpdateRepos: Loading page: " + (page + 1));
Map<String, String> header = new HashMap<>();
if (mode == CHECK_ETAG && page < etags.size() && !TextUtils.isEmpty(etags.get(page))) {
Logger.dev("ETAG: " + etags.get(page));
header.put(IF_NONE_MATCH, etags.get(page));
}
if (url == null) {
url = String.format(Locale.US, REPO_URL, page + 1);
}
String jsonString = WebService.getString(url, header);
if (TextUtils.isEmpty(jsonString)) {
// At least check the pages we know
return page + 1 < etags.size() && loadPage(page + 1, null, CHECK_ETAG);
}
// The getString succeed, parse the new stuffs
try {
loadJSON(jsonString);
} catch (Exception e) {
e.printStackTrace();
return false;
}
// Update the ETAG
String newEtag = header.get(ETAG_KEY);
newEtag = newEtag.substring(newEtag.indexOf('\"'), newEtag.lastIndexOf('\"') + 1);
Logger.dev("New ETAG: " + newEtag);
if (page < etags.size()) {
etags.set(page, newEtag);
} else {
etags.add(newEtag);
}
String links = header.get(LINK_KEY);
if (links != null) {
if (mode == CHECK_ETAG || mode == LOAD_NEXT) {
// Try to check next page URL
url = null;
for (String s : links.split(", ")) {
if (s.contains("next")) {
url = s.substring(s.indexOf("<") + 1, s.indexOf(">; "));
break;
}
}
if (url != null) {
loadPage(page + 1, url, LOAD_NEXT);
}
}
if (mode == CHECK_ETAG || mode == LOAD_PREV) {
// Try to check prev page URL
url = null;
for (String s : links.split(", ")) {
if (s.contains("prev")) {
url = s.substring(s.indexOf("<") + 1, s.indexOf(">; "));
break;
}
}
if (url != null) {
loadPage(page - 1, url, LOAD_PREV);
}
}
}
return true;
}
@Override
protected Void doInBackground(Void... voids) {
Logger.dev("UpdateRepos: Loading repos");
cached = repoDB.getRepoIDList();
if (!loadPage(0, null, CHECK_ETAG)) {
Logger.dev("UpdateRepos: No updates, use DB");
return null;
}
// The leftover cached means they are removed from online repo
repoDB.removeRepo(cached);
// Update ETag
StringBuilder etagBuilder = new StringBuilder();
for (int i = 0; i < etags.size(); ++i) {
if (i != 0) etagBuilder.append(",");
etagBuilder.append(etags.get(i));
}
prefs.edit().putString(ETAG_KEY, etagBuilder.toString()).apply();
Logger.dev("UpdateRepos: Done");
return null;
}
@Override
protected void onPostExecute(Void v) {
MagiskManager mm = getMagiskManager();
if (mm == null) return;
mm.repoLoadDone.publish();
super.onPostExecute(v);
}
}

View File

@@ -1,79 +0,0 @@
package com.topjohnwu.magisk.components;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.WindowManager;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
public class Activity extends AppCompatActivity {
private Runnable permissionGrantCallback;
public Activity() {
super();
Configuration configuration = new Configuration();
configuration.setLocale(MagiskManager.locale);
applyOverrideConfiguration(configuration);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (this instanceof Topic.Subscriber) {
((Topic.Subscriber) this).subscribeTopics();
}
}
@Override
protected void onDestroy() {
if (this instanceof Topic.Subscriber) {
((Topic.Subscriber) this).unsubscribeTopics();
}
super.onDestroy();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (permissionGrantCallback != null) {
permissionGrantCallback.run();
}
}
permissionGrantCallback = null;
}
public void setPermissionGrantCallback(Runnable callback) {
permissionGrantCallback = callback;
}
public MagiskManager getMagiskManager() {
return (MagiskManager) super.getApplicationContext();
}
public Shell getShell() {
return Shell.getShell(this);
}
protected void setFloating() {
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
if (isTablet) {
WindowManager.LayoutParams params = getWindow().getAttributes();
params.height = getResources().getDimensionPixelSize(R.dimen.floating_height);
params.width = getResources().getDimensionPixelSize(R.dimen.floating_width);
params.alpha = 1.0f;
params.dimAmount = 0.6f;
params.flags |= 2;
getWindow().setAttributes(params);
setFinishOnTouchOutside(true);
}
}
}

View File

@@ -1,68 +0,0 @@
package com.topjohnwu.magisk.module;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
public class Module extends BaseModule {
private String mRemoveFile, mDisableFile, mUpdateFile;
private boolean mEnable, mRemove, mUpdated;
public Module(Shell shell, String path) throws CacheModException {
parseProps(Utils.readFile(shell, path + "/module.prop"));
mRemoveFile = path + "/remove";
mDisableFile = path + "/disable";
mUpdateFile = path + "/update";
if (getId() == null) {
int sep = path.lastIndexOf('/');
setId(path.substring(sep + 1));
}
if (getName() == null) {
setName(getId());
}
Logger.dev("Creating Module, id: " + getId());
mEnable = !Utils.itemExist(shell, mDisableFile);
mRemove = Utils.itemExist(shell, mRemoveFile);
mUpdated = Utils.itemExist(shell, mUpdateFile);
}
public void createDisableFile(Shell shell) {
mEnable = false;
Utils.createFile(shell, mDisableFile);
}
public void removeDisableFile(Shell shell) {
mEnable = true;
Utils.removeItem(shell, mDisableFile);
}
public boolean isEnabled() {
return mEnable;
}
public void createRemoveFile(Shell shell) {
mRemove = true;
Utils.createFile(shell, mRemoveFile);
}
public void deleteRemoveFile(Shell shell) {
mRemove = false;
Utils.removeItem(shell, mRemoveFile);
}
public boolean willBeRemoved() {
return mRemove;
}
public boolean isUpdated() {
return mUpdated;
}
}

View File

@@ -1,76 +0,0 @@
package com.topjohnwu.magisk.module;
import android.content.ContentValues;
import android.database.Cursor;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.WebService;
import java.util.Date;
public class Repo extends BaseModule {
private static final String FILE_URL = "https://raw.githubusercontent.com/Magisk-Modules-Repo/%s/master/%s";
private static final String ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip";
private String repoName;
private Date mLastUpdate;
public Repo(String name, Date lastUpdate) throws CacheModException {
mLastUpdate = lastUpdate;
repoName = name;
update();
}
public Repo(Cursor c) {
super(c);
repoName = c.getString(c.getColumnIndex("repo_name"));
mLastUpdate = new Date(c.getLong(c.getColumnIndex("last_update")));
}
public void update() throws CacheModException {
String props = WebService.getString(getManifestUrl());
String lines[] = props.split("\\n");
parseProps(lines);
Logger.dev("Repo: Fetching prop: " + getId());
}
public boolean update(Date lastUpdate) throws CacheModException {
if (lastUpdate.after(mLastUpdate)) {
mLastUpdate = lastUpdate;
update();
return true;
}
return false;
}
public ContentValues getContentValues() {
ContentValues values = new ContentValues();
values.put("id", getId());
values.put("name", getName());
values.put("version", getVersion());
values.put("versionCode", getVersionCode());
values.put("author", getAuthor());
values.put("description", getDescription());
values.put("repo_name", repoName);
values.put("last_update", mLastUpdate.getTime());
values.put("template", getTemplateVersion());
return values;
}
public String getZipUrl() {
return String.format(ZIP_URL, repoName);
}
public String getManifestUrl() {
return String.format(FILE_URL, repoName, "module.prop");
}
public String getDetailUrl() {
return String.format(FILE_URL, repoName, "README.md");
}
public Date getLastUpdate() {
return mLastUpdate;
}
}

View File

@@ -1,40 +0,0 @@
package com.topjohnwu.magisk.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.superuser.Policy;
import com.topjohnwu.magisk.utils.Utils;
public class PackageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
MagiskManager magiskManager = Utils.getMagiskManager(context);
String pkg = intent.getData().getEncodedSchemeSpecificPart();
Policy policy = magiskManager.suDB.getPolicy(pkg);
if (policy == null)
return;
switch (intent.getAction()) {
case Intent.ACTION_PACKAGE_REPLACED:
// This will only work pre-O
if (magiskManager.suReauth) {
magiskManager.suDB.deletePolicy(policy);
} else {
int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
// Update the UID if available
if (uid > 0) {
policy.uid = uid % 100000;
}
magiskManager.suDB.updatePolicy(policy);
}
break;
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
magiskManager.suDB.deletePolicy(policy);
break;
}
}
}

View File

@@ -1,34 +0,0 @@
package com.topjohnwu.magisk.services;
import android.app.IntentService;
import android.content.Intent;
import android.os.Build;
import android.support.v7.app.NotificationCompat;
import com.topjohnwu.magisk.R;
public class OnBootIntentService extends IntentService {
private static final int ONBOOT_NOTIFICATION_ID = 3;
public OnBootIntentService() {
super("OnBootIntentService");
}
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle("onBoot")
.setContentText("Running onBoot operations...");
startForeground(ONBOOT_NOTIFICATION_ID, builder.build());
}
}
@Override
protected void onHandleIntent(Intent intent) {
// Currently nothing to do
}
}

View File

@@ -1,24 +0,0 @@
package com.topjohnwu.magisk.superuser;
import android.content.Intent;
import android.os.Bundle;
import com.topjohnwu.magisk.components.Activity;
public class RequestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent == null) {
finish();
return;
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setClass(this, SuRequestActivity.class);
startActivity(intent);
finish();
}
}

View File

@@ -1,36 +0,0 @@
package com.topjohnwu.magisk.utils;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
public class AdaptiveList<E> extends ArrayList<E> {
private Runnable callback;
private RecyclerView mView;
public AdaptiveList(RecyclerView v) {
mView = v;
}
public void updateView() {
mView.getAdapter().notifyDataSetChanged();
mView.scrollToPosition(mView.getAdapter().getItemCount() - 1);
}
public void setCallback(Runnable cb) {
callback = cb;
}
public boolean add(E e) {
boolean ret = super.add(e);
if (ret) {
if (callback == null) {
updateView();
} else {
callback.run();
}
}
return ret;
}
}

View File

@@ -1,49 +0,0 @@
package com.topjohnwu.magisk.utils;
import android.util.Log;
import com.topjohnwu.magisk.MagiskManager;
import java.util.Locale;
public class Logger {
public static final String MAIN_TAG = "Magisk";
public static final String DEBUG_TAG = "MagiskManager";
public static void debug(String line) {
Log.d(DEBUG_TAG, "DEBUG: " + line);
}
public static void debug(String fmt, Object... args) {
debug(String.format(Locale.US, fmt, args));
}
public static void error(String line) {
Log.e(MAIN_TAG, "MANAGERERROR: " + line);
}
public static void error(String fmt, Object... args) {
error(String.format(Locale.US, fmt, args));
}
public static void dev(String line) {
if (MagiskManager.devLogging) {
Log.d(DEBUG_TAG, line);
}
}
public static void dev(String fmt, Object... args) {
dev(String.format(Locale.US, fmt, args));
}
public static void shell(String line) {
if (MagiskManager.shellLogging) {
Log.d(DEBUG_TAG, "SHELL: " + line);
}
}
public static void shell(String fmt, Object... args) {
shell(String.format(Locale.US, fmt, args));
}
}

View File

@@ -1,114 +0,0 @@
package com.topjohnwu.magisk.utils;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.util.Base64;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.safetynet.SafetyNet;
import com.topjohnwu.magisk.R;
import org.json.JSONException;
import org.json.JSONObject;
import java.security.SecureRandom;
public abstract class SafetyNetHelper
implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
private static boolean isRunning = false;
private GoogleApiClient mGoogleApiClient;
private Result ret;
protected FragmentActivity mActivity;
public SafetyNetHelper(FragmentActivity activity) {
ret = new Result();
mActivity = activity;
}
// Entry point to start test
public void requestTest() {
if (isRunning)
return;
// Connect Google Service
mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
.enableAutoManage(mActivity, this)
.addApi(SafetyNet.API)
.addConnectionCallbacks(this)
.build();
mGoogleApiClient.connect();
isRunning = true;
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult result) {
Logger.dev("SN: Google API fail");
ret.errmsg = result.getErrorMessage();
handleResults(ret);
}
@Override
public void onConnectionSuspended(int i) {
Logger.dev("SN: Google API Suspended");
switch (i) {
case CAUSE_NETWORK_LOST:
ret.errmsg = mActivity.getString(R.string.safetyNet_network_loss);
break;
case CAUSE_SERVICE_DISCONNECTED:
ret.errmsg = mActivity.getString(R.string.safetyNet_service_disconnected);
break;
}
handleResults(ret);
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Logger.dev("SN: Google API Connected");
// Create nonce
byte[] nonce = new byte[24];
new SecureRandom().nextBytes(nonce);
Logger.dev("SN: Check with nonce: " + Base64.encodeToString(nonce, Base64.DEFAULT));
// Call SafetyNet
SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)
.setResultCallback(result -> {
Status status = result.getStatus();
if (status.isSuccess()) {
String json = new String(Base64.decode(result.getJwsResult().split("\\.")[1], Base64.DEFAULT));
Logger.dev("SN: Response: " + json);
try {
JSONObject decoded = new JSONObject(json);
ret.ctsProfile = decoded.getBoolean("ctsProfileMatch");
ret.basicIntegrity = decoded.getBoolean("basicIntegrity");
ret.failed = false;
} catch (JSONException e) {
ret.errmsg = mActivity.getString(R.string.safetyNet_res_invalid);
}
} else {
Logger.dev("SN: No response");
ret.errmsg = mActivity.getString(R.string.safetyNet_no_response);
}
// Disconnect
mGoogleApiClient.stopAutoManage(mActivity);
mGoogleApiClient.disconnect();
isRunning = false;
handleResults(ret);
});
}
// Callback function to save the results
public abstract void handleResults(Result result);
public static class Result {
public boolean failed = true;
public String errmsg;
public boolean ctsProfile = false;
public boolean basicIntegrity = false;
}
}

View File

@@ -1,225 +0,0 @@
package com.topjohnwu.magisk.utils;
import android.content.Context;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Modified by topjohnwu, based on Chainfire's libsuperuser
*/
public class Shell {
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted
public static int rootStatus;
private final Process shellProcess;
private final DataOutputStream STDIN;
private final DataInputStream STDOUT;
private boolean isValid;
private void testRootShell(DataOutputStream in, DataInputStream out) throws IOException {
in.write(("id\n").getBytes("UTF-8"));
in.flush();
String s = new BufferedReader(new InputStreamReader(out)).readLine();
if (TextUtils.isEmpty(s) || !s.contains("uid=0")) {
in.close();
out.close();
throw new IOException();
}
}
private Shell() {
rootStatus = 1;
Process process = null;
DataOutputStream in = null;
DataInputStream out = null;
try {
// Try getting global namespace
process = Runtime.getRuntime().exec("su --mount-master");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
testRootShell(in, out);
} catch (IOException e) {
// Feature not implemented, normal root shell
try {
process = Runtime.getRuntime().exec("su");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
testRootShell(in, out);
} catch (IOException e1) {
rootStatus = 0;
}
}
if (!rootAccess()) {
// Try to gain non-root sh
try {
process = Runtime.getRuntime().exec("sh");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
} catch (IOException e) {
// Nothing works....
shellProcess = null;
STDIN = null;
STDOUT = null;
isValid = false;
return;
}
}
isValid = true;
shellProcess = process;
STDIN = in;
STDOUT = out;
sh_raw("umask 022");
}
private Shell(String command) {
Process process;
DataOutputStream in;
DataInputStream out;
try {
process = Runtime.getRuntime().exec(command);
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
} catch (IOException e) {
// Nothing works....
shellProcess = null;
STDIN = null;
STDOUT = null;
isValid = false;
return;
}
isValid = true;
shellProcess = process;
STDIN = in;
STDOUT = out;
}
public static Shell getShell() {
return new Shell();
}
public static Shell getShell(String command) {
return new Shell(command);
}
public static Shell getShell(Context context) {
MagiskManager magiskManager = Utils.getMagiskManager(context);
if (magiskManager.shell == null || !magiskManager.shell.isValid) {
// Get new shell if needed
magiskManager.shell = getShell();
}
return magiskManager.shell;
}
public static boolean rootAccess() {
return rootStatus > 0;
}
public void loadInputStream(InputStream in) {
try {
int read;
byte[] bytes = new byte[4096];
while ((read = in.read(bytes)) != -1) {
STDIN.write(bytes, 0, read);
}
STDIN.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public List<String> sh(String... commands) {
List<String> res = new ArrayList<>();
if (!isValid) return res;
sh(res, commands);
return res;
}
public void sh_raw(String... commands) {
sh_raw(false, commands);
}
public void sh_raw(boolean stdout, String... commands) {
if (!isValid) return;
synchronized (shellProcess) {
try {
for (String command : commands) {
Logger.shell(command);
STDIN.write((command + (stdout ? "\n" : " >/dev/null\n")).getBytes("UTF-8"));
STDIN.flush();
}
} catch (IOException e) {
e.printStackTrace();
shellProcess.destroy();
isValid = false;
}
}
}
public void sh(Collection<String> output, String... commands) {
if (!isValid) return;
try {
shellProcess.exitValue();
isValid = false;
return; // The process is dead, return
} catch (IllegalThreadStateException ignored) {
// This should be the expected result
}
synchronized (shellProcess) {
StreamGobbler out = new StreamGobbler(STDOUT, output);
out.start();
sh_raw(true, commands);
sh_raw(true, "echo \'-shell-done-\'");
try { out.join(); } catch (InterruptedException ignored) {}
}
}
public List<String> su(String... commands) {
if (!rootAccess()) return sh();
return sh(commands);
}
public void su_raw(String... commands) {
if (!rootAccess()) return;
sh_raw(commands);
}
public void su(Collection<String> output, String... commands) {
if (!rootAccess()) return;
sh(output, commands);
}
public static abstract class AbstractList<E> extends java.util.AbstractList<E> {
@Override
public abstract boolean add(E e);
@Override
public E get(int i) {
return null;
}
@Override
public int size() {
return 0;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,79 +0,0 @@
package com.topjohnwu.magisk.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
public class WebService {
public final static int GET = 1;
public final static int POST = 2;
public static String getString(String url) {
return getString(url, null);
}
public static String getString(String url, Map<String, String> header) {
InputStream in = request(GET, url, header);
if (in == null) return "";
BufferedReader br = new BufferedReader(new InputStreamReader(in));
int len;
StringBuilder builder = new StringBuilder();
char buf[] = new char[4096];
try {
while ((len = br.read(buf)) != -1) {
builder.append(buf, 0, len);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return builder.toString();
}
public static InputStream request(int method, String address, Map<String, String> header) {
Logger.dev("WebService: Service call " + address);
try {
URL url = new URL(address);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setDoInput(true);
if (method == POST) {
conn.setRequestMethod("POST");
} else if (method == GET) {
conn.setRequestMethod("GET");
}
if (header != null) {
for (Map.Entry<String, String> entry : header.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
if (conn.getResponseCode() == HttpsURLConnection.HTTP_OK) {
if (header != null) {
header.clear();
for (Map.Entry<String, List<String>> entry : conn.getHeaderFields().entrySet()) {
List<String> l = entry.getValue();
header.put(entry.getKey(), l.get(l.size() - 1));
}
}
return conn.getInputStream();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="@dimen/card_vertical_margin"
android:layout_marginEnd="@dimen/card_horizontal_margin"
android:layout_marginStart="@dimen/card_horizontal_margin"
android:layout_marginTop="@dimen/card_vertical_margin"
style="?attr/cardStyle"
android:minHeight="?android:attr/listPreferredItemHeight"
card_view:cardCornerRadius="@dimen/card_corner_radius"
card_view:cardElevation="@dimen/card_elevation">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
android:padding="@dimen/card_layout_padding">
<ImageView
android:id="@+id/app_icon"
android:layout_width="@dimen/card_appicon_size"
android:layout_height="@dimen/card_appicon_size"
android:layout_centerVertical="true"
android:scaleType="centerCrop"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignBottom="@+id/app_icon"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingEnd="@dimen/card_appicon_size"
android:paddingStart="65dp"
android:weightSum="1">
<TextView
android:id="@+id/app_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:maxLines="1"
android:paddingEnd="3dp"
android:paddingStart="3dp"
android:textStyle="bold"/>
<TextView
android:id="@+id/app_package"
android:layout_width="fill_parent"
android:layout_height="25dp"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:marqueeRepeatLimit="marquee_forever"
android:maxLines="1"
android:paddingEnd="3dp"
android:paddingStart="3dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true">
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:gravity="center"
android:src="@drawable/ic_menu_overflow_material"
android:checked="false" />
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>

Some files were not shown because too many files have changed in this diff Show More