mirror of
https://github.com/topjohnwu/Magisk
synced 2025-11-05 19:22:29 +01:00
Compare commits
94 Commits
manager-v4
...
manager-v5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a69b16d36 | ||
|
|
b5e8673e62 | ||
|
|
264c6a50b6 | ||
|
|
493642eb38 | ||
|
|
28d42b9164 | ||
|
|
42f29062ca | ||
|
|
c4377ed6c2 | ||
|
|
7d283ed65f | ||
|
|
bf1f941e50 | ||
|
|
789fef34ba | ||
|
|
1daf5a611c | ||
|
|
6aed1db67e | ||
|
|
cf68854770 | ||
|
|
711392c73b | ||
|
|
9573c32481 | ||
|
|
a15f80f79d | ||
|
|
23e7475f06 | ||
|
|
1eb571b787 | ||
|
|
dd3b716d85 | ||
|
|
28649c07e3 | ||
|
|
961e02be0d | ||
|
|
a161491bfd | ||
|
|
e0b4d1c1e4 | ||
|
|
fd4aaab137 | ||
|
|
42d14d5ca2 | ||
|
|
d3ff482c9b | ||
|
|
f682368eeb | ||
|
|
4a5d033efb | ||
|
|
343161b195 | ||
|
|
bc576a9659 | ||
|
|
19e407fcc4 | ||
|
|
bc7327d004 | ||
|
|
666fa1c797 | ||
|
|
0eda4a7821 | ||
|
|
862058fd2b | ||
|
|
69e5bcd57d | ||
|
|
efeddda328 | ||
|
|
ff6938280e | ||
|
|
1e4425b30f | ||
|
|
b5d1d8cdad | ||
|
|
029be5ccca | ||
|
|
29c2d785b5 | ||
|
|
abda8cfa32 | ||
|
|
44e7d79d4c | ||
|
|
9a1dc8ee0e | ||
|
|
27879c3f01 | ||
|
|
29096eb5d7 | ||
|
|
a573baea03 | ||
|
|
5af07c4531 | ||
|
|
44e36feb09 | ||
|
|
2a7d996881 | ||
|
|
738f943a68 | ||
|
|
47e62a5681 | ||
|
|
1ecbfd7590 | ||
|
|
67c139a04b | ||
|
|
31cc008249 | ||
|
|
9cb026439d | ||
|
|
e6f10176c6 | ||
|
|
0917c79470 | ||
|
|
597baa986d | ||
|
|
75cc4b4843 | ||
|
|
aac088d496 | ||
|
|
a822e5bbc5 | ||
|
|
c527249c21 | ||
|
|
9ef798f534 | ||
|
|
e69b99f089 | ||
|
|
55b8079e86 | ||
|
|
e272dbe9af | ||
|
|
962f8354ac | ||
|
|
20e4a960f7 | ||
|
|
82249cb50a | ||
|
|
fad417e553 | ||
|
|
5ba692f50c | ||
|
|
907e01e524 | ||
|
|
b8ed23efa7 | ||
|
|
2b3bbf7e67 | ||
|
|
464fe627a3 | ||
|
|
6a9e39c470 | ||
|
|
7fec9a3cc6 | ||
|
|
008f6ef462 | ||
|
|
2440c108ca | ||
|
|
430baad8a4 | ||
|
|
51132e74b4 | ||
|
|
a4f33e106a | ||
|
|
baba3190e0 | ||
|
|
47b13aa5ea | ||
|
|
ae88d3054d | ||
|
|
411b600e14 | ||
|
|
0a0ad9a184 | ||
|
|
234bead59e | ||
|
|
76de310986 | ||
|
|
817f050bcd | ||
|
|
60ae685d1e | ||
|
|
4c7bdbb284 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,6 +3,6 @@
|
||||
/local.properties
|
||||
.idea/
|
||||
/build
|
||||
app/app-release.apk
|
||||
app/release
|
||||
*.hprof
|
||||
app/.externalNativeBuild/
|
||||
|
||||
10
README.md
10
README.md
@@ -1,4 +1,6 @@
|
||||
# Magisk Manager
|
||||
The project should be built with Android Studio version 2.2.0+
|
||||
I use Java 8 features, which requires Jack compiler and it's only available in 2.2.0+
|
||||
Also, you need to install CMake and NDK to build the zipadjust library for zip preprocessing
|
||||
# Magisk Manager
|
||||
You need to install CMake and NDK to build the zipadjust library for zip preprocessing
|
||||
|
||||
## Pre-built Binaries
|
||||
Busybox (arm and x86) compiled by osm0sis (`libbusybox.so` under `app\src\main\jniLibs`)
|
||||
Source and more info: [osm0sis' Odds and Ends](https://forum.xda-developers.com/showthread.php?t=2239421)
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.2"
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion "26.0.0"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.topjohnwu.magisk"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 26
|
||||
versionName "4.2.7"
|
||||
jackOptions {
|
||||
enabled true
|
||||
jackInProcess true
|
||||
}
|
||||
targetSdkVersion 26
|
||||
versionCode 44
|
||||
versionName "5.0.4"
|
||||
ndk {
|
||||
moduleName 'zipadjust'
|
||||
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||
abiFilters 'x86', 'armeabi-v7a'
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
@@ -31,34 +28,36 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
dexOptions {
|
||||
preDexLibraries = true
|
||||
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 {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
|
||||
compile 'com.android.support:recyclerview-v7:25.3.0'
|
||||
compile 'com.android.support:cardview-v7:25.3.0'
|
||||
compile 'com.android.support:design:25.3.0'
|
||||
compile 'com.android.support:support-v4:25.3.0'
|
||||
compile 'com.jakewharton:butterknife:8.5.1'
|
||||
compile 'com.github.clans:fab:1.6.4'
|
||||
compile 'com.thoughtbot:expandablerecyclerview:1.4'
|
||||
compile 'us.feras.mdv:markdownview:1.1.0'
|
||||
compile 'com.madgag.spongycastle:core:1.54.0.0'
|
||||
compile 'com.madgag.spongycastle:prov:1.54.0.0'
|
||||
compile 'com.madgag.spongycastle:pkix:1.54.0.0'
|
||||
compile 'com.madgag.spongycastle:pg:1.54.0.0'
|
||||
compile 'com.google.android.gms:play-services-safetynet:9.0.1'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.android.support:recyclerview-v7:26.0.0-beta2'
|
||||
implementation 'com.android.support:cardview-v7:26.0.0-beta2'
|
||||
implementation 'com.android.support:design:26.0.0-beta2'
|
||||
implementation 'com.android.support:support-v4:26.0.0-beta2'
|
||||
implementation 'com.jakewharton:butterknife:8.6.0'
|
||||
implementation 'com.thoughtbot:expandablerecyclerview:1.4'
|
||||
implementation 'us.feras.mdv:markdownview:1.1.0'
|
||||
implementation 'com.madgag.spongycastle:core:1.54.0.0'
|
||||
implementation 'com.madgag.spongycastle:prov:1.54.0.0'
|
||||
implementation 'com.madgag.spongycastle:pkix:1.54.0.0'
|
||||
implementation 'com.google.android.gms:play-services-safetynet:9.0.1'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'
|
||||
}
|
||||
|
||||
12
app/proguard-rules.pro
vendored
12
app/proguard-rules.pro
vendored
@@ -16,10 +16,10 @@
|
||||
# public *;
|
||||
#}
|
||||
|
||||
-keep class android.support.v7.internal.** { *; }
|
||||
-keep interface android.support.v7.internal.** { *; }
|
||||
-keep class android.support.v7.** { *; }
|
||||
-keep interface android.support.v7.** { *; }
|
||||
|
||||
# SpongyCastle
|
||||
-keep class org.spongycastle.** {*;}
|
||||
-keep class org.spongycastle.** { *; }
|
||||
-dontwarn javax.naming.**
|
||||
|
||||
-dontwarn android.content.**
|
||||
-dontwarn android.animation.**
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.topjohnwu.magisk"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<manifest
|
||||
package="com.topjohnwu.magisk"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
@@ -52,8 +52,7 @@
|
||||
android:taskAffinity="internal.superuser"
|
||||
android:theme="@style/SuRequest" />
|
||||
|
||||
<receiver
|
||||
android:name=".superuser.SuReceiver" />
|
||||
<receiver android:name=".superuser.SuReceiver" />
|
||||
|
||||
<receiver android:name=".receivers.BootReceiver">
|
||||
<intent-filter>
|
||||
@@ -61,7 +60,17 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name=".services.BootupIntentService" />
|
||||
<receiver android:name=".receivers.PackageReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
||||
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
||||
<data android:scheme="package" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receivers.ManagerUpdate" />
|
||||
|
||||
<service android:name=".services.OnBootIntentService" />
|
||||
|
||||
<service
|
||||
android:name=".services.UpdateCheckService"
|
||||
|
||||
@@ -1,133 +1,137 @@
|
||||
#!/system/bin/sh
|
||||
##########################################################################################
|
||||
#
|
||||
# Magisk Uninstaller
|
||||
# by topjohnwu
|
||||
#
|
||||
# This script can be placed in /cache/magisk_uninstaller.sh
|
||||
# The Magisk main binary will pick up the script, and uninstall itself, following a reboot
|
||||
# This script can also be used in flashable zip with the uninstaller_loader.sh
|
||||
#
|
||||
# This script will try to do restoration with the following:
|
||||
# 1-1. Find and restore the original stock boot image dump (OTA proof)
|
||||
# 1-2. If 1-1 fails, restore ramdisk from the internal backup
|
||||
# (ramdisk fully restored, not OTA friendly)
|
||||
# 1-3. If 1-2 fails, it will remove added files in ramdisk, however modified files
|
||||
# are remained modified, because we have no backups. By doing so, Magisk will
|
||||
# not be started at boot, but this isn't actually 100% cleaned up
|
||||
# 2. Remove all Magisk related files
|
||||
# (The list is LARGE, most likely due to bad decision in early versions
|
||||
# the latest versions has much less bloat to cleanup)
|
||||
#
|
||||
##########################################################################################
|
||||
|
||||
# Call ui_print_wrap if exists, or else simply use echo
|
||||
# Useful when wrapped in flashable zip
|
||||
ui_print_wrap() {
|
||||
type ui_print >/dev/null 2>&1 && ui_print "$1" || echo "$1"
|
||||
}
|
||||
|
||||
# Call abort if exists, or else show error message and exit
|
||||
# Essential when wrapped in flashable zip
|
||||
abort_wrap() {
|
||||
type abort >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
ui_print_wrap "$1"
|
||||
exit 1
|
||||
else
|
||||
abort "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ ! -d $MAGISKBIN -o ! -f $MAGISKBIN/magiskboot -o ! -f $MAGISKBIN/util_functions.sh ]; then
|
||||
ui_print_wrap "! Cannot find $MAGISKBIN"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -z $BOOTMODE ] && BOOTMODE=false
|
||||
|
||||
# This path should work in any cases
|
||||
TMPDIR=/dev/tmp
|
||||
|
||||
BOOTTMP=$TMPDIR/boottmp
|
||||
MAGISKBIN=/data/magisk
|
||||
CHROMEDIR=$MAGISKBIN/chromeos
|
||||
|
||||
SYSTEMLIB=/system/lib
|
||||
[ -d /system/lib64 ] && SYSTEMLIB=/system/lib64
|
||||
|
||||
# Default permissions
|
||||
umask 022
|
||||
|
||||
ui_print_wrapper() {
|
||||
type ui_print >/dev/null && ui_print "$1" || echo "$1"
|
||||
}
|
||||
|
||||
grep_prop() {
|
||||
REGEX="s/^$1=//p"
|
||||
shift
|
||||
FILES=$@
|
||||
if [ -z "$FILES" ]; then
|
||||
FILES='/system/build.prop'
|
||||
fi
|
||||
cat $FILES 2>/dev/null | sed -n "$REGEX" | head -n 1
|
||||
}
|
||||
|
||||
find_boot_image() {
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
for PARTITION in kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do
|
||||
BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || readlink /dev/block/platform/*/by-name/$PARTITION || readlink /dev/block/platform/*/*/by-name/$PARTITION`
|
||||
if [ ! -z "$BOOTIMAGE" ]; then break; fi
|
||||
done
|
||||
fi
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
FSTAB="/etc/recovery.fstab"
|
||||
[ ! -f "$FSTAB" ] && FSTAB="/etc/recovery.fstab.bak"
|
||||
[ -f "$FSTAB" ] && BOOTIMAGE=`grep -E '\b/boot\b' "$FSTAB" | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
|
||||
fi
|
||||
}
|
||||
|
||||
# Environments
|
||||
# Set permissions
|
||||
chmod -R 755 $CHROMEDIR/futility $MAGISKBIN 2>/dev/null
|
||||
# Temporary busybox for installation
|
||||
mkdir -p $TMPDIR/busybox
|
||||
$MAGISKBIN/busybox --install -s $TMPDIR/busybox
|
||||
rm -f $TMPDIR/busybox/su $TMPDIR/busybox/sh $TMPDIR/busybox/reboot
|
||||
PATH=$TMPDIR/busybox:$PATH
|
||||
# Load utility functions
|
||||
. $MAGISKBIN/util_functions.sh
|
||||
|
||||
# Find the boot image
|
||||
find_boot_image
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
ui_print_wrapper "! Unable to detect boot image"
|
||||
exit 1
|
||||
fi
|
||||
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
|
||||
|
||||
ui_print_wrapper "- Found Boot Image: $BOOTIMAGE"
|
||||
ui_print_wrap "- Found Boot Image: $BOOTIMAGE"
|
||||
|
||||
rm -rf $BOOTTMP 2>/dev/null
|
||||
mkdir -p $BOOTTMP
|
||||
cd $BOOTTMP
|
||||
cd $MAGISKBIN
|
||||
|
||||
ui_print_wrapper "- Unpacking boot image"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --unpack $BOOTIMAGE
|
||||
if [ $? -ne 0 ]; then
|
||||
ui_print_wrapper "! Unable to unpack boot image"
|
||||
exit 1
|
||||
fi
|
||||
ui_print_wrap "- Unpacking boot image"
|
||||
./magiskboot --unpack "$BOOTIMAGE"
|
||||
[ $? -ne 0 ] && abort_wrap "! Unable to unpack boot image"
|
||||
|
||||
# Update our previous backup to new format if exists
|
||||
if [ -f /data/stock_boot.img ]; then
|
||||
SHA1=`LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --sha1 /data/stock_boot.img | tail -n 1`
|
||||
SHA1=`./magiskboot --sha1 /data/stock_boot.img | tail -n 1`
|
||||
STOCKDUMP=/data/stock_boot_${SHA1}.img
|
||||
mv /data/stock_boot.img $STOCKDUMP
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --compress $STOCKDUMP
|
||||
./magiskboot --compress $STOCKDUMP
|
||||
fi
|
||||
|
||||
# Detect boot image state
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-test ramdisk.cpio
|
||||
./magiskboot --cpio-test ramdisk.cpio
|
||||
case $? in
|
||||
0 )
|
||||
ui_print_wrapper "! Magisk is not installed!"
|
||||
ui_print_wrapper "! Nothing to uninstall"
|
||||
0 ) # Stock boot
|
||||
ui_print_wrap "- Stock boot image detected!"
|
||||
ui_print_wrap "! Magisk is not installed!"
|
||||
exit
|
||||
;;
|
||||
1 )
|
||||
1 ) # Magisk patched
|
||||
ui_print_wrap "- Magisk patched image detected!"
|
||||
# Find SHA1 of stock boot image
|
||||
if [ -z $SHA1 ]; then
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-extract ramdisk.cpio init.magisk.rc init.magisk.rc
|
||||
SHA1=`grep_prop "# STOCKSHA1" init.magisk.rc`
|
||||
[ ! -z $SHA1 ] && STOCKDUMP=/data/stock_boot_${SHA1}.img
|
||||
rm -f init.magisk.rc
|
||||
./magiskboot --cpio-extract ramdisk.cpio init.magisk.rc init.magisk.rc.old
|
||||
SHA1=`grep_prop "# STOCKSHA1" init.magisk.rc.old`
|
||||
rm -f init.magisk.rc.old
|
||||
fi
|
||||
[ ! -z $SHA1 ] && STOCKDUMP=/data/stock_boot_${SHA1}.img
|
||||
if [ -f ${STOCKDUMP}.gz ]; then
|
||||
ui_print_wrapper "- Boot image backup found!"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
|
||||
ui_print_wrap "- Boot image backup found!"
|
||||
./magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
|
||||
else
|
||||
ui_print_wrapper "! Boot image backup unavailable"
|
||||
ui_print_wrapper "- Restoring ramdisk with backup"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-restore ramdisk.cpio
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --repack $BOOTIMAGE stock_boot.img
|
||||
ui_print_wrap "! Boot image backup unavailable"
|
||||
ui_print_wrap "- Restoring ramdisk with backup"
|
||||
./magiskboot --cpio-restore ramdisk.cpio
|
||||
./magiskboot --repack $BOOTIMAGE stock_boot.img
|
||||
fi
|
||||
;;
|
||||
2 )
|
||||
ui_print_wrapper "- SuperSU patched image detected"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-restore ramdisk.cpio
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --repack $BOOTIMAGE stock_boot.img
|
||||
2 ) # Other patched
|
||||
ui_print_wrap "! Boot image patched by other programs!"
|
||||
abort_wrap "! Cannot uninstall with this uninstaller"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Sign chromeos boot
|
||||
if [ -f chromeos ]; then
|
||||
echo > config
|
||||
echo > bootloader
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $CHROMEDIR/futility vbutil_kernel --pack stock_boot.img.signed --keyblock $CHROMEDIR/kernel.keyblock --signprivate $CHROMEDIR/kernel_data_key.vbprivk --version 1 --vmlinuz stock_boot.img --config config --arch arm --bootloader bootloader --flags 0x1
|
||||
rm -f stock_boot.img
|
||||
echo > empty
|
||||
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $CHROMEDIR/futility vbutil_kernel --pack stock_boot.img.signed \
|
||||
--keyblock $CHROMEDIR/kernel.keyblock --signprivate $CHROMEDIR/kernel_data_key.vbprivk \
|
||||
--version 1 --vmlinuz stock_boot.img --config empty --arch arm --bootloader empty --flags 0x1
|
||||
|
||||
rm -f empty stock_boot.img
|
||||
mv stock_boot.img.signed stock_boot.img
|
||||
fi
|
||||
|
||||
ui_print_wrapper "- Flashing stock/reverted image"
|
||||
[ ! -L "$BOOTIMAGE" ] && dd if=/dev/zero of=$BOOTIMAGE bs=4096 2>/dev/null
|
||||
dd if=stock_boot.img of=$BOOTIMAGE bs=4096
|
||||
ui_print_wrap "- Flashing stock/reverted image"
|
||||
if [ -L "$BOOTIMAGE" ]; then
|
||||
dd if=stock_boot.img of="$BOOTIMAGE" bs=4096
|
||||
else
|
||||
cat stock_boot.img /dev/zero | dd of="$BOOTIMAGE" bs=4096 >/dev/null 2>&1
|
||||
fi
|
||||
rm -f stock_boot.img
|
||||
|
||||
ui_print_wrapper "- Removing Magisk files"
|
||||
ui_print_wrap "- Removing Magisk files"
|
||||
rm -rf /cache/magisk.log /cache/last_magisk.log /cache/magiskhide.log /cache/.disable_magisk \
|
||||
/cache/magisk /cache/magisk_merge /cache/magisk_mount /cache/unblock /cache/magisk_uninstaller.sh \
|
||||
/data/Magisk.apk /data/magisk.apk /data/magisk.img /data/magisk_merge.img \
|
||||
/data/Magisk.apk /data/magisk.apk /data/magisk.img /data/magisk_merge.img /data/magisk_debug.log \
|
||||
/data/busybox /data/magisk /data/custom_ramdisk_patch.sh 2>/dev/null
|
||||
|
||||
$BOOTMODE && reboot
|
||||
|
||||
192
app/src/main/assets/util_functions.sh
Normal file
192
app/src/main/assets/util_functions.sh
Normal file
@@ -0,0 +1,192 @@
|
||||
##########################################################################################
|
||||
#
|
||||
# Magisk General Utility Functions
|
||||
# by topjohnwu
|
||||
#
|
||||
# Used in flash_script.sh, addon.d.sh, magisk module installers, and uninstaller
|
||||
#
|
||||
##########################################################################################
|
||||
|
||||
get_outfd() {
|
||||
readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null
|
||||
if [ "$?" -eq "0" ]; then
|
||||
OUTFD=0
|
||||
|
||||
for FD in `ls /proc/$$/fd`; do
|
||||
readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null
|
||||
if [ "$?" -eq "0" ]; then
|
||||
ps | grep " 3 $FD " | grep -v grep >/dev/null
|
||||
if [ "$?" -eq "0" ]; then
|
||||
OUTFD=$FD
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
ui_print() {
|
||||
if $BOOTMODE; then
|
||||
echo "$1"
|
||||
else
|
||||
echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD
|
||||
echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD
|
||||
fi
|
||||
}
|
||||
|
||||
getvar() {
|
||||
local VARNAME=$1
|
||||
local VALUE=$(eval echo \$"$VARNAME");
|
||||
for FILE in /dev/.magisk /data/.magisk /cache/.magisk /system/.magisk; do
|
||||
if [ -z "$VALUE" ]; then
|
||||
LINE=$(cat $FILE 2>/dev/null | grep "$VARNAME=")
|
||||
if [ ! -z "$LINE" ]; then
|
||||
VALUE=${LINE#*=}
|
||||
fi
|
||||
fi
|
||||
done
|
||||
eval $VARNAME=\$VALUE
|
||||
}
|
||||
|
||||
find_boot_image() {
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
for BLOCK in boot_a BOOT_A kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do
|
||||
BOOTIMAGE=`ls /dev/block/by-name/$BLOCK || ls /dev/block/platform/*/by-name/$BLOCK || ls /dev/block/platform/*/*/by-name/$BLOCK` 2>/dev/null
|
||||
[ ! -z $BOOTIMAGE ] && break
|
||||
done
|
||||
fi
|
||||
# Recovery fallback
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
for FSTAB in /etc/*fstab*; do
|
||||
BOOTIMAGE=`grep -E '\b/boot\b' $FSTAB | grep -v "#" | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
|
||||
[ ! -z $BOOTIMAGE ] && break
|
||||
done
|
||||
fi
|
||||
[ -L "$BOOTIMAGE" ] && BOOTIMAGE=`readlink $BOOTIMAGE`
|
||||
}
|
||||
|
||||
is_mounted() {
|
||||
if [ ! -z "$2" ]; then
|
||||
cat /proc/mounts | grep $1 | grep $2, >/dev/null
|
||||
else
|
||||
cat /proc/mounts | grep $1 >/dev/null
|
||||
fi
|
||||
return $?
|
||||
}
|
||||
|
||||
grep_prop() {
|
||||
REGEX="s/^$1=//p"
|
||||
shift
|
||||
FILES=$@
|
||||
if [ -z "$FILES" ]; then
|
||||
FILES='/system/build.prop'
|
||||
fi
|
||||
cat $FILES 2>/dev/null | sed -n "$REGEX" | head -n 1
|
||||
}
|
||||
|
||||
remove_system_su() {
|
||||
if [ -f /system/bin/su -o -f /system/xbin/su ] && [ ! -f /su/bin/su ]; then
|
||||
ui_print "! System installed root detected, mount rw :("
|
||||
mount -o rw,remount /system
|
||||
# SuperSU
|
||||
if [ -e /system/bin/.ext/.su ]; then
|
||||
mv -f /system/bin/app_process32_original /system/bin/app_process32 2>/dev/null
|
||||
mv -f /system/bin/app_process64_original /system/bin/app_process64 2>/dev/null
|
||||
mv -f /system/bin/install-recovery_original.sh /system/bin/install-recovery.sh 2>/dev/null
|
||||
cd /system/bin
|
||||
if [ -e app_process64 ]; then
|
||||
ln -sf app_process64 app_process
|
||||
else
|
||||
ln -sf app_process32 app_process
|
||||
fi
|
||||
fi
|
||||
rm -rf /system/.pin /system/bin/.ext /system/etc/.installed_su_daemon /system/etc/.has_su_daemon \
|
||||
/system/xbin/daemonsu /system/xbin/su /system/xbin/sugote /system/xbin/sugote-mksh /system/xbin/supolicy \
|
||||
/system/bin/app_process_init /system/bin/su /cache/su /system/lib/libsupol.so /system/lib64/libsupol.so \
|
||||
/system/su.d /system/etc/install-recovery.sh /system/etc/init.d/99SuperSUDaemon /cache/install-recovery.sh \
|
||||
/system/.supersu /cache/.supersu /data/.supersu \
|
||||
/system/app/Superuser.apk /system/app/SuperSU /cache/Superuser.apk 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
api_level_arch_detect() {
|
||||
API=`grep_prop ro.build.version.sdk`
|
||||
ABI=`grep_prop ro.product.cpu.abi | cut -c-3`
|
||||
ABI2=`grep_prop ro.product.cpu.abi2 | cut -c-3`
|
||||
ABILONG=`grep_prop ro.product.cpu.abi`
|
||||
|
||||
ARCH=arm
|
||||
IS64BIT=false
|
||||
if [ "$ABI" = "x86" ]; then ARCH=x86; fi;
|
||||
if [ "$ABI2" = "x86" ]; then ARCH=x86; fi;
|
||||
if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=true; fi;
|
||||
if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=true; fi;
|
||||
}
|
||||
|
||||
recovery_actions() {
|
||||
# TWRP bug fix
|
||||
mount -o bind /dev/urandom /dev/random
|
||||
# Temporarily block out all custom recovery binaries/libs
|
||||
mv /sbin /sbin_tmp
|
||||
# Add all possible library paths
|
||||
OLD_LD_PATH=$LD_LIBRARY_PATH
|
||||
$IS64BIT && export LD_LIBRARY_PATH=/system/lib64:/system/vendor/lib64 || export LD_LIBRARY_PATH=/system/lib:/system/vendor/lib
|
||||
}
|
||||
|
||||
recovery_cleanup() {
|
||||
mv /sbin_tmp /sbin
|
||||
# Clear LD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH=$OLD_LD_PATH
|
||||
ui_print "- Unmounting partitions"
|
||||
umount -l /system
|
||||
umount -l /vendor 2>/dev/null
|
||||
umount -l /dev/random
|
||||
}
|
||||
|
||||
abort() {
|
||||
ui_print "$1"
|
||||
mv /sbin_tmp /sbin 2>/dev/null
|
||||
exit 1
|
||||
}
|
||||
|
||||
set_perm() {
|
||||
chown $2:$3 $1 || exit 1
|
||||
chmod $4 $1 || exit 1
|
||||
if [ ! -z $5 ]; then
|
||||
chcon $5 $1 2>/dev/null
|
||||
else
|
||||
chcon 'u:object_r:system_file:s0' $1 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
set_perm_recursive() {
|
||||
find $1 -type d 2>/dev/null | while read dir; do
|
||||
set_perm $dir $2 $3 $4 $6
|
||||
done
|
||||
find $1 -type f 2>/dev/null | while read file; do
|
||||
set_perm $file $2 $3 $5 $6
|
||||
done
|
||||
}
|
||||
|
||||
mktouch() {
|
||||
mkdir -p ${1%/*}
|
||||
if [ -z "$2" ]; then
|
||||
touch $1
|
||||
else
|
||||
echo $2 > $1
|
||||
fi
|
||||
chmod 644 $1
|
||||
}
|
||||
|
||||
request_size_check() {
|
||||
reqSizeM=`du -s $1 | cut -f1`
|
||||
reqSizeM=$((reqSizeM / 1024 + 1))
|
||||
}
|
||||
|
||||
image_size_check() {
|
||||
SIZE="`$MAGISKBIN/magisk --imgsize $IMG`"
|
||||
curUsedM=`echo "$SIZE" | cut -d" " -f1`
|
||||
curSizeM=`echo "$SIZE" | cut -d" " -f2`
|
||||
curFreeM=$((curSizeM - curUsedM))
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.topjohnwu.magisk;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
@@ -13,13 +12,11 @@ import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.components.AboutCardRow;
|
||||
import com.topjohnwu.magisk.components.Activity;
|
||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||
import com.topjohnwu.magisk.utils.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -29,7 +26,7 @@ import butterknife.ButterKnife;
|
||||
|
||||
public class AboutActivity extends Activity {
|
||||
|
||||
private static final String DONATION_URL = "http://topjohnwu.github.io/donate";
|
||||
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";
|
||||
|
||||
@@ -45,10 +42,8 @@ public class AboutActivity extends Activity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String theme = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("theme", "");
|
||||
Logger.dev("AboutActivity: Theme is " + theme);
|
||||
if (getApplicationContext().isDarkTheme) {
|
||||
setTheme(R.style.AppTheme_Dark);
|
||||
setTheme(R.style.AppTheme_Transparent_Dark);
|
||||
}
|
||||
setContentView(R.layout.activity_about);
|
||||
ButterKnife.bind(this);
|
||||
@@ -135,18 +130,4 @@ public class AboutActivity extends Activity {
|
||||
setFloating();
|
||||
}
|
||||
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.ProcessMagiskZip;
|
||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class InstallFragment extends Fragment implements CallbackEvent.Listener<Void> {
|
||||
|
||||
|
||||
private static final String UNINSTALLER = "magisk_uninstaller.sh";
|
||||
|
||||
@BindView(R.id.current_version_title) TextView currentVersionTitle;
|
||||
@BindView(R.id.install_title) TextView installTitle;
|
||||
@BindView(R.id.block_spinner) Spinner spinner;
|
||||
@BindView(R.id.detect_bootimage) Button detectButton;
|
||||
@BindView(R.id.install_button) CardView installButton;
|
||||
@BindView(R.id.install_text) TextView installText;
|
||||
@BindView(R.id.uninstall_button) CardView uninstallButton;
|
||||
@BindView(R.id.keep_force_enc) CheckBox keepEncChkbox;
|
||||
@BindView(R.id.keep_verity) CheckBox keepVerityChkbox;
|
||||
|
||||
@OnClick(R.id.detect_bootimage)
|
||||
public void toAutoDetect() {
|
||||
if (magiskManager.bootBlock != null) {
|
||||
spinner.setSelection(0);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.install_button)
|
||||
public void install() {
|
||||
String bootImage = null;
|
||||
if (magiskManager.blockList != null) {
|
||||
int idx = spinner.getSelectedItemPosition();
|
||||
if (magiskManager.bootBlock != null) {
|
||||
if (idx > 0) {
|
||||
bootImage = magiskManager.blockList.get(idx - 1);
|
||||
}
|
||||
} else {
|
||||
if (idx > 0) {
|
||||
bootImage = magiskManager.blockList.get(idx - 1);
|
||||
} else {
|
||||
SnackbarMaker.make(getActivity(), R.string.manual_boot_image, Snackbar.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
}
|
||||
final String finalBootImage = bootImage;
|
||||
String filename = "Magisk-v" + magiskManager.remoteMagiskVersion + ".zip";
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(getString(R.string.repo_install_title, getString(R.string.magisk)))
|
||||
.setMessage(getString(R.string.repo_install_msg, filename))
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(Shell.rootAccess() ? R.string.install : R.string.download,
|
||||
(dialogInterface, i) -> Utils.dlAndReceive(
|
||||
getActivity(),
|
||||
new DownloadReceiver() {
|
||||
private String boot = finalBootImage;
|
||||
private boolean enc = keepEncChkbox.isChecked();
|
||||
private boolean verity = keepVerityChkbox.isChecked();
|
||||
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
new ProcessMagiskZip(getActivity(), uri, boot, enc, verity).exec();
|
||||
}
|
||||
},
|
||||
magiskManager.magiskLink,
|
||||
Utils.getLegalFilename(filename)))
|
||||
.setNeutralButton(R.string.release_notes, (dialog, which) -> {
|
||||
magiskManager.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(magiskManager.releaseNoteLink)));
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@OnClick(R.id.uninstall_button)
|
||||
public void uninstall() {
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.uninstall_magisk_title)
|
||||
.setMessage(R.string.uninstall_magisk_msg)
|
||||
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
|
||||
try {
|
||||
InputStream in = magiskManager.getAssets().open(UNINSTALLER);
|
||||
File uninstaller = new File(magiskManager.getCacheDir(), UNINSTALLER);
|
||||
FileOutputStream out = new FileOutputStream(uninstaller);
|
||||
byte[] bytes = new byte[1024];
|
||||
int read;
|
||||
while ((read = in.read(bytes)) != -1) {
|
||||
out.write(bytes, 0, read);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
ProgressDialog progress = new ProgressDialog(getActivity());
|
||||
progress.setTitle(R.string.reboot);
|
||||
progress.show();
|
||||
new CountDownTimer(5000, 1000) {
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
progress.setMessage(getString(R.string.reboot_countdown, millisUntilFinished / 1000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
progress.setMessage(getString(R.string.reboot_countdown, 0));
|
||||
Shell.su(true, "mv -f " + uninstaller + " /cache/" + UNINSTALLER,
|
||||
"reboot");
|
||||
}
|
||||
}.start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private Unbinder unbinder;
|
||||
private MagiskManager magiskManager;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_install, container, false);
|
||||
unbinder = ButterKnife.bind(this, v);
|
||||
magiskManager = getApplication();
|
||||
if (magiskManager.magiskVersion < 0) {
|
||||
currentVersionTitle.setText(getString(R.string.current_magisk_title, getString(R.string.version_none)));
|
||||
} else {
|
||||
currentVersionTitle.setText(getString(R.string.current_magisk_title, "v" + magiskManager.magiskVersionString));
|
||||
}
|
||||
installTitle.setText(getString(R.string.install_magisk_title, "v" + String.format(Locale.US, "%.1f", magiskManager.remoteMagiskVersion)));
|
||||
|
||||
updateUI();
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrigger(CallbackEvent<Void> event) {
|
||||
updateUI();
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
if (magiskManager.blockList == null || !Shell.rootAccess()) {
|
||||
uninstallButton.setVisibility(View.GONE);
|
||||
installText.setText(R.string.download);
|
||||
detectButton.setEnabled(false);
|
||||
keepEncChkbox.setEnabled(false);
|
||||
keepVerityChkbox.setEnabled(false);
|
||||
spinner.setEnabled(false);
|
||||
} else {
|
||||
uninstallButton.setVisibility(magiskManager.magiskVersion > 10.3 ? View.VISIBLE : View.GONE);
|
||||
installText.setText(R.string.download_install);
|
||||
detectButton.setEnabled(true);
|
||||
keepEncChkbox.setEnabled(true);
|
||||
keepVerityChkbox.setEnabled(true);
|
||||
spinner.setEnabled(true);
|
||||
|
||||
List<String> items = new ArrayList<>();
|
||||
if (magiskManager.bootBlock != null) {
|
||||
items.add(getString(R.string.auto_detect, magiskManager.bootBlock));
|
||||
} else {
|
||||
items.add(getString(R.string.cannot_auto_detect));
|
||||
}
|
||||
items.addAll(magiskManager.blockList);
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
|
||||
android.R.layout.simple_spinner_item, items);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
toAutoDetect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
getActivity().setTitle(R.string.install);
|
||||
magiskManager.blockDetectionDone.register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
magiskManager.blockDetectionDone.unRegister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
unbinder.unbind();
|
||||
}
|
||||
}
|
||||
@@ -31,14 +31,14 @@ public class LogFragment extends Fragment {
|
||||
|
||||
TabFragmentAdapter adapter = new TabFragmentAdapter(getChildFragmentManager());
|
||||
|
||||
adapter.addTab(new MagiskLogFragment(), getString(R.string.magisk));
|
||||
|
||||
if (getApplication().isSuClient) {
|
||||
adapter.addTab(new SuLogFragment(), getString(R.string.superuser));
|
||||
tab.setupWithViewPager(viewPager);
|
||||
tab.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
adapter.addTab(new MagiskLogFragment(), getString(R.string.magisk));
|
||||
|
||||
viewPager.setAdapter(adapter);
|
||||
|
||||
return v;
|
||||
|
||||
509
app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java
Normal file
509
app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,7 @@ import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.SerialTask;
|
||||
import com.topjohnwu.magisk.asyncs.RootTask;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
@@ -127,14 +127,14 @@ public class MagiskLogFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
public class LogManager extends SerialTask<Object, Void, Object> {
|
||||
private class LogManager extends RootTask<Object, Void, Object> {
|
||||
|
||||
int mode;
|
||||
File targetFile;
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
@Override
|
||||
protected Object doInBackground(Object... params) {
|
||||
protected Object doInRoot(Object... params) {
|
||||
mode = (int) params[0];
|
||||
switch (mode) {
|
||||
case 0:
|
||||
|
||||
@@ -5,13 +5,14 @@ import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.SparseArray;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.module.Module;
|
||||
import com.topjohnwu.magisk.module.Repo;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
import com.topjohnwu.magisk.utils.SafetyNetHelper;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.ValueSortedMap;
|
||||
@@ -22,10 +23,14 @@ import java.util.List;
|
||||
public class MagiskManager extends Application {
|
||||
|
||||
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
|
||||
public static final String MAGISK_HIDE_PATH = "/magisk/.core/magiskhide/";
|
||||
public static final String TMP_FOLDER_PATH = "/dev/tmp";
|
||||
public static final String MAGISK_PATH = "/magisk";
|
||||
public static final String UNINSTALLER = "magisk_uninstaller.sh";
|
||||
public static final String UTIL_FUNCTIONS= "util_functions.sh";
|
||||
public static final String INTENT_SECTION = "section";
|
||||
public static final String BUSYBOX_VERSION = "1.26.2";
|
||||
public static final String MAGISKHIDE_PROP = "persist.magisk.hide";
|
||||
public static final String DISABLE_INDICATION_PROP = "ro.magisk.disable";
|
||||
|
||||
// Events
|
||||
public final CallbackEvent<Void> blockDetectionDone = new CallbackEvent<>();
|
||||
@@ -35,20 +40,22 @@ public class MagiskManager extends Application {
|
||||
public final CallbackEvent<Void> repoLoadDone = new CallbackEvent<>();
|
||||
public final CallbackEvent<Void> updateCheckDone = new CallbackEvent<>();
|
||||
public final CallbackEvent<Void> safetyNetDone = new CallbackEvent<>();
|
||||
public final SparseArray<CallbackEvent<Policy>> uidSuRequest = new SparseArray<>();
|
||||
|
||||
// Info
|
||||
public double magiskVersion;
|
||||
public String magiskVersionString;
|
||||
public double remoteMagiskVersion = -1;
|
||||
public int magiskVersionCode = -1;
|
||||
public String remoteMagiskVersionString;
|
||||
public int remoteMagiskVersionCode = -1;
|
||||
public String magiskLink;
|
||||
public String releaseNoteLink;
|
||||
public int SNCheckResult = -1;
|
||||
public String remoteManagerVersionString;
|
||||
public int remoteManagerVersionCode = -1;
|
||||
public String managerLink;
|
||||
public SafetyNetHelper.Result SNCheckResult;
|
||||
public String bootBlock = null;
|
||||
public boolean isSuClient = false;
|
||||
public String suVersion = null;
|
||||
public boolean disabled;
|
||||
public boolean magiskHideStarted;
|
||||
|
||||
// Data
|
||||
public ValueSortedMap<String, Repo> repoMap;
|
||||
@@ -64,13 +71,18 @@ public class MagiskManager extends Application {
|
||||
public boolean magiskHide;
|
||||
public boolean isDarkTheme;
|
||||
public boolean updateNotification;
|
||||
public boolean suReauth;
|
||||
public int suRequestTimeout;
|
||||
public int suLogTimeout = 14;
|
||||
public int suAccessState;
|
||||
public int multiuserMode;
|
||||
public int suResponseType;
|
||||
public int suNotificationType;
|
||||
public int suNamespaceMode;
|
||||
|
||||
// Global resources
|
||||
public SharedPreferences prefs;
|
||||
public SuDatabaseHelper suDB;
|
||||
|
||||
private static Handler mHandler = new Handler();
|
||||
|
||||
@@ -90,80 +102,103 @@ public class MagiskManager extends Application {
|
||||
|
||||
public void init() {
|
||||
isDarkTheme = prefs.getBoolean("dark_theme", false);
|
||||
devLogging = prefs.getBoolean("developer_logging", false);
|
||||
shellLogging = prefs.getBoolean("shell_logging", false);
|
||||
magiskHide = prefs.getBoolean("magiskhide", false);
|
||||
if (BuildConfig.DEBUG) {
|
||||
devLogging = prefs.getBoolean("developer_logging", false);
|
||||
shellLogging = prefs.getBoolean("shell_logging", false);
|
||||
} else {
|
||||
devLogging = false;
|
||||
shellLogging = false;
|
||||
}
|
||||
magiskHide = prefs.getBoolean("magiskhide", true);
|
||||
updateNotification = prefs.getBoolean("notification", true);
|
||||
initSU();
|
||||
// Always start a new root shell manually, just for safety
|
||||
Shell.init();
|
||||
updateMagiskInfo();
|
||||
initSuAccess();
|
||||
initSuConfigs();
|
||||
// Initialize busybox
|
||||
File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox");
|
||||
if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) {
|
||||
busybox.getParentFile().mkdirs();
|
||||
Shell.su(
|
||||
"cp -f " + new File(getApplicationInfo().nativeLibraryDir, "libbusybox.so") + " " + busybox,
|
||||
"chmod -R 755 " + busybox.getParent(),
|
||||
busybox + " --install -s " + busybox.getParent()
|
||||
);
|
||||
}
|
||||
// Initialize prefs
|
||||
prefs.edit()
|
||||
.putBoolean("dark_theme", isDarkTheme)
|
||||
.putBoolean("magiskhide", magiskHide)
|
||||
.putBoolean("notification", updateNotification)
|
||||
.putBoolean("busybox", Utils.commandExists("busybox"))
|
||||
.putBoolean("hosts", new File("/magisk/.core/hosts").exists())
|
||||
.putBoolean("disable", Utils.itemExist(MAGISK_DISABLE_FILE))
|
||||
.putBoolean("su_reauth", suReauth)
|
||||
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
|
||||
.putString("su_auto_response", String.valueOf(suResponseType))
|
||||
.putString("su_notification", String.valueOf(suNotificationType))
|
||||
.putString("su_access", String.valueOf(suAccessState))
|
||||
.putString("multiuser_mode", String.valueOf(multiuserMode))
|
||||
.putString("mnt_ns", String.valueOf(suNamespaceMode))
|
||||
.putString("busybox_version", BUSYBOX_VERSION)
|
||||
.apply();
|
||||
// Add busybox to PATH
|
||||
Shell.su("PATH=$PATH:" + busybox.getParent());
|
||||
}
|
||||
|
||||
public void initSuConfigs() {
|
||||
public void initSUConfig() {
|
||||
suDB = new SuDatabaseHelper(this);
|
||||
suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
|
||||
suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
|
||||
suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
|
||||
suReauth = prefs.getBoolean("su_reauth", false);
|
||||
}
|
||||
|
||||
public void initSuAccess() {
|
||||
public void initSU() {
|
||||
// Create the app data directory, so su binary can work properly
|
||||
new File(getApplicationInfo().dataDir).mkdirs();
|
||||
|
||||
initSUConfig();
|
||||
|
||||
List<String> ret = Shell.sh("su -v");
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
suVersion = ret.get(0);
|
||||
isSuClient = suVersion.toUpperCase().contains("MAGISK");
|
||||
}
|
||||
if (isSuClient) {
|
||||
ret = Shell.sh("getprop persist.sys.root_access");
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
suAccessState = Integer.parseInt(ret.get(0));
|
||||
} else {
|
||||
Shell.su(true, "setprop persist.sys.root_access 3");
|
||||
suAccessState = 3;
|
||||
}
|
||||
suAccessState = suDB.getSettings(SuDatabaseHelper.ROOT_ACCESS, 3);
|
||||
multiuserMode = suDB.getSettings(SuDatabaseHelper.MULTIUSER_MODE, 0);
|
||||
suNamespaceMode = suDB.getSettings(SuDatabaseHelper.MNT_NS, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateMagiskInfo() {
|
||||
List<String> ret = Shell.sh("getprop magisk.version");
|
||||
List<String> ret;
|
||||
ret = Shell.sh("magisk -v");
|
||||
if (!Utils.isValidShellResponse(ret)) {
|
||||
magiskVersion = -1;
|
||||
} else {
|
||||
try {
|
||||
magiskVersionString = ret.get(0);
|
||||
magiskVersion = Double.parseDouble(ret.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
// Custom version don't need to receive updates
|
||||
magiskVersion = Double.POSITIVE_INFINITY;
|
||||
ret = Shell.sh("getprop magisk.version");
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
try {
|
||||
magiskVersionString = ret.get(0);
|
||||
magiskVersionCode = (int) Double.parseDouble(ret.get(0)) * 10;
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
} else {
|
||||
magiskVersionString = ret.get(0).split(":")[0];
|
||||
ret = Shell.sh("magisk -V");
|
||||
try {
|
||||
magiskVersionCode = Integer.parseInt(ret.get(0));
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
ret = Shell.sh("getprop ro.magisk.disable");
|
||||
ret = Shell.sh("getprop " + DISABLE_INDICATION_PROP);
|
||||
try {
|
||||
disabled = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
|
||||
} catch (NumberFormatException e) {
|
||||
disabled = false;
|
||||
}
|
||||
ret = Shell.sh("getprop persist.magisk.hide");
|
||||
ret = Shell.sh("getprop " + MAGISKHIDE_PROP);
|
||||
try {
|
||||
magiskHideStarted = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
|
||||
magiskHide = !Utils.isValidShellResponse(ret) || Integer.parseInt(ret.get(0)) != 0;
|
||||
} catch (NumberFormatException e) {
|
||||
magiskHideStarted = false;
|
||||
}
|
||||
|
||||
if (magiskHideStarted) {
|
||||
magiskHide = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.view.View;
|
||||
import com.topjohnwu.magisk.components.Activity;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
@@ -90,18 +91,6 @@ public class MainActivity extends Activity
|
||||
checkHideSection();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
navigate(savedInstanceState.getInt(MagiskManager.INTENT_SECTION, R.id.status));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(MagiskManager.INTENT_SECTION, mDrawerItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
getApplicationContext().reloadMainActivity.unRegister(this);
|
||||
@@ -110,10 +99,13 @@ public class MainActivity extends Activity
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (drawer.isDrawerOpen(navigationView))
|
||||
if (drawer.isDrawerOpen(navigationView)) {
|
||||
drawer.closeDrawer(navigationView);
|
||||
else
|
||||
} else if (mDrawerItem != R.id.magisk) {
|
||||
navigate(R.id.magisk);
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,30 +121,27 @@ public class MainActivity extends Activity
|
||||
recreate();
|
||||
}
|
||||
|
||||
private void checkHideSection() {
|
||||
public void checkHideSection() {
|
||||
Menu menu = navigationView.getMenu();
|
||||
menu.findItem(R.id.magiskhide).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersion >= 8
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 1300
|
||||
&& prefs.getBoolean("magiskhide", false));
|
||||
menu.findItem(R.id.modules).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersion >= 4);
|
||||
menu.findItem(R.id.downloads).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersion >= 4);
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 0);
|
||||
menu.findItem(R.id.downloads).setVisible(Utils.checkNetworkStatus(this) &&
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 0);
|
||||
menu.findItem(R.id.log).setVisible(Shell.rootAccess());
|
||||
menu.findItem(R.id.superuser).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().isSuClient);
|
||||
menu.findItem(R.id.install).setVisible(getApplicationContext().remoteMagiskVersion > 0);
|
||||
}
|
||||
|
||||
public void navigate(String item) {
|
||||
int itemId = R.id.status;
|
||||
int itemId = R.id.magisk;
|
||||
if (item != null) {
|
||||
switch (item) {
|
||||
case "status":
|
||||
itemId = R.id.status;
|
||||
break;
|
||||
case "magisk":
|
||||
case "install":
|
||||
itemId = R.id.install;
|
||||
itemId = R.id.magisk;
|
||||
break;
|
||||
case "superuser":
|
||||
itemId = R.id.superuser;
|
||||
@@ -185,11 +174,8 @@ public class MainActivity extends Activity
|
||||
mDrawerItem = itemId;
|
||||
navigationView.setCheckedItem(itemId);
|
||||
switch (itemId) {
|
||||
case R.id.status:
|
||||
displayFragment(new StatusFragment(), "status", true);
|
||||
break;
|
||||
case R.id.install:
|
||||
displayFragment(new InstallFragment(), "install", true);
|
||||
case R.id.magisk:
|
||||
displayFragment(new MagiskFragment(), "magisk", true);
|
||||
break;
|
||||
case R.id.superuser:
|
||||
displayFragment(new SuperuserFragment(), "superuser", true);
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -12,7 +13,6 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.github.clans.fab.FloatingActionButton;
|
||||
import com.topjohnwu.magisk.adapters.ModulesAdapter;
|
||||
import com.topjohnwu.magisk.asyncs.FlashZip;
|
||||
import com.topjohnwu.magisk.asyncs.LoadModules;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,15 +6,15 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||
import com.topjohnwu.magisk.asyncs.GetBootBlocks;
|
||||
import com.topjohnwu.magisk.asyncs.LoadApps;
|
||||
import com.topjohnwu.magisk.asyncs.LoadModules;
|
||||
import com.topjohnwu.magisk.asyncs.LoadRepos;
|
||||
import com.topjohnwu.magisk.asyncs.MagiskHide;
|
||||
import com.topjohnwu.magisk.components.Activity;
|
||||
import com.topjohnwu.magisk.services.UpdateCheckService;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class SplashActivity extends Activity{
|
||||
|
||||
@@ -25,49 +25,34 @@ public class SplashActivity extends Activity{
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
MagiskManager magiskManager = getApplicationContext();
|
||||
|
||||
// Init the info and configs and root shell
|
||||
magiskManager.init();
|
||||
|
||||
// Initialize the update check service, notify every 3 hours
|
||||
if (!"install".equals(getIntent().getStringExtra(MagiskManager.INTENT_SECTION))) {
|
||||
ComponentName service = new ComponentName(magiskManager, UpdateCheckService.class);
|
||||
JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service)
|
||||
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
||||
.setPersisted(true)
|
||||
.setPeriodic(3 * 60 * 60 * 1000)
|
||||
.build();
|
||||
JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
||||
scheduler.schedule(jobInfo);
|
||||
}
|
||||
getApplicationContext().init();
|
||||
|
||||
// Now fire all async tasks
|
||||
new GetBootBlocks(this).exec();
|
||||
if (magiskManager.magiskHide && !magiskManager.disabled &&
|
||||
magiskManager.magiskVersion > 11 && !magiskManager.magiskHideStarted) {
|
||||
new MagiskHide().enable();
|
||||
}
|
||||
new LoadModules(this) {
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
super.onPostExecute(v);
|
||||
new LoadRepos(activity).exec();
|
||||
}
|
||||
}.exec();
|
||||
new LoadModules(this).setCallBack(() -> new LoadRepos(this).exec()).exec();
|
||||
new LoadApps(this).exec();
|
||||
new CheckUpdates(this, false){
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
super.onPostExecute(v);
|
||||
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);
|
||||
Intent intent = new Intent(magiskManager, MainActivity.class);
|
||||
if (section != null) {
|
||||
intent.putExtra(MagiskManager.INTENT_SECTION, section);
|
||||
}
|
||||
startActivity(intent);
|
||||
finish();
|
||||
|
||||
if (Utils.checkNetworkStatus(this)) {
|
||||
// Initialize the update check service, notify every 8 hours
|
||||
if (!TextUtils.equals("install", getIntent().getStringExtra(MagiskManager.INTENT_SECTION))) {
|
||||
ComponentName service = new ComponentName(this, UpdateCheckService.class);
|
||||
JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service)
|
||||
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
||||
.setPersisted(true)
|
||||
.setPeriodic(8 * 60 * 60 * 1000)
|
||||
.build();
|
||||
JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
||||
scheduler.schedule(jobInfo);
|
||||
}
|
||||
}.exec();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,6 @@ import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.adapters.SuLogAdapter;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.database.SuLogDatabaseHelper;
|
||||
import com.topjohnwu.magisk.superuser.SuLogEntry;
|
||||
|
||||
import java.util.List;
|
||||
@@ -28,7 +27,7 @@ public class SuLogFragment extends Fragment {
|
||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||
|
||||
private Unbinder unbinder;
|
||||
private SuLogDatabaseHelper dbHelper;
|
||||
private MagiskManager magiskManager;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -48,8 +47,7 @@ public class SuLogFragment extends Fragment {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_su_log, container, false);
|
||||
unbinder = ButterKnife.bind(this, v);
|
||||
|
||||
dbHelper = new SuLogDatabaseHelper(getActivity());
|
||||
magiskManager = getApplication();
|
||||
|
||||
updateList();
|
||||
|
||||
@@ -57,7 +55,7 @@ public class SuLogFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
List<SuLogEntry> logs = dbHelper.getLogList();
|
||||
List<SuLogEntry> logs = magiskManager.suDB.getLogList();
|
||||
|
||||
if (logs.size() == 0) {
|
||||
emptyRv.setVisibility(View.VISIBLE);
|
||||
@@ -76,7 +74,7 @@ public class SuLogFragment extends Fragment {
|
||||
updateList();
|
||||
return true;
|
||||
case R.id.menu_clear:
|
||||
dbHelper.clearLogs();
|
||||
magiskManager.suDB.clearLogs();
|
||||
updateList();
|
||||
return true;
|
||||
default:
|
||||
|
||||
@@ -11,7 +11,6 @@ import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.adapters.PolicyAdapter;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
|
||||
import java.util.List;
|
||||
@@ -33,15 +32,15 @@ public class SuperuserFragment extends Fragment {
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
|
||||
PackageManager pm = getActivity().getPackageManager();
|
||||
MagiskManager magiskManager = getApplication();
|
||||
|
||||
SuDatabaseHelper dbHelper = new SuDatabaseHelper(getActivity());
|
||||
List<Policy> policyList = dbHelper.getPolicyList(pm);
|
||||
List<Policy> policyList = magiskManager.suDB.getPolicyList(pm);
|
||||
|
||||
if (policyList.size() == 0) {
|
||||
emptyRv.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
} else {
|
||||
recyclerView.setAdapter(new PolicyAdapter(policyList, dbHelper, pm));
|
||||
recyclerView.setAdapter(new PolicyAdapter(policyList, magiskManager.suDB, pm));
|
||||
emptyRv.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.asyncs.SerialTask;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.module.Module;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
@@ -53,44 +52,31 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
||||
|
||||
holder.checkBox.setOnCheckedChangeListener(null);
|
||||
holder.checkBox.setChecked(module.isEnabled());
|
||||
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> new SerialTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
if (isChecked) {
|
||||
module.removeDisableFile();
|
||||
} else {
|
||||
module.createDisableFile();
|
||||
}
|
||||
return null;
|
||||
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
int snack;
|
||||
if (isChecked) {
|
||||
module.removeDisableFile();
|
||||
snack = R.string.disable_file_removed;
|
||||
} else {
|
||||
module.createDisableFile();
|
||||
snack = R.string.disable_file_created;
|
||||
}
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
});
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
int snack = isChecked ? R.string.disable_file_removed : R.string.disable_file_created;
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
holder.delete.setOnClickListener(v -> {
|
||||
boolean removed = module.willBeRemoved();
|
||||
int snack;
|
||||
if (removed) {
|
||||
module.deleteRemoveFile();
|
||||
snack = R.string.remove_file_deleted;
|
||||
} else {
|
||||
module.createRemoveFile();
|
||||
snack = R.string.remove_file_created;
|
||||
}
|
||||
}.exec());
|
||||
|
||||
holder.delete.setOnClickListener(v -> new SerialTask<Void, Void, Void>() {
|
||||
private final boolean removed = module.willBeRemoved();
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
if (removed) {
|
||||
module.deleteRemoveFile();
|
||||
} else {
|
||||
module.createRemoveFile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
int snack = removed ? R.string.remove_file_deleted : R.string.remove_file_created;
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
updateDeleteButton(holder, module);
|
||||
}
|
||||
}.exec());
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
updateDeleteButton(holder, module);
|
||||
});
|
||||
|
||||
if (module.isUpdated()) {
|
||||
holder.notice.setVisibility(View.VISIBLE);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk.adapters;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
@@ -65,6 +66,7 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
|
||||
new DownloadReceiver() {
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
Activity activity = (Activity) mContext;
|
||||
new ProcessRepoZip(activity, uri, true).exec();
|
||||
}
|
||||
},
|
||||
@@ -75,6 +77,7 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
|
||||
new DownloadReceiver() {
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
Activity activity = (Activity) mContext;
|
||||
new ProcessRepoZip(activity, uri, false).exec();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
package com.topjohnwu.magisk.adapters;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.RotateAnimation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.thoughtbot.expandablerecyclerview.ExpandableRecyclerViewAdapter;
|
||||
@@ -19,6 +15,7 @@ import com.thoughtbot.expandablerecyclerview.models.ExpandableGroup;
|
||||
import com.thoughtbot.expandablerecyclerview.viewholders.ChildViewHolder;
|
||||
import com.thoughtbot.expandablerecyclerview.viewholders.GroupViewHolder;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.components.ExpandableViewHolder;
|
||||
import com.topjohnwu.magisk.superuser.SuLogEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -90,7 +87,7 @@ public class SuLogAdapter {
|
||||
SuLogEntry logEntry = (SuLogEntry) group.getItems().get(childIndex);
|
||||
holder.setExpanded(expandList.contains(logEntry));
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
if (holder.mExpanded) {
|
||||
if (holder.getExpanded()) {
|
||||
holder.collapse();
|
||||
expandList.remove(logEntry);
|
||||
} else {
|
||||
@@ -150,92 +147,50 @@ public class SuLogAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper class
|
||||
static class LogViewHolder extends ChildViewHolder {
|
||||
|
||||
private InternalViewHolder expandableViewHolder;
|
||||
|
||||
@BindView(R.id.app_name) TextView appName;
|
||||
@BindView(R.id.action) TextView action;
|
||||
@BindView(R.id.time) TextView time;
|
||||
@BindView(R.id.fromPid) TextView fromPid;
|
||||
@BindView(R.id.toUid) TextView toUid;
|
||||
@BindView(R.id.command) TextView command;
|
||||
@BindView(R.id.expand_layout) LinearLayout expandLayout;
|
||||
|
||||
private ValueAnimator mAnimator;
|
||||
private boolean mExpanded = false;
|
||||
private static int expandHeight = 0;
|
||||
|
||||
public LogViewHolder(View itemView) {
|
||||
LogViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
expandLayout.getViewTreeObserver().addOnPreDrawListener(
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
expandableViewHolder = new InternalViewHolder(itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
if (expandHeight == 0) {
|
||||
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||
expandLayout.measure(widthSpec, heightSpec);
|
||||
expandHeight = expandLayout.getMeasuredHeight();
|
||||
}
|
||||
private class InternalViewHolder extends ExpandableViewHolder {
|
||||
|
||||
expandLayout.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
expandLayout.setVisibility(View.GONE);
|
||||
mAnimator = slideAnimator(0, expandHeight);
|
||||
return true;
|
||||
}
|
||||
InternalViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
});
|
||||
@Override
|
||||
public void setExpandLayout(View itemView) {
|
||||
expandLayout = itemView.findViewById(R.id.expand_layout);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getExpanded() {
|
||||
return expandableViewHolder.mExpanded;
|
||||
}
|
||||
|
||||
private void setExpanded(boolean expanded) {
|
||||
mExpanded = expanded;
|
||||
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
|
||||
layoutParams.height = expanded ? expandHeight : 0;
|
||||
expandLayout.setLayoutParams(layoutParams);
|
||||
expandLayout.setVisibility(expanded ? View.VISIBLE : View.GONE);
|
||||
expandableViewHolder.setExpanded(expanded);
|
||||
}
|
||||
|
||||
private void expand() {
|
||||
expandLayout.setVisibility(View.VISIBLE);
|
||||
mAnimator.start();
|
||||
mExpanded = true;
|
||||
expandableViewHolder.expand();
|
||||
}
|
||||
|
||||
private void collapse() {
|
||||
if (!mExpanded) return;
|
||||
int finalHeight = expandLayout.getHeight();
|
||||
ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
|
||||
mAnimator.addListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
expandLayout.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animator) {}
|
||||
});
|
||||
mAnimator.start();
|
||||
mExpanded = false;
|
||||
}
|
||||
|
||||
private ValueAnimator slideAnimator(int start, int end) {
|
||||
|
||||
ValueAnimator animator = ValueAnimator.ofInt(start, end);
|
||||
|
||||
animator.addUpdateListener(valueAnimator -> {
|
||||
int value = (Integer) valueAnimator.getAnimatedValue();
|
||||
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
|
||||
layoutParams.height = value;
|
||||
expandLayout.setLayoutParams(layoutParams);
|
||||
});
|
||||
return animator;
|
||||
expandableViewHolder.collapse();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.support.v7.app.NotificationCompat;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.SplashActivity;
|
||||
import com.topjohnwu.magisk.BuildConfig;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
|
||||
@@ -18,8 +11,8 @@ import org.json.JSONObject;
|
||||
|
||||
public class CheckUpdates extends ParallelTask<Void, Void, Void> {
|
||||
|
||||
private static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/updates/magisk_update.json";
|
||||
private static final int NOTIFICATION_ID = 1;
|
||||
private static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/magisk_update.json";
|
||||
|
||||
|
||||
private boolean showNotification = false;
|
||||
|
||||
@@ -38,35 +31,29 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
|
||||
try {
|
||||
JSONObject json = new JSONObject(jsonStr);
|
||||
JSONObject magisk = json.getJSONObject("magisk");
|
||||
magiskManager.remoteMagiskVersion = magisk.getDouble("versionCode");
|
||||
magiskManager.remoteMagiskVersionString = magisk.getString("version");
|
||||
magiskManager.remoteMagiskVersionCode = magisk.getInt("versionCode");
|
||||
magiskManager.magiskLink = magisk.getString("link");
|
||||
magiskManager.releaseNoteLink = magisk.getString("note");
|
||||
} catch (JSONException ignored) {
|
||||
}
|
||||
JSONObject manager = json.getJSONObject("app");
|
||||
magiskManager.remoteManagerVersionString = manager.getString("version");
|
||||
magiskManager.remoteManagerVersionCode = manager.getInt("versionCode");
|
||||
magiskManager.managerLink = manager.getString("link");
|
||||
} catch (JSONException ignored) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
if (magiskManager.magiskVersion < magiskManager.remoteMagiskVersion
|
||||
&& showNotification && magiskManager.updateNotification) {
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(magiskManager);
|
||||
builder.setSmallIcon(R.drawable.ic_magisk)
|
||||
.setContentTitle(magiskManager.getString(R.string.magisk_update_title))
|
||||
.setContentText(magiskManager.getString(R.string.magisk_update_available, magiskManager.remoteMagiskVersion))
|
||||
.setVibrate(new long[]{0, 100, 100, 100})
|
||||
.setAutoCancel(true);
|
||||
Intent intent = new Intent(magiskManager, SplashActivity.class);
|
||||
intent.putExtra(MagiskManager.INTENT_SECTION, "install");
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(magiskManager);
|
||||
stackBuilder.addParentStack(SplashActivity.class);
|
||||
stackBuilder.addNextIntent(intent);
|
||||
PendingIntent pendingIntent = stackBuilder.getPendingIntent(NOTIFICATION_ID, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setContentIntent(pendingIntent);
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) magiskManager.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(NOTIFICATION_ID, builder.build());
|
||||
if (showNotification && magiskManager.updateNotification) {
|
||||
if (magiskManager.magiskVersionCode < magiskManager.remoteMagiskVersionCode) {
|
||||
Utils.showMagiskUpdate(magiskManager);
|
||||
}
|
||||
if (BuildConfig.VERSION_CODE < magiskManager.remoteManagerVersionCode) {
|
||||
Utils.showManagerUpdate(magiskManager);
|
||||
}
|
||||
}
|
||||
magiskManager.updateCheckDone.trigger();
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
public class FlashZip extends RootTask<Void, String, Integer> {
|
||||
|
||||
private Uri mUri;
|
||||
private File mCachedFile, mScriptFile, mCheckFile;
|
||||
@@ -68,7 +68,7 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean unzipAndCheck() throws Exception {
|
||||
private boolean unzipAndCheck() throws Exception {
|
||||
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android");
|
||||
List<String> ret;
|
||||
ret = Utils.readFile(mCheckFile.getPath());
|
||||
@@ -96,7 +96,7 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(Void... voids) {
|
||||
protected Integer doInRoot(Void... voids) {
|
||||
Logger.dev("FlashZip Running... " + mFilename);
|
||||
List<String> ret;
|
||||
try {
|
||||
@@ -124,7 +124,6 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
// -1 = error, manual install; 0 = invalid zip; 1 = success
|
||||
@Override
|
||||
protected void onPostExecute(Integer result) {
|
||||
super.onPostExecute(result);
|
||||
progress.dismiss();
|
||||
switch (result) {
|
||||
case -1:
|
||||
@@ -138,6 +137,7 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
onSuccess();
|
||||
break;
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
protected void onSuccess() {
|
||||
|
||||
@@ -5,15 +5,17 @@ import android.app.Activity;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class GetBootBlocks extends SerialTask<Void, Void, Void> {
|
||||
public class GetBootBlocks extends RootTask<Void, Void, Void> {
|
||||
|
||||
public GetBootBlocks(Activity context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
magiskManager.blockList = Shell.su("ls /dev/block | grep mmc");
|
||||
protected Void doInRoot(Void... params) {
|
||||
magiskManager.blockList = Shell.su(
|
||||
"find /dev/block -type b -maxdepth 1 | grep -v -E \"loop|ram|dm-0\""
|
||||
);
|
||||
if (magiskManager.bootBlock == null) {
|
||||
magiskManager.bootBlock = Utils.detectBootImage();
|
||||
}
|
||||
@@ -23,5 +25,6 @@ public class GetBootBlocks extends SerialTask<Void, Void, Void> {
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
magiskManager.blockDetectionDone.trigger();
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@ import com.topjohnwu.magisk.utils.Logger;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.ValueSortedMap;
|
||||
|
||||
public class LoadModules extends SerialTask<Void, Void, Void> {
|
||||
public class LoadModules extends RootTask<Void, Void, Void> {
|
||||
|
||||
public LoadModules(Activity context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
protected Void doInRoot(Void... voids) {
|
||||
Logger.dev("LoadModules: Loading modules");
|
||||
|
||||
magiskManager.moduleMap = new ValueSortedMap<>();
|
||||
@@ -37,5 +37,6 @@ public class LoadModules extends SerialTask<Void, Void, Void> {
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
magiskManager.moduleLoadDone.trigger();
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,11 @@ package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
public class MagiskHide extends RootTask<Object, Void, Void> {
|
||||
|
||||
private boolean isList = false;
|
||||
|
||||
@@ -18,9 +17,9 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Object... params) {
|
||||
protected Void doInRoot(Object... params) {
|
||||
String command = (String) params[0];
|
||||
List<String> ret = Shell.su(MagiskManager.MAGISK_HIDE_PATH + command);
|
||||
List<String> ret = Shell.su("magiskhide --" + command);
|
||||
if (isList) {
|
||||
magiskManager.magiskHideList = ret;
|
||||
}
|
||||
@@ -32,6 +31,7 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
if (isList) {
|
||||
magiskManager.magiskHideDone.trigger();
|
||||
}
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
|
||||
public void add(CharSequence packageName) {
|
||||
@@ -43,17 +43,17 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
exec("enable; setprop persist.magisk.hide 1");
|
||||
exec("enable");
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
exec("disable; setprop persist.magisk.hide 0");
|
||||
exec("disable");
|
||||
}
|
||||
|
||||
public void list() {
|
||||
isList = true;
|
||||
if (magiskManager == null) return;
|
||||
exec("list");
|
||||
exec("ls");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,9 +7,12 @@ import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public abstract class ParallelTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
|
||||
|
||||
protected Activity activity;
|
||||
protected MagiskManager magiskManager;
|
||||
|
||||
private Runnable callback = null;
|
||||
|
||||
public ParallelTask() {}
|
||||
|
||||
public ParallelTask(Activity context) {
|
||||
@@ -17,8 +20,18 @@ public abstract class ParallelTask<Params, Progress, Result> extends AsyncTask<P
|
||||
magiskManager = Utils.getMagiskManager(context);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final void exec(Params... params) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void exec(Params... params) {
|
||||
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Result result) {
|
||||
if (callback != null) callback.run();
|
||||
}
|
||||
|
||||
public ParallelTask<Params, Progress, Result> setCallBack(Runnable next) {
|
||||
callback = next;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,9 @@ import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
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.ZipUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
||||
|
||||
@@ -38,26 +33,12 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
if (Shell.rootAccess()) {
|
||||
try {
|
||||
// We might not have busybox yet, unzip with Java
|
||||
// We shall have complete busybox after Magisk installation
|
||||
File tempdir = new File(magiskManager.getCacheDir(), "magisk");
|
||||
ZipUtils.unzip(magiskManager.getContentResolver().openInputStream(mUri), tempdir);
|
||||
// Running in parallel mode, open new shell
|
||||
Shell.su(true,
|
||||
"rm -f /dev/.magisk",
|
||||
(mBoot != null) ? "echo \"BOOTIMAGE=/dev/block/" + mBoot + "\" >> /dev/.magisk" : "",
|
||||
synchronized (Shell.lock) {
|
||||
Shell.su("rm -f /dev/.magisk",
|
||||
(mBoot != null) ? "echo \"BOOTIMAGE=" + mBoot + "\" >> /dev/.magisk" : "",
|
||||
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(mEnc) + "\" >> /dev/.magisk",
|
||||
"echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk",
|
||||
"mkdir -p " + MagiskManager.TMP_FOLDER_PATH,
|
||||
"cp -af " + tempdir + "/. " + MagiskManager.TMP_FOLDER_PATH + "/magisk",
|
||||
"mv -f " + tempdir + "/META-INF " + magiskManager.getCacheDir() + "/META-INF",
|
||||
"rm -rf " + tempdir
|
||||
"echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk"
|
||||
);
|
||||
} catch (Exception e) {
|
||||
Logger.error("ProcessMagiskZip: Error!");
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -68,29 +49,10 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
||||
protected void onPostExecute(Boolean result) {
|
||||
progressDialog.dismiss();
|
||||
if (result) {
|
||||
new FlashZip(activity, mUri) {
|
||||
@Override
|
||||
protected boolean unzipAndCheck() throws Exception {
|
||||
// Don't need to check, as it is downloaded in correct form
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
new SerialTask<Void, Void, Void>(activity) {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
Shell.su("setprop magisk.version "
|
||||
+ String.valueOf(magiskManager.remoteMagiskVersion));
|
||||
magiskManager.updateCheckDone.trigger();
|
||||
return null;
|
||||
}
|
||||
}.exec();
|
||||
super.onSuccess();
|
||||
}
|
||||
}.exec();
|
||||
new FlashZip(activity, mUri).exec();
|
||||
} else {
|
||||
Utils.showUriSnack(activity, mUri);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user