Compare commits

...

38 Commits

Author SHA1 Message Date
topjohnwu
cfe32f1a70 Update Magisk Manager changelogs 2018-09-20 22:34:09 -04:00
Taras
d877f5d5c6 update Ukrainian strings 2018-09-20 16:56:17 -04:00
yuchenlin
0ab6ffefb4 utils/misc.c: prevent file staying opened when function leaving
The utils function may be called in any situation, such as in daemon. We
should guarantee that all the resource got from this function released
normally.

Signed-off-by: yuchenlin <npes87184@gmail.com>
2018-09-20 16:55:48 -04:00
topjohnwu
a292a1d23a Cleanup and add new rules
Close #607
2018-09-20 16:55:16 -04:00
topjohnwu
3f87f6aee3 Fix output in Magisk Manager if no root exists 2018-09-20 16:21:22 -04:00
topjohnwu
04bcd145d3 Add a.a alias to BootSigner 2018-09-20 15:37:59 -04:00
topjohnwu
244e811291 Remove icon padding in preference screen
Courtesy of https://stackoverflow.com/a/51568782
2018-09-19 00:06:14 -04:00
topjohnwu
ac7467fb59 Optimize boot signing to use as little memory as possible 2018-09-18 23:48:21 -04:00
topjohnwu
2c0436216f Prevent null strings in modules/repos
Close #620, close #621
2018-09-18 10:04:12 -04:00
topjohnwu
017fbf267b Fix small theme config issue 2018-09-17 23:29:38 -04:00
topjohnwu
e6afbf2ec0 Force remove busybox from APK 2018-09-17 23:03:37 -04:00
topjohnwu
906b4aad9e New method of communication
Introduce a new communication method between Magisk and Magisk Manager.

Magisk used to hardcode classnames and send broadcast/start activities to
specific components. This new method makes no assumption of any class names,
so Magisk Manager can easily be fully obfuscated.

In addition, the new method connects Magisk and Magisk Manager with random
abstract Linux sockets instead of socket files in filesystems, bypassing
file system complexities (selinux, permissions and such)
2018-09-16 04:16:18 -04:00
topjohnwu
4cf8d41f6a Fix FlashActivity crash 2018-09-16 00:18:34 -04:00
topjohnwu
47c860142e Use ClassMaps to prevent errors 2018-09-16 00:08:13 -04:00
topjohnwu
2fba3f213b Use proper socket address length 2018-09-15 02:49:19 -04:00
topjohnwu
af7c6f9fce Fix FlashActivity crash 2018-09-15 01:45:10 -04:00
topjohnwu
78534deab6 Excessive obfuscation when building in release mode
Close #606
2018-09-14 23:00:39 -04:00
topjohnwu
6710314832 Allow all context to SIGCLD magisk
Fix #596
2018-09-11 11:04:51 -04:00
topjohnwu
0cd4fa6fa0 Simplify SignAPK code 2018-09-11 10:48:36 -04:00
topjohnwu
065949496e Migrate to AndroidX support library 2018-09-10 02:27:45 -04:00
topjohnwu
39c82576ae Prevent warning
Close #524
2018-09-09 12:36:42 -04:00
John Wu
37221a508d Update README.MD 2018-09-09 12:25:22 -04:00
John Wu
6b43a32a10 Delete repo_description.png 2018-09-09 10:41:02 -04:00
ImgBotApp
d7cd1ff142 [ImgBot] optimizes images
*Total -- 990.86kb -> 771.48kb (22.14%)

/docs/images/flashfire.png -- 223.55kb -> 153.39kb (31.39%)
/docs/images/repo_description.png -- 38.55kb -> 27.31kb (29.15%)
/docs/images/manager_reboot.png -- 147.43kb -> 111.50kb (24.37%)
/docs/images/install_inactive_slot.png -- 123.15kb -> 99.79kb (18.97%)
/docs/images/restore_img.png -- 134.17kb -> 109.22kb (18.59%)
/docs/images/disable_auto_ota.png -- 160.04kb -> 132.05kb (17.49%)
/docs/images/ota_done.png -- 163.97kb -> 138.22kb (15.71%)
2018-09-09 10:40:40 -04:00
Sandro Jäckel
659d947863 Updated German translations 2018-09-09 10:40:33 -04:00
Rom
39be7a6288 Update stub French translation 2018-09-09 00:38:47 -04:00
Rom
8ac976c579 Update French translation (#576) 2018-09-09 00:38:33 -04:00
Vladimír Kubala
70fd432c57 Update Slovak translation 2018-09-09 00:38:25 -04:00
Jonas Schubert
00135f2f49 updated full\res\values.de\strings.xml 2018-09-09 00:38:11 -04:00
Albert I
9b944bc29c Update Indonesian translations
Signed-off-by: Albert I <krascgq@outlook.co.id>
2018-09-09 00:38:02 -04:00
topjohnwu
d520b3d2a0 Request storage permission when patching boot images 2018-09-08 23:27:19 -04:00
topjohnwu
6f41d9855b Randomize service names
Fix Aniplex Game detections.
Close #502, close #513
2018-09-08 23:17:00 -04:00
topjohnwu
2d7c1da741 Better support for external config file 2018-09-06 14:25:35 -04:00
topjohnwu
c0f45b6b1e Add resetprop magic 2018-09-06 02:57:02 -04:00
topjohnwu
7a0025673c Use libsystemproperties in resetprop
Upstream to latest Android Pie
2018-09-06 02:57:02 -04:00
topjohnwu
ad7ec79903 Support custom config paths 2018-09-05 14:24:28 -04:00
topjohnwu
0543239cca Do not merge binaries if fake symlink 2018-09-01 11:15:05 -04:00
topjohnwu
ff3dad2457 Prevent upgrading database before upgrading to v17.0 2018-09-01 10:46:13 -04:00
174 changed files with 5350 additions and 3674 deletions

View File

@@ -1,7 +1,7 @@
# Magisk
[XDA Announcement Thread](https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445)
## Building Environment Requirements
1. Python 3.5+: run `build.py` script
2. Java Development Kit (JDK) 8: Compile Magisk Manager and sign zips
3. Latest Android SDK: set `ANDROID_HOME` environment variable to the path to Android SDK
@@ -9,10 +9,16 @@
5. (Windows Only) Python package Colorama: Install with `pip install colorama`, used for ANSI color codes
## Building Notes and Instructions
1. Building is supported on macOS, Linux, and Windows using the custom NDK: [FrankeNDK](https://github.com/topjohnwu/FrankeNDK).
2. Set configurations in `config.prop`. A sample file `config.prop.sample` is provided as an example.
3. Run `build.py` with argument `-h` to see the built-in help message. The `-h` option also works for each supported actions, e.g. `./build.py binary -h`
4. By default, `build.py` build binaries and Magisk Manager in debug mode. If you want to build Magisk Manager in release mode (via the `-r, --release` flag), you need a Java Keystore file `release-key.jks` (only `JKS` format is supported) to sign APKs and zips. For more information, check out [Google's Official Documentation](https://developer.android.com/studio/publish/app-signing.html#signing-manually).
1. Clone sources with submodules: `git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git`
2. Building is supported on macOS, Linux, and Windows. Official releases are built and tested with [FrankeNDK](https://github.com/topjohnwu/FrankeNDK); point `ANDROID_NDK_HOME` to FrankeNDK if you want to use it for compiling.
3. Set configurations in `config.prop`. A sample file `config.prop.sample` is provided as an example.
4. Run `build.py` with argument `-h` to see the built-in help message. The `-h` option also works for each supported actions, e.g. `./build.py binary -h`
5. By default, `build.py` build binaries and Magisk Manager in debug mode. If you want to build Magisk Manager in release mode (via the `-r, --release` flag), you need a Java Keystore file `release-key.jks` (only `JKS` format is supported) to sign APKs and zips. For more information, check out [Google's Official Documentation](https://developer.android.com/studio/publish/app-signing.html#signing-manually).
## Bug Reports
**Make sure to install the latest [Canary Build](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337) before reporting any bugs!** Please **DO NOT** report bugs that is already fixed upstream.
Follow the instructions in the [Canary Channel XDA Thread](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337), and report a bug either by opening an issue on GitHub or directly in the thread.
## Documentation
[Link to Documentation](docs/README.MD)

View File

@@ -1,7 +1,8 @@
apply plugin: 'com.android.application'
def configProps = new Properties()
configProps.load(new FileInputStream(rootProject.file('config.prop')))
def configPath = project.hasProperty('configPath') ? project.configPath : rootProject.file('config.prop')
configProps.load(new FileInputStream(configPath))
android {
compileSdkVersion rootProject.ext.compileSdkVersion
@@ -70,14 +71,12 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
fullImplementation project(':utils')
implementation "com.android.support:support-core-utils:${rootProject.ext.supportLibVersion}"
fullImplementation "com.android.support:preference-v7:${rootProject.ext.supportLibVersion}"
fullImplementation "com.android.support:recyclerview-v7:${rootProject.ext.supportLibVersion}"
fullImplementation "com.android.support:cardview-v7:${rootProject.ext.supportLibVersion}"
fullImplementation "com.android.support:design:${rootProject.ext.supportLibVersion}"
fullImplementation 'com.github.topjohnwu:libsu:2.0.1'
implementation "androidx.core:core:${rootProject.ext.androidXVersion}"
fullImplementation "androidx.preference:preference:${rootProject.ext.androidXVersion}"
fullImplementation "androidx.recyclerview:recyclerview:${rootProject.ext.androidXVersion}"
fullImplementation "androidx.cardview:cardview:${rootProject.ext.androidXVersion}"
fullImplementation "com.google.android.material:material:${rootProject.ext.androidXVersion}"
fullImplementation 'com.github.topjohnwu:libsu:2.0.2'
fullImplementation 'com.atlassian.commonmark:commonmark:0.11.0'
fullImplementation 'org.kamranzafar:jtar:2.3'
fullImplementation 'com.jakewharton:butterknife:8.8.1'
fullAnnotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

View File

@@ -16,19 +16,20 @@
# public *;
#}
# Don't obfuscate, we are open source anyway :)
-dontobfuscate
# BouncyCastle
-keep class org.bouncycastle.jcajce.provider.asymmetric.rsa.**SHA1** { *; }
-keep class org.bouncycastle.jcajce.provider.asymmetric.RSA** { *; }
-keep class org.bouncycastle.jcajce.provider.digest.SHA1** { *; }
-dontwarn javax.naming.**
# Gson
-keepattributes Signature
# Snet extention
-keepclassmembers class com.topjohnwu.magisk.utils.ISafetyNetHelper { *; }
# Strip logging
-assumenosideeffects class com.topjohnwu.magisk.utils.Logger {
public *** debug(...);
}
# Excessive obfuscation
-repackageclasses 'a'
-allowaccessmodification

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.topjohnwu.magisk">
<uses-permission android:name="android.permission.VIBRATE" />
@@ -8,15 +9,18 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".MagiskManager"
android:theme="@style/AppTheme">
android:name="a.q"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<!-- Activities -->
<activity
android:name=".MainActivity"
android:name="a.b"
android:configChanges="orientation|screenSize"
android:exported="true" />
<activity
android:name=".SplashActivity"
android:name="a.c"
android:configChanges="orientation|screenSize"
android:exported="true"
android:theme="@style/SplashTheme">
@@ -26,53 +30,68 @@
</intent-filter>
</activity>
<activity
android:name=".AboutActivity"
android:name="a.d"
android:theme="@style/AppTheme.StatusBar" />
<activity
android:name=".DonationActivity"
android:name="a.e"
android:theme="@style/AppTheme.StatusBar"/>
<activity
android:name=".FlashActivity"
android:name="a.f"
android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="nosensor"
android:theme="@style/AppTheme.StatusBar" />
<activity
android:name=".NoUIActivity"
android:name="a.g"
android:theme="@style/AppTheme.Translucent" />
<!-- Superuser -->
<activity
android:name=".superuser.RequestActivity"
android:name="a.p"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity="internal.superuser"
android:theme="@style/SuRequest" />
<activity
android:name=".superuser.RequestActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity="internal.superuser"
android:theme="@style/AppTheme.Translucent" />
<receiver android:name=".superuser.SuReceiver" />
<receiver android:name=".receivers.BootReceiver">
<!-- Receiver -->
<receiver android:name="a.h">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.PackageReceiver">
<receiver android:name="a.i">
<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" />
<receiver android:name=".receivers.RebootReceiver" />
<receiver android:name=".receivers.ShortcutReceiver">
<receiver android:name="a.j" />
<receiver android:name="a.k" />
<receiver android:name="a.l">
<intent-filter>
<action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>
<!-- Service -->
<service
android:name=".services.OnBootService"
android:name="a.m"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service
android:name=".services.UpdateCheckService"
android:name="a.n"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />

View File

@@ -0,0 +1,10 @@
package a;
import com.topjohnwu.magisk.utils.BootSigner;
import androidx.annotation.Keep;
@Keep
public class a extends BootSigner {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.MainActivity;
public class b extends MainActivity {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.SplashActivity;
public class c extends SplashActivity {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.AboutActivity;
public class d extends AboutActivity {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.DonationActivity;
public class e extends DonationActivity {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.FlashActivity;
public class f extends FlashActivity {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.receivers.BootReceiver;
public class h extends BootReceiver {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.receivers.PackageReceiver;
public class i extends PackageReceiver {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.receivers.ManagerUpdate;
public class j extends ManagerUpdate {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.receivers.RebootReceiver;
public class k extends RebootReceiver {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
public class l extends ShortcutReceiver {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.services.OnBootService;
public class m extends OnBootService {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.services.UpdateCheckService;
public class n extends UpdateCheckService {
/* stub */
}

View File

@@ -0,0 +1,22 @@
package a;
import android.content.Context;
import android.util.AttributeSet;
import com.topjohnwu.magisk.components.AboutCardRow;
public class o extends AboutCardRow {
/* stub */
public o(Context context) {
super(context);
}
public o(Context context, AttributeSet attrs) {
super(context, attrs);
}
public o(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.SuRequestActivity;
public class p extends SuRequestActivity {
/* stub */
}

View File

@@ -0,0 +1,7 @@
package a;
import com.topjohnwu.magisk.MagiskManager;
public class q extends MagiskManager {
/* stub */
}

View File

@@ -2,9 +2,6 @@ package com.topjohnwu.magisk;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.View;
@@ -15,18 +12,19 @@ import com.topjohnwu.magisk.utils.Utils;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
public class AboutActivity extends BaseActivity {
@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_translators) AboutCardRow appTranslators;
@BindView(R.id.app_source_code) AboutCardRow appSourceCode;
@BindView(R.id.support_thread) AboutCardRow supportThread;
@BindView(R.id.follow_twitter) AboutCardRow twitter;
Toolbar toolbar;
AboutCardRow appVersionInfo;
AboutCardRow appChangelog;
AboutCardRow appTranslators;
AboutCardRow appSourceCode;
AboutCardRow supportThread;
AboutCardRow twitter;
@Override
public int getDarkTheme() {
@@ -37,7 +35,7 @@ public class AboutActivity extends BaseActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
ButterKnife.bind(this);
ViewBinder.bind(this);
setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(view -> finish());

View File

@@ -57,6 +57,7 @@ public class Const {
public static final int REMOVE_LEGACY_LINK = 1630;
public static final int SEPOL_REFACTOR = 1640;
public static final int FIX_ENV = 1650;
public static final int DBVER_SIX = 17000;
}
public static class ID {
@@ -140,9 +141,6 @@ public class Const {
public static final int NAMESPACE_MODE_ISOLATE = 2;
public static final int NO_NOTIFICATION = 0;
public static final int NOTIFICATION_TOAST = 1;
public static final int NOTIFY_NORMAL_LOG = 0;
public static final int NOTIFY_USER_TOASTS = 1;
public static final int NOTIFY_USER_TO_OWNER = 2;
public static final int SU_PROMPT = 0;
public static final int SU_AUTO_DENY = 1;
public static final int SU_AUTO_ALLOW = 2;

View File

@@ -5,6 +5,14 @@ import android.os.Handler;
import android.os.Looper;
import android.util.Xml;
import com.topjohnwu.magisk.components.AboutCardRow;
import com.topjohnwu.magisk.receivers.BootReceiver;
import com.topjohnwu.magisk.receivers.ManagerUpdate;
import com.topjohnwu.magisk.receivers.PackageReceiver;
import com.topjohnwu.magisk.receivers.RebootReceiver;
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
import com.topjohnwu.magisk.services.OnBootService;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.FingerprintHelper;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell;
@@ -18,11 +26,14 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
public class Data {
// Global app instance
public static WeakReference<MagiskManager> weakApp;
public static Handler mainHandler = new Handler(Looper.getMainLooper());
public static Map<Class, Class> classMap = new HashMap<>();
// Current status
public static String magiskVersionString;
@@ -60,6 +71,26 @@ public class Data {
public static int updateChannel;
public static int repoOrder;
static {
classMap.put(MagiskManager.class, a.q.class);
classMap.put(MainActivity.class, a.b.class);
classMap.put(SplashActivity.class, a.c.class);
classMap.put(AboutActivity.class, a.d.class);
classMap.put(DonationActivity.class, a.e.class);
classMap.put(FlashActivity.class, a.f.class);
classMap.put(NoUIActivity.class, a.g.class);
classMap.put(BootReceiver.class, a.h.class);
classMap.put(PackageReceiver.class, a.i.class);
classMap.put(ManagerUpdate.class, a.j.class);
classMap.put(RebootReceiver.class, a.k.class);
classMap.put(ShortcutReceiver.class, a.l.class);
classMap.put(OnBootService.class, a.m.class);
classMap.put(UpdateCheckService.class, a.n.class);
classMap.put(AboutCardRow.class, a.o.class);
classMap.put(SuRequestActivity.class, a.p.class);
}
public static void loadMagiskInfo() {
try {
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0];

View File

@@ -2,22 +2,20 @@ package com.topjohnwu.magisk;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import com.topjohnwu.magisk.components.AboutCardRow;
import com.topjohnwu.magisk.components.BaseActivity;
import com.topjohnwu.magisk.utils.Utils;
import butterknife.BindView;
import butterknife.ButterKnife;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
public class DonationActivity extends BaseActivity {
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.paypal) AboutCardRow paypal;
@BindView(R.id.patreon) AboutCardRow patreon;
Toolbar toolbar;
AboutCardRow paypal;
AboutCardRow patreon;
@Override
public int getDarkTheme() {
@@ -28,7 +26,7 @@ public class DonationActivity extends BaseActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_donation);
ButterKnife.bind(this);
ViewBinder.bind(this);
setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(view -> finish());

View File

@@ -4,8 +4,6 @@ import android.Manifest;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
@@ -31,31 +29,27 @@ import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
public class FlashActivity extends BaseActivity {
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.txtLog) TextView flashLogs;
@BindView(R.id.button_panel) public LinearLayout buttonPanel;
@BindView(R.id.reboot) public Button reboot;
@BindView(R.id.scrollView) ScrollView sv;
Toolbar toolbar;
TextView flashLogs;
public LinearLayout buttonPanel;
public Button reboot;
ScrollView sv;
private List<String> logs;
@OnClick(R.id.no_thanks)
void dismiss() {
finish();
}
@OnClick(R.id.reboot)
void reboot() {
Shell.su("/system/bin/reboot").submit();
}
@OnClick(R.id.save_logs)
void saveLogs() {
runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> {
Calendar now = Calendar.getInstance();
@@ -88,7 +82,7 @@ public class FlashActivity extends BaseActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flash);
ButterKnife.bind(this);
ViewBinder.bind(this);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
if (ab != null) {
@@ -139,8 +133,9 @@ public class FlashActivity extends BaseActivity {
new InstallMagisk(this, console, logs, InstallMagisk.SECOND_SLOT_MODE).exec();
break;
case Const.Value.PATCH_BOOT:
new InstallMagisk(this, console, logs,
intent.getParcelableExtra(Const.Key.FLASH_SET_BOOT)).exec();
runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
() -> new InstallMagisk(this, console, logs,
intent.getParcelableExtra(Const.Key.FLASH_SET_BOOT)).exec());
break;
}
}

View File

@@ -3,17 +3,11 @@ package com.topjohnwu.magisk;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.google.android.material.navigation.NavigationView;
import com.topjohnwu.magisk.components.BaseActivity;
import com.topjohnwu.magisk.fragments.LogFragment;
import com.topjohnwu.magisk.fragments.MagiskFragment;
@@ -26,8 +20,12 @@ import com.topjohnwu.magisk.utils.Download;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.superuser.Shell;
import butterknife.BindView;
import butterknife.ButterKnife;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.widget.Toolbar;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends BaseActivity
implements NavigationView.OnNavigationItemSelectedListener, Topic.Subscriber {
@@ -36,9 +34,9 @@ public class MainActivity extends BaseActivity
private int mDrawerItem;
private static boolean fromShortcut = false;
@BindView(R.id.drawer_layout) DrawerLayout drawer;
@BindView(R.id.toolbar) public Toolbar toolbar;
@BindView(R.id.nav_view) public NavigationView navigationView;
public Toolbar toolbar;
DrawerLayout drawer;
NavigationView navigationView;
private float toolbarElevation;
@@ -50,13 +48,13 @@ public class MainActivity extends BaseActivity
@Override
protected void onCreate(final Bundle savedInstanceState) {
if (!mm.hasInit) {
startActivity(new Intent(this, SplashActivity.class));
startActivity(new Intent(this, Data.classMap.get(SplashActivity.class)));
finish();
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
ViewBinder.bind(this);
setSupportActionBar(toolbar);
@@ -112,11 +110,6 @@ public class MainActivity extends BaseActivity
return true;
}
@Override
public int[] getSubscribedTopics() {
return new int[] {Topic.RELOAD_ACTIVITY};
}
@Override
public void onPublish(int topic, Object[] result) {
recreate();
@@ -196,11 +189,11 @@ public class MainActivity extends BaseActivity
displayFragment(new SettingsFragment(), true);
break;
case R.id.app_about:
startActivity(new Intent(this, AboutActivity.class));
startActivity(new Intent(this, Data.classMap.get(AboutActivity.class)));
mDrawerItem = bak;
break;
case R.id.donation:
startActivity(new Intent(this, DonationActivity.class));
startActivity(new Intent(this, Data.classMap.get(DonationActivity.class)));
mDrawerItem = bak;
break;
}

View File

@@ -1,9 +1,9 @@
package com.topjohnwu.magisk;
import android.support.annotation.NonNull;
import com.topjohnwu.magisk.components.BaseActivity;
import androidx.annotation.NonNull;
public class NoUIActivity extends BaseActivity {
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

View File

@@ -44,7 +44,7 @@ public class SplashActivity extends BaseActivity {
}
// Setup shortcuts
sendBroadcast(new Intent(this, ShortcutReceiver.class));
sendBroadcast(new Intent(this, Data.classMap.get(ShortcutReceiver.class)));
if (Download.checkNetworkStatus(this)) {
// Fire update check
@@ -58,7 +58,7 @@ public class SplashActivity extends BaseActivity {
mm.hasInit = true;
Intent intent = new Intent(this, MainActivity.class);
Intent intent = new Intent(this, Data.classMap.get(MainActivity.class));
intent.putExtra(Const.Key.OPEN_SECTION, getIntent().getStringExtra(Const.Key.OPEN_SECTION));
intent.putExtra(BaseActivity.INTENT_PERM, getIntent().getStringExtra(BaseActivity.INTENT_PERM));
startActivity(intent);

View File

@@ -0,0 +1,258 @@
package com.topjohnwu.magisk;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.net.LocalSocketAddress;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.FileObserver;
import android.text.TextUtils;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.topjohnwu.magisk.components.BaseActivity;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.utils.FingerprintHelper;
import com.topjohnwu.magisk.utils.SuConnector;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import androidx.annotation.Nullable;
public class SuRequestActivity extends BaseActivity {
LinearLayout suPopup;
Spinner timeout;
ImageView appIcon;
TextView appNameView;
TextView packageNameView;
Button grant_btn;
Button deny_btn;
ImageView fingerprintImg;
TextView warning;
private SuConnector connector;
private Policy policy;
private CountDownTimer timer;
private FingerprintHelper fingerprintHelper;
class SuConnectorV1 extends SuConnector {
SuConnectorV1(String name) throws IOException {
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.FILESYSTEM));
new FileObserver(name) {
@Override
public void onEvent(int fileEvent, String path) {
if (fileEvent == FileObserver.DELETE_SELF) {
finish();
}
}
}.startWatching();
}
@Override
public void response() {
try (OutputStream out = getOutputStream()) {
out.write((policy.policy == Policy.ALLOW ? "socket:ALLOW" : "socket:DENY").getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SuConnectorV2 extends SuConnector {
SuConnectorV2(String name) throws IOException {
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.ABSTRACT));
}
@Override
public void response() {
try (DataOutputStream out = getOutputStream()) {
out.writeInt(policy.policy);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public int getDarkTheme() {
return R.style.SuRequest_Dark;
}
@Override
public void finish() {
if (timer != null)
timer.cancel();
if (fingerprintHelper != null)
fingerprintHelper.cancel();
super.finish();
}
@Override
public void onBackPressed() {
if (policy != null) {
handleAction(Policy.DENY);
} else {
finish();
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
PackageManager pm = getPackageManager();
mm.mDB.clearOutdated();
// Get policy
Intent intent = getIntent();
try {
connector = intent.getIntExtra("version", 1) == 1 ?
new SuConnectorV1(intent.getStringExtra("socket")) :
new SuConnectorV2(intent.getStringExtra("socket"));
Bundle bundle = connector.readSocketInput();
int uid = Integer.parseInt(bundle.getString("uid"));
policy = mm.mDB.getPolicy(uid);
if (policy == null) {
policy = new Policy(uid, pm);
}
} catch (IOException | PackageManager.NameNotFoundException e) {
e.printStackTrace();
finish();
return;
}
// Never allow com.topjohnwu.magisk (could be malware)
if (TextUtils.equals(policy.packageName, Const.ORIG_PKG_NAME)) {
finish();
return;
}
switch (Data.suResponseType) {
case Const.Value.SU_AUTO_DENY:
handleAction(Policy.DENY, 0);
return;
case Const.Value.SU_AUTO_ALLOW:
handleAction(Policy.ALLOW, 0);
return;
case Const.Value.SU_PROMPT:
default:
}
// If not interactive, response directly
if (policy.policy != Policy.INTERACTIVE) {
handleAction();
return;
}
setContentView(R.layout.activity_request);
ViewBinder.bind(this);
appIcon.setImageDrawable(policy.info.loadIcon(pm));
appNameView.setText(policy.appName);
packageNameView.setText(policy.packageName);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.allow_timeout, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
timeout.setAdapter(adapter);
timer = new CountDownTimer(Data.suRequestTimeout * 1000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
deny_btn.setText(getString(R.string.deny_with_str, "(" + millisUntilFinished / 1000 + ")"));
}
@Override
public void onFinish() {
deny_btn.setText(getString(R.string.deny_with_str, "(0)"));
handleAction(Policy.DENY);
}
};
boolean useFingerprint = Data.suFingerprint && FingerprintHelper.canUseFingerprint();
if (useFingerprint) {
try {
fingerprintHelper = new FingerprintHelper() {
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
warning.setText(errString);
}
@Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
warning.setText(helpString);
}
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
handleAction(Policy.ALLOW);
}
@Override
public void onAuthenticationFailed() {
warning.setText(R.string.auth_fail);
}
};
fingerprintHelper.authenticate();
} catch (Exception e) {
e.printStackTrace();
useFingerprint = false;
}
}
if (!useFingerprint) {
grant_btn.setOnClickListener(v -> {
handleAction(Policy.ALLOW);
timer.cancel();
});
grant_btn.requestFocus();
}
grant_btn.setVisibility(useFingerprint ? View.GONE : View.VISIBLE);
fingerprintImg.setVisibility(useFingerprint ? View.VISIBLE : View.GONE);
deny_btn.setOnClickListener(v -> {
handleAction(Policy.DENY);
timer.cancel();
});
suPopup.setOnClickListener(v -> cancelTimeout());
timeout.setOnTouchListener((v, event) -> cancelTimeout());
timer.start();
}
private boolean cancelTimeout() {
timer.cancel();
deny_btn.setText(getString(R.string.deny));
return false;
}
private void handleAction() {
connector.response();
finish();
}
private void handleAction(int action) {
handleAction(action, Const.Value.timeoutList[timeout.getSelectedItemPosition()]);
}
private void handleAction(int action, int time) {
policy.policy = action;
if (time >= 0) {
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
mm.mDB.addPolicy(policy);
}
handleAction();
}
}

View File

@@ -0,0 +1,293 @@
package com.topjohnwu.magisk;
import android.content.Context;
import android.view.View;
import com.topjohnwu.magisk.adapters.ApplicationAdapter;
import com.topjohnwu.magisk.adapters.ModulesAdapter;
import com.topjohnwu.magisk.adapters.PolicyAdapter;
import com.topjohnwu.magisk.adapters.ReposAdapter;
import com.topjohnwu.magisk.adapters.SuLogAdapter;
import com.topjohnwu.magisk.components.AboutCardRow;
import com.topjohnwu.magisk.components.CustomAlertDialog;
import com.topjohnwu.magisk.fragments.LogFragment;
import com.topjohnwu.magisk.fragments.MagiskFragment;
import com.topjohnwu.magisk.fragments.MagiskHideFragment;
import com.topjohnwu.magisk.fragments.MagiskLogFragment;
import com.topjohnwu.magisk.fragments.ModulesFragment;
import com.topjohnwu.magisk.fragments.ReposFragment;
import com.topjohnwu.magisk.fragments.SuLogFragment;
import com.topjohnwu.magisk.fragments.SuperuserFragment;
import androidx.core.content.ContextCompat;
public class ViewBinder {
public static void bind(MainActivity target) {
target.drawer = target.findViewById(R.id.drawer_layout);
target.toolbar = target.findViewById(R.id.toolbar);
target.navigationView = target.findViewById(R.id.nav_view);
}
public static void bind(AboutActivity target) {
target.toolbar = target.findViewById(R.id.toolbar);
target.appVersionInfo = target.findViewById(R.id.app_version_info);
target.appChangelog = target.findViewById(R.id.app_changelog);
target.appTranslators = target.findViewById(R.id.app_translators);
target.appSourceCode = target.findViewById(R.id.app_source_code);
target.supportThread = target.findViewById(R.id.support_thread);
target.twitter = target.findViewById(R.id.follow_twitter);
}
public static void bind(DonationActivity target) {
target.toolbar = target.findViewById(R.id.toolbar);
target.paypal = target.findViewById(R.id.paypal);
target.patreon = target.findViewById(R.id.patreon);
}
public static void bind(FlashActivity target) {
target.toolbar = target.findViewById(R.id.toolbar);
target.flashLogs = target.findViewById(R.id.txtLog);
target.buttonPanel = target.findViewById(R.id.button_panel);
target.sv = target.findViewById(R.id.scrollView);
target.reboot = target.findViewById(R.id.reboot);
target.reboot.setOnClickListener(v -> target.reboot());
target.findViewById(R.id.no_thanks).setOnClickListener(v -> target.finish());
target.findViewById(R.id.save_logs).setOnClickListener(v -> target.saveLogs());
}
public static void bind(SuRequestActivity target) {
target.suPopup = target.findViewById(R.id.su_popup);
target.timeout = target.findViewById(R.id.timeout);
target.appIcon = target.findViewById(R.id.app_icon);
target.appNameView = target.findViewById(R.id.app_name);
target.packageNameView = target.findViewById(R.id.package_name);
target.grant_btn = target.findViewById(R.id.grant_btn);
target.deny_btn = target.findViewById(R.id.deny_btn);
target.fingerprintImg = target.findViewById(R.id.fingerprint);
target.warning = target.findViewById(R.id.warning);
}
public static void bind(LogFragment target, View v) {
target.viewPager = v.findViewById(R.id.container);
target.tab = v.findViewById(R.id.tab);
}
public static void unbind(LogFragment target) {
target.viewPager = null;
target.tab = null;
}
public static void bind(MagiskFragment target, View v) {
target.mSwipeRefreshLayout = v.findViewById(R.id.swipeRefreshLayout);
target.coreOnlyNotice = v.findViewById(R.id.core_only_notice);
target.magiskUpdate = v.findViewById(R.id.magisk_update);
target.magiskUpdateIcon = v.findViewById(R.id.magisk_update_icon);
target.magiskUpdateText = v.findViewById(R.id.magisk_update_status);
target.magiskUpdateProgress = v.findViewById(R.id.magisk_update_progress);
target.magiskStatusIcon = v.findViewById(R.id.magisk_status_icon);
target.magiskVersionText = v.findViewById(R.id.magisk_version);
target.safetyNetCard = v.findViewById(R.id.safetyNet_card);
target.safetyNetRefreshIcon = v.findViewById(R.id.safetyNet_refresh);
target.safetyNetStatusText = v.findViewById(R.id.safetyNet_status);
target.safetyNetProgress = v.findViewById(R.id.safetyNet_check_progress);
target.expandLayout = v.findViewById(R.id.expand_layout);
target.ctsStatusIcon = v.findViewById(R.id.cts_status_icon);
target.ctsStatusText = v.findViewById(R.id.cts_status);
target.basicStatusIcon = v.findViewById(R.id.basic_status_icon);
target.basicStatusText = v.findViewById(R.id.basic_status);
target.installOptionCard = v.findViewById(R.id.install_option_card);
target.keepEncChkbox = v.findViewById(R.id.keep_force_enc);
target.keepVerityChkbox = v.findViewById(R.id.keep_verity);
target.installButton = v.findViewById(R.id.install_button);
target.installText = v.findViewById(R.id.install_text);
target.uninstallButton = v.findViewById(R.id.uninstall_button);
v.findViewById(R.id.safetyNet_title).setOnClickListener(v1 -> target.safetyNet());
v.findViewById(R.id.install_button).setOnClickListener(v1 -> target.install());
v.findViewById(R.id.uninstall_button).setOnClickListener(v1 -> target.uninstall());
Context ctx = target.getContext();
target.colorBad = ContextCompat.getColor(ctx, R.color.red500);
target.colorOK = ContextCompat.getColor(ctx, R.color.green500);
target.colorWarn = ContextCompat.getColor(ctx, R.color.yellow500);
target.colorNeutral = ContextCompat.getColor(ctx, R.color.grey500);
target.colorInfo = ContextCompat.getColor(ctx, R.color.blue500);
}
public static void unbind(MagiskFragment target) {
target.mSwipeRefreshLayout = null;
target.coreOnlyNotice = null;
target.magiskUpdate = null;
target.magiskUpdateIcon = null;
target.magiskUpdateText = null;
target.magiskUpdateProgress = null;
target.magiskStatusIcon = null;
target.magiskVersionText = null;
target.safetyNetCard = null;
target.safetyNetRefreshIcon = null;
target.safetyNetStatusText = null;
target.safetyNetProgress = null;
target.expandLayout = null;
target.ctsStatusIcon = null;
target.ctsStatusText = null;
target.basicStatusIcon = null;
target.basicStatusText = null;
target.installOptionCard = null;
target.keepEncChkbox = null;
target.keepVerityChkbox = null;
target.installButton = null;
target.installText = null;
target.uninstallButton = null;
View v = target.getView();
v.findViewById(R.id.safetyNet_title).setOnClickListener(null);
v.findViewById(R.id.install_button).setOnClickListener(null);
v.findViewById(R.id.uninstall_button).setOnClickListener(null);
}
public static void bind(MagiskHideFragment target, View v) {
target.mSwipeRefreshLayout = v.findViewById(R.id.swipeRefreshLayout);
target.recyclerView = v.findViewById(R.id.recyclerView);
}
public static void unbind(MagiskHideFragment target) {
target.mSwipeRefreshLayout = null;
target.recyclerView = null;
}
public static void bind(MagiskLogFragment target, View v) {
target.txtLog = v.findViewById(R.id.txtLog);
target.svLog = v.findViewById(R.id.svLog);
target.hsvLog = v.findViewById(R.id.hsvLog);
target.progressBar = v.findViewById(R.id.progressBar);
}
public static void unbind(MagiskLogFragment target) {
target.txtLog = null;
target.svLog = null;
target.hsvLog = null;
target.progressBar = null;
}
public static void bind(ModulesFragment target, View v) {
target.mSwipeRefreshLayout = v.findViewById(R.id.swipeRefreshLayout);
target.recyclerView = v.findViewById(R.id.recyclerView);
target.emptyRv = v.findViewById(R.id.empty_rv);
v.findViewById(R.id.fab).setOnClickListener(v1 -> target.selectFile());
}
public static void unbind(ModulesFragment target) {
target.mSwipeRefreshLayout = null;
target.recyclerView = null;
target.emptyRv = null;
View v = target.getView();
v.findViewById(R.id.fab).setOnClickListener(null);
}
public static void bind(ReposFragment target, View source) {
target.recyclerView = source.findViewById(R.id.recyclerView);
target.emptyRv = source.findViewById(R.id.empty_rv);
target.mSwipeRefreshLayout = source.findViewById(R.id.swipeRefreshLayout);
}
public static void unbind(ReposFragment target) {
target.recyclerView = null;
target.emptyRv = null;
target.mSwipeRefreshLayout = null;
}
public static void bind(SuLogFragment target, View source) {
target.emptyRv = source.findViewById(R.id.empty_rv);
target.recyclerView = source.findViewById(R.id.recyclerView);
}
public static void unbind(SuLogFragment target) {
target.emptyRv = null;
target.recyclerView = null;
}
public static void bind(SuperuserFragment target, View source) {
target.recyclerView = source.findViewById(R.id.recyclerView);
target.emptyRv = source.findViewById(R.id.empty_rv);
}
public static void unbind(SuperuserFragment target) {
target.emptyRv = null;
target.recyclerView = null;
}
public static void bind(CustomAlertDialog.ViewHolder target, View source) {
target.dialogLayout = source.findViewById(R.id.dialog_layout);
target.buttons = source.findViewById(R.id.button_panel);
target.messageView = source.findViewById(R.id.message);
target.negative = source.findViewById(R.id.negative);
target.positive = source.findViewById(R.id.positive);
target.neutral = source.findViewById(R.id.neutral);
}
public static void bind(AboutCardRow target, View source) {
target.mTitle = source.findViewById(android.R.id.title);
target.mSummary = source.findViewById(android.R.id.summary);
target.mIcon = source.findViewById(android.R.id.icon);
target.mView = source.findViewById(R.id.container);
}
public static void bind(ApplicationAdapter.ViewHolder target, View source) {
target.appIcon = source.findViewById(R.id.app_icon);
target.appName = source.findViewById(R.id.app_name);
target.appPackage = source.findViewById(R.id.package_name);
target.checkBox = source.findViewById(R.id.checkbox);
}
public static void bind(ModulesAdapter.ViewHolder target, View source) {
target.title = source.findViewById(R.id.title);
target.versionName = source.findViewById(R.id.version_name);
target.description = source.findViewById(R.id.description);
target.notice = source.findViewById(R.id.notice);
target.checkBox = source.findViewById(R.id.checkbox);
target.author = source.findViewById(R.id.author);
target.delete = source.findViewById(R.id.delete);
}
public static void bind(PolicyAdapter.ViewHolder target, View source) {
target.appName = source.findViewById(R.id.app_name);
target.packageName = source.findViewById(R.id.package_name);
target.appIcon = source.findViewById(R.id.app_icon);
target.masterSwitch = source.findViewById(R.id.master_switch);
target.notificationSwitch = source.findViewById(R.id.notification_switch);
target.loggingSwitch = source.findViewById(R.id.logging_switch);
target.expandLayout = source.findViewById(R.id.expand_layout);
target.delete = source.findViewById(R.id.delete);
target.moreInfo = source.findViewById(R.id.more_info);
}
public static void bind(ReposAdapter.SectionHolder target, View source) {
target.sectionText = source.findViewById(R.id.section_text);
}
public static void bind(ReposAdapter.RepoHolder target, View source) {
target.title = source.findViewById(R.id.title);
target.versionName = source.findViewById(R.id.version_name);
target.description = source.findViewById(R.id.description);
target.author = source.findViewById(R.id.author);
target.infoLayout = source.findViewById(R.id.info_layout);
target.downloadImage = source.findViewById(R.id.download);
target.updateTime = source.findViewById(R.id.update_time);
}
public static void bind(SuLogAdapter.SectionHolder target, View source) {
target.date = source.findViewById(R.id.date);
target.arrow = source.findViewById(R.id.arrow);
}
public static void bind(SuLogAdapter.LogViewHolder target, View source) {
target.appName = source.findViewById(R.id.app_name);
target.action = source.findViewById(R.id.action);
target.time = source.findViewById(R.id.time);
target.fromPid = source.findViewById(R.id.fromPid);
target.toUid = source.findViewById(R.id.toUid);
target.command = source.findViewById(R.id.command);
target.expandLayout = source.findViewById(R.id.expand_layout);
}
}

View File

@@ -6,8 +6,6 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -19,6 +17,7 @@ import android.widget.TextView;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.utils.LocaleManager;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.superuser.Shell;
@@ -28,8 +27,8 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.ViewHolder> {
@@ -123,16 +122,16 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
AsyncTask.THREAD_POOL_EXECUTOR.execute(this::loadApps);
}
static class ViewHolder extends RecyclerView.ViewHolder {
public static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.app_icon) ImageView appIcon;
@BindView(R.id.app_name) TextView appName;
@BindView(R.id.package_name) TextView appPackage;
@BindView(R.id.checkbox) CheckBox checkBox;
public ImageView appIcon;
public TextView appName;
public TextView appPackage;
public CheckBox checkBox;
ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
ViewBinder.bind(this, itemView);
}
}

View File

@@ -1,8 +1,6 @@
package com.topjohnwu.magisk.adapters;
import android.content.Context;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -11,15 +9,16 @@ import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.android.material.snackbar.Snackbar;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.container.Module;
import com.topjohnwu.superuser.Shell;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import androidx.recyclerview.widget.RecyclerView;
public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> {
@@ -46,9 +45,9 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
String noInfo = context.getString(R.string.no_info_provided);
holder.title.setText(module.getName());
holder.versionName.setText( TextUtils.isEmpty(version) ? noInfo : version);
holder.author.setText( TextUtils.isEmpty(author) ? noInfo : context.getString(R.string.author, author));
holder.description.setText( TextUtils.isEmpty(description) ? noInfo : description);
holder.versionName.setText(TextUtils.isEmpty(version) ? noInfo : version);
holder.author.setText(TextUtils.isEmpty(author) ? noInfo : context.getString(R.string.author, author));
holder.description.setText(TextUtils.isEmpty(description) ? noInfo : description);
holder.checkBox.setOnCheckedChangeListener(null);
holder.checkBox.setChecked(module.isEnabled());
@@ -102,19 +101,19 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
return mList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
public static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.title) TextView title;
@BindView(R.id.version_name) TextView versionName;
@BindView(R.id.description) TextView description;
@BindView(R.id.notice) TextView notice;
@BindView(R.id.checkbox) CheckBox checkBox;
@BindView(R.id.author) TextView author;
@BindView(R.id.delete) ImageView delete;
public TextView title;
public TextView versionName;
public TextView description;
public TextView notice;
public CheckBox checkBox;
public TextView author;
public ImageView delete;
ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
ViewBinder.bind(this, itemView);
if (!Shell.rootAccess()) {
checkBox.setEnabled(false);

View File

@@ -2,8 +2,6 @@ package com.topjohnwu.magisk.adapters;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -11,7 +9,9 @@ import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;
import com.google.android.material.snackbar.Snackbar;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.components.CustomAlertDialog;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.components.SnackbarMaker;
@@ -22,8 +22,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import butterknife.BindView;
import butterknife.ButterKnife;
import androidx.recyclerview.widget.RecyclerView;
public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder> {
@@ -120,24 +119,24 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
return policyList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
public static class ViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
@BindView(R.id.app_name) TextView appName;
@BindView(R.id.package_name) TextView packageName;
@BindView(R.id.app_icon) ImageView appIcon;
@BindView(R.id.master_switch) Switch masterSwitch;
@BindView(R.id.notification_switch) Switch notificationSwitch;
@BindView(R.id.logging_switch) Switch loggingSwitch;
@BindView(R.id.expand_layout) ViewGroup expandLayout;
public TextView appName;
public TextView packageName;
public ImageView appIcon;
public Switch masterSwitch;
public Switch notificationSwitch;
public Switch loggingSwitch;
public ViewGroup expandLayout;
@BindView(R.id.delete) ImageView delete;
@BindView(R.id.more_info) ImageView moreInfo;
public ImageView delete;
public ImageView moreInfo;
private Container container = new Container();
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
ViewBinder.bind(this, itemView);
container.expandLayout = expandLayout;
setupExpandable();
}

View File

@@ -2,7 +2,6 @@ package com.topjohnwu.magisk.adapters;
import android.content.Context;
import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Pair;
import android.view.LayoutInflater;
@@ -13,6 +12,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.asyncs.MarkDownWindow;
import com.topjohnwu.magisk.asyncs.ProcessRepoZip;
import com.topjohnwu.magisk.components.BaseActivity;
@@ -25,8 +25,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import androidx.recyclerview.widget.RecyclerView;
public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, ReposAdapter.RepoHolder> {
@@ -89,11 +88,16 @@ public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, R
Repo repo = repoPairs.get(section).second.get(position);
Context context = holder.itemView.getContext();
holder.title.setText(repo.getName());
holder.versionName.setText(repo.getVersion());
String name = repo.getName();
String version = repo.getVersion();
String author = repo.getAuthor();
holder.author.setText(TextUtils.isEmpty(author) ? null : context.getString(R.string.author, author));
holder.description.setText(repo.getDescription());
String description = repo.getDescription();
String noInfo = context.getString(R.string.no_info_provided);
holder.title.setText(TextUtils.isEmpty(name) ? noInfo : name);
holder.versionName.setText(TextUtils.isEmpty(version) ? noInfo : version);
holder.author.setText(TextUtils.isEmpty(author) ? noInfo : context.getString(R.string.author, author));
holder.description.setText(TextUtils.isEmpty(description) ? noInfo : description);
holder.updateTime.setText(context.getString(R.string.updated_on, repo.getLastUpdateString()));
holder.infoLayout.setOnClickListener(v ->
@@ -159,29 +163,29 @@ public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, R
notifyDataSetChanged();
}
static class SectionHolder extends RecyclerView.ViewHolder {
public static class SectionHolder extends RecyclerView.ViewHolder {
@BindView(R.id.section_text) TextView sectionText;
public TextView sectionText;
SectionHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
ViewBinder.bind(this, itemView);
}
}
static class RepoHolder extends RecyclerView.ViewHolder {
public static class RepoHolder extends RecyclerView.ViewHolder {
@BindView(R.id.title) TextView title;
@BindView(R.id.version_name) TextView versionName;
@BindView(R.id.description) TextView description;
@BindView(R.id.author) TextView author;
@BindView(R.id.info_layout) LinearLayout infoLayout;
@BindView(R.id.download) ImageView downloadImage;
@BindView(R.id.update_time) TextView updateTime;
public TextView title;
public TextView versionName;
public TextView description;
public TextView author;
public LinearLayout infoLayout;
public ImageView downloadImage;
public TextView updateTime;
RepoHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
ViewBinder.bind(this, itemView);
}
}

View File

@@ -1,8 +1,9 @@
package com.topjohnwu.magisk.adapters;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
public abstract class SectionedAdapter<S extends RecyclerView.ViewHolder, C extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

View File

@@ -1,7 +1,6 @@
package com.topjohnwu.magisk.adapters;
import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -11,6 +10,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.container.SuLogEntry;
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
@@ -20,8 +20,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import butterknife.BindView;
import butterknife.ButterKnife;
import androidx.recyclerview.widget.RecyclerView;
public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, SuLogAdapter.LogViewHolder> {
@@ -117,32 +116,32 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
notifyDataSetChanged();
}
static class SectionHolder extends RecyclerView.ViewHolder {
public static class SectionHolder extends RecyclerView.ViewHolder {
@BindView(R.id.date) TextView date;
@BindView(R.id.arrow) ImageView arrow;
public TextView date;
public ImageView arrow;
SectionHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
ViewBinder.bind(this, itemView);
}
}
static class LogViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
public static class LogViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
@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) ViewGroup expandLayout;
public TextView appName;
public TextView action;
public TextView time;
public TextView fromPid;
public TextView toUid;
public TextView command;
public ViewGroup expandLayout;
private Container container = new Container();
LogViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
ViewBinder.bind(this, itemView);
container.expandLayout = expandLayout;
setupExpandable();
}

View File

@@ -1,13 +1,13 @@
package com.topjohnwu.magisk.adapters;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.ArrayList;
import java.util.List;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
public class TabFragmentAdapter extends FragmentPagerAdapter {
private List<Fragment> fragmentList;

View File

@@ -4,7 +4,6 @@ import android.app.Activity;
import android.app.ProgressDialog;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.View;
import android.widget.Toast;
@@ -44,6 +43,8 @@ import java.net.HttpURLConnection;
import java.util.Arrays;
import java.util.List;
import androidx.annotation.NonNull;
public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
private static final int PATCH_MODE = 0;

View File

@@ -1,7 +1,6 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.support.v7.app.AlertDialog;
import android.webkit.WebView;
import com.topjohnwu.magisk.Data;
@@ -18,6 +17,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import androidx.appcompat.app.AlertDialog;
public class MarkDownWindow extends ParallelTask<Void, Void, String> {
private String mTitle;

View File

@@ -4,7 +4,6 @@ import android.Manifest;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.widget.Toast;
import com.topjohnwu.magisk.Const;
@@ -35,6 +34,8 @@ import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import androidx.annotation.NonNull;
public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
private ProgressDialog progressDialog;
@@ -140,7 +141,7 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
if (result) {
Uri uri = Uri.fromFile(mFile);
if (mInstall) {
Intent intent = new Intent(activity, FlashActivity.class);
Intent intent = new Intent(activity, Data.classMap.get(FlashActivity.class));
intent.setData(uri).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
activity.startActivity(intent);
} else {

View File

@@ -27,19 +27,17 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import com.topjohnwu.magisk.ViewBinder;
/**
* @author dvdandroid
*/
public class AboutCardRow extends LinearLayout {
@BindView(android.R.id.title) TextView mTitle;
@BindView(android.R.id.summary) TextView mSummary;
@BindView(android.R.id.icon) ImageView mIcon;
@BindView(R.id.container) View mView;
public TextView mTitle;
public TextView mSummary;
public ImageView mIcon;
public View mView;
public AboutCardRow(Context context) {
this(context, null);
@@ -52,7 +50,7 @@ public class AboutCardRow extends LinearLayout {
public AboutCardRow(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater.from(context).inflate(R.layout.info_item_row, this);
ButterKnife.bind(this, this);
ViewBinder.bind(this, this);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AboutCardRow, 0, 0);
String title;
@@ -69,8 +67,6 @@ public class AboutCardRow extends LinearLayout {
@Override
public void setOnClickListener(OnClickListener l) {
super.setOnClickListener(l);
mView.setOnClickListener(l);
}

View File

@@ -1,12 +1,13 @@
package com.topjohnwu.magisk.components;
import android.content.Intent;
import android.support.v4.app.Fragment;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Topic;
import androidx.fragment.app.Fragment;
public class BaseFragment extends Fragment implements Topic.AutoSubscriber {
public MagiskManager mm;

View File

@@ -2,11 +2,6 @@ package com.topjohnwu.magisk.components;
import android.app.Activity;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.annotation.StyleRes;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
@@ -14,9 +9,13 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import butterknife.BindView;
import butterknife.ButterKnife;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.annotation.StyleRes;
import androidx.appcompat.app.AlertDialog;
public class CustomAlertDialog extends AlertDialog.Builder {
@@ -28,16 +27,16 @@ public class CustomAlertDialog extends AlertDialog.Builder {
private ViewHolder vh;
public class ViewHolder {
@BindView(R.id.dialog_layout) public LinearLayout dialogLayout;
@BindView(R.id.button_panel) public LinearLayout buttons;
public LinearLayout dialogLayout;
public LinearLayout buttons;
@BindView(R.id.message) public TextView messageView;
@BindView(R.id.negative) public Button negative;
@BindView(R.id.positive) public Button positive;
@BindView(R.id.neutral) public Button neutral;
public TextView messageView;
public Button negative;
public Button positive;
public Button neutral;
ViewHolder(View v) {
ButterKnife.bind(this, v);
ViewBinder.bind(this, v);
messageView.setVisibility(View.GONE);
negative.setVisibility(View.GONE);
positive.setVisibility(View.GONE);

View File

@@ -1,11 +1,12 @@
package com.topjohnwu.magisk.components;
import android.app.Activity;
import android.support.annotation.NonNull;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.InstallMagisk;
import androidx.annotation.NonNull;
public class EnvFixDialog extends CustomAlertDialog {
public EnvFixDialog(@NonNull Activity activity) {

View File

@@ -4,9 +4,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.support.v7.app.AppCompatActivity;
import android.view.WindowManager;
import com.topjohnwu.magisk.Data;
@@ -15,6 +12,10 @@ import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.LocaleManager;
import com.topjohnwu.magisk.utils.Topic;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.appcompat.app.AppCompatActivity;
public abstract class FlavorActivity extends AppCompatActivity implements Topic.AutoSubscriber {
private ActivityResultListener activityResultListener;
@@ -42,11 +43,11 @@ public abstract class FlavorActivity extends AppCompatActivity implements Topic.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Topic.subscribe(this);
if (Data.isDarkTheme && getDarkTheme() != -1) {
setTheme(getDarkTheme());
}
super.onCreate(savedInstanceState);
}
@Override

View File

@@ -3,10 +3,9 @@ package com.topjohnwu.magisk.components;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.widget.Toast;
import com.google.android.material.snackbar.Snackbar;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.FlashActivity;
@@ -17,6 +16,8 @@ import com.topjohnwu.magisk.utils.Utils;
import java.util.List;
import androidx.appcompat.app.AlertDialog;
class InstallMethodDialog extends AlertDialog.Builder {
InstallMethodDialog(BaseActivity activity, List<String> options) {
@@ -37,7 +38,7 @@ class InstallMethodDialog extends AlertDialog.Builder {
(requestCode, resultCode, data) -> {
if (requestCode == Const.ID.SELECT_BOOT &&
resultCode == BaseActivity.RESULT_OK && data != null) {
Intent i = new Intent(activity, FlashActivity.class)
Intent i = new Intent(activity, Data.classMap.get(FlashActivity.class))
.putExtra(Const.Key.FLASH_SET_BOOT, data.getData())
.putExtra(Const.Key.FLASH_ACTION, Const.Value.PATCH_BOOT);
activity.startActivity(i);
@@ -55,7 +56,7 @@ class InstallMethodDialog extends AlertDialog.Builder {
}, Data.magiskLink, filename);
break;
case 2:
intent = new Intent(activity, FlashActivity.class)
intent = new Intent(activity, Data.classMap.get(FlashActivity.class))
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_MAGISK);
activity.startActivity(intent);
break;
@@ -65,7 +66,7 @@ class InstallMethodDialog extends AlertDialog.Builder {
.setMessage(R.string.install_inactive_slot_msg)
.setCancelable(true)
.setPositiveButton(R.string.yes, (d, i) -> {
Intent it = new Intent(activity, FlashActivity.class)
Intent it = new Intent(activity, Data.classMap.get(FlashActivity.class))
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_INACTIVE_SLOT);
activity.startActivity(it);
})

View File

@@ -2,7 +2,6 @@ package com.topjohnwu.magisk.components;
import android.Manifest;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.topjohnwu.magisk.Const;
@@ -13,6 +12,8 @@ import com.topjohnwu.magisk.asyncs.MarkDownWindow;
import com.topjohnwu.magisk.receivers.ManagerUpdate;
import com.topjohnwu.magisk.utils.Utils;
import androidx.annotation.NonNull;
public class ManagerInstallDialog extends CustomAlertDialog {
public ManagerInstallDialog(@NonNull BaseActivity activity) {
@@ -25,7 +26,7 @@ public class ManagerInstallDialog extends CustomAlertDialog {
setCancelable(true);
setPositiveButton(R.string.install, (d, i) -> activity.runWithPermission(
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
Intent intent = new Intent(mm, ManagerUpdate.class);
Intent intent = new Intent(mm, Data.classMap.get(ManagerUpdate.class));
intent.putExtra(Const.Key.INTENT_SET_LINK, Data.managerLink);
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
mm.sendBroadcast(intent);

View File

@@ -2,14 +2,15 @@ package com.topjohnwu.magisk.components;
import android.app.Activity;
import android.net.Uri;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.view.View;
import android.widget.TextView;
import com.google.android.material.snackbar.Snackbar;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Utils;
import androidx.annotation.StringRes;
public class SnackbarMaker {
public static Snackbar make(Activity activity, CharSequence text, int duration) {
@@ -34,7 +35,7 @@ public class SnackbarMaker {
}
private static void setup(Snackbar snack) {
TextView text = snack.getView().findViewById(android.support.design.R.id.snackbar_text);
TextView text = snack.getView().findViewById(com.google.android.material.R.id.snackbar_text);
text.setMaxLines(Integer.MAX_VALUE);
}

View File

@@ -5,7 +5,6 @@ import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.widget.Toast;
@@ -19,6 +18,8 @@ import com.topjohnwu.magisk.utils.Download;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell;
import androidx.annotation.NonNull;
public class UninstallDialog extends CustomAlertDialog {
public UninstallDialog(@NonNull Activity activity) {
@@ -44,7 +45,7 @@ public class UninstallDialog extends CustomAlertDialog {
Download.receive(activity, new DownloadReceiver() {
@Override
public void onDownloadDone(Context context, Uri uri) {
Intent intent = new Intent(context, FlashActivity.class)
Intent intent = new Intent(context, Data.classMap.get(FlashActivity.class))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.setData(uri)
.putExtra(Const.Key.FLASH_ACTION, Const.Value.UNINSTALL);

View File

@@ -1,29 +1,35 @@
package com.topjohnwu.magisk.container;
import android.content.ContentValues;
import android.database.Cursor;
import android.support.annotation.NonNull;
import java.util.List;
import androidx.annotation.NonNull;
public abstract class BaseModule implements Comparable<BaseModule> {
private String mId = null, mName, mVersion, mAuthor, mDescription;
private String mId, mName, mVersion, mAuthor, mDescription;
private int mVersionCode = -1, minMagiskVersion = -1;
protected BaseModule() {}
protected BaseModule() {
mId = mName = mVersion = mAuthor = mDescription = "";
}
protected BaseModule(Cursor c) {
mId = c.getString(c.getColumnIndex("id"));
mName = c.getString(c.getColumnIndex("name"));
mVersion = c.getString(c.getColumnIndex("version"));
mId = nonNull(c.getString(c.getColumnIndex("id")));
mName = nonNull(c.getString(c.getColumnIndex("name")));
mVersion = nonNull(c.getString(c.getColumnIndex("version")));
mVersionCode = c.getInt(c.getColumnIndex("versionCode"));
mAuthor = c.getString(c.getColumnIndex("author"));
mDescription = c.getString(c.getColumnIndex("description"));
mAuthor = nonNull(c.getString(c.getColumnIndex("author")));
mDescription = nonNull(c.getString(c.getColumnIndex("description")));
minMagiskVersion = c.getInt(c.getColumnIndex("minMagisk"));
}
private String nonNull(String s) {
return s == null ? "" : s;
}
public ContentValues getContentValues() {
ContentValues values = new ContentValues();
values.put("id", mId);

View File

@@ -4,7 +4,8 @@ import android.content.ContentValues;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
public class Policy implements Comparable<Policy>{

View File

@@ -2,6 +2,7 @@ package com.topjohnwu.magisk.container;
import android.content.ContentValues;
import android.database.Cursor;
import android.text.TextUtils;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.utils.Download;
@@ -35,7 +36,7 @@ public class Repo extends BaseModule {
throw new IllegalRepoException("Repo [" + repoName + "] parse error: " + e.getMessage());
}
if (getId() == null) {
if (TextUtils.isEmpty(getId())) {
throw new IllegalRepoException("Repo [" + repoName + "] does not contain id");
}
if (getVersionCode() < 0) {

View File

@@ -1,7 +1,5 @@
package com.topjohnwu.magisk.container;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -9,6 +7,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.annotation.NonNull;
public class ValueSortedMap<K, V extends Comparable<? super V>> extends HashMap<K, V> {
private List<V> sorted = new ArrayList<>();

View File

@@ -7,7 +7,6 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Process;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.widget.Toast;
@@ -29,9 +28,12 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import androidx.annotation.NonNull;
public class MagiskDatabaseHelper {
private static final int DATABASE_VER = 6;
private static final int OLD_DATABASE_VER = 5;
private static final String POLICY_TABLE = "policies";
private static final String LOG_TABLE = "logs";
private static final String SETTINGS_TABLE = "settings";
@@ -57,13 +59,15 @@ public class MagiskDatabaseHelper {
pm = mm.getPackageManager();
db = openDatabase(mm);
db.disableWriteAheadLogging();
int version = db.getVersion();
if (version < DATABASE_VER) {
onUpgrade(db, version);
} else if (version > DATABASE_VER) {
int version = Data.magiskVersionCode >= Const.MAGISK_VER.DBVER_SIX ? DATABASE_VER : OLD_DATABASE_VER;
int curVersion = db.getVersion();
if (curVersion < version) {
onUpgrade(db, curVersion);
} else if (curVersion > DATABASE_VER) {
/* Higher than we can possibly support */
onDowngrade(db);
}
db.setVersion(DATABASE_VER);
db.setVersion(version);
clearOutdated();
}

View File

@@ -2,36 +2,32 @@ package com.topjohnwu.magisk.fragments;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.material.tabs.TabLayout;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.MainActivity;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.adapters.TabFragmentAdapter;
import com.topjohnwu.magisk.components.BaseFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import androidx.viewpager.widget.ViewPager;
public class LogFragment extends BaseFragment {
private Unbinder unbinder;
@BindView(R.id.container) ViewPager viewPager;
@BindView(R.id.tab) TabLayout tab;
public ViewPager viewPager;
public TabLayout tab;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_log, container, false);
unbinder = ButterKnife.bind(this, v);
ViewBinder.bind(this, v);
((MainActivity) requireActivity()).toolbar.setElevation(0);
@@ -52,7 +48,6 @@ public class LogFragment extends BaseFragment {
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
ViewBinder.unbind(this);
}
}

View File

@@ -5,11 +5,6 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -25,6 +20,7 @@ import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.MainActivity;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.asyncs.CheckSafetyNet;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.components.BaseActivity;
@@ -41,55 +37,53 @@ import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils;
import butterknife.BindColor;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.cardview.widget.CardView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
public class MagiskFragment extends BaseFragment
implements SwipeRefreshLayout.OnRefreshListener, ExpandableView, Topic.Subscriber {
private Container expandableContainer = new Container();
private Unbinder unbinder;
private static boolean shownDialog = false;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
public SwipeRefreshLayout mSwipeRefreshLayout;
@BindView(R.id.core_only_notice) CardView coreOnlyNotice;
public CardView coreOnlyNotice;
@BindView(R.id.magisk_update) RelativeLayout magiskUpdate;
@BindView(R.id.magisk_update_icon) ImageView magiskUpdateIcon;
@BindView(R.id.magisk_update_status) TextView magiskUpdateText;
@BindView(R.id.magisk_update_progress) ProgressBar magiskUpdateProgress;
@BindView(R.id.magisk_status_icon) ImageView magiskStatusIcon;
@BindView(R.id.magisk_version) TextView magiskVersionText;
public RelativeLayout magiskUpdate;
public ImageView magiskUpdateIcon;
public TextView magiskUpdateText;
public ProgressBar magiskUpdateProgress;
public ImageView magiskStatusIcon;
public TextView magiskVersionText;
@BindView(R.id.safetyNet_card) CardView safetyNetCard;
@BindView(R.id.safetyNet_refresh) ImageView safetyNetRefreshIcon;
@BindView(R.id.safetyNet_status) TextView safetyNetStatusText;
@BindView(R.id.safetyNet_check_progress) ProgressBar safetyNetProgress;
@BindView(R.id.expand_layout) LinearLayout expandLayout;
@BindView(R.id.cts_status_icon) ImageView ctsStatusIcon;
@BindView(R.id.cts_status) TextView ctsStatusText;
@BindView(R.id.basic_status_icon) ImageView basicStatusIcon;
@BindView(R.id.basic_status) TextView basicStatusText;
public CardView safetyNetCard;
public ImageView safetyNetRefreshIcon;
public TextView safetyNetStatusText;
public ProgressBar safetyNetProgress;
public LinearLayout expandLayout;
public ImageView ctsStatusIcon;
public TextView ctsStatusText;
public ImageView basicStatusIcon;
public TextView basicStatusText;
@BindView(R.id.install_option_card) CardView installOptionCard;
@BindView(R.id.keep_force_enc) CheckBox keepEncChkbox;
@BindView(R.id.keep_verity) CheckBox keepVerityChkbox;
@BindView(R.id.install_button) CardView installButton;
@BindView(R.id.install_text) TextView installText;
@BindView(R.id.uninstall_button) CardView uninstallButton;
public CardView installOptionCard;
public CheckBox keepEncChkbox;
public CheckBox keepVerityChkbox;
public CardView installButton;
public TextView installText;
public CardView uninstallButton;
@BindColor(R.color.red500) int colorBad;
@BindColor(R.color.green500) int colorOK;
@BindColor(R.color.yellow500) int colorWarn;
@BindColor(R.color.grey500) int colorNeutral;
@BindColor(R.color.blue500) int colorInfo;
public int colorBad;
public int colorOK;
public int colorWarn;
public int colorNeutral;
public int colorInfo;
@OnClick(R.id.safetyNet_title)
void safetyNet() {
public void safetyNet() {
Runnable task = () -> {
safetyNetProgress.setVisibility(View.VISIBLE);
safetyNetRefreshIcon.setVisibility(View.GONE);
@@ -112,8 +106,7 @@ public class MagiskFragment extends BaseFragment
}
@OnClick(R.id.install_button)
void install() {
public void install() {
shownDialog = true;
// Show Manager update first
@@ -126,8 +119,7 @@ public class MagiskFragment extends BaseFragment
new MagiskInstallDialog((BaseActivity) getActivity()).show();
}
@OnClick(R.id.uninstall_button)
void uninstall() {
public void uninstall() {
new UninstallDialog(requireActivity()).show();
}
@@ -136,7 +128,7 @@ public class MagiskFragment extends BaseFragment
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_magisk, container, false);
unbinder = ButterKnife.bind(this, v);
ViewBinder.bind(this, v);
requireActivity().setTitle(R.string.magisk);
expandableContainer.expandLayout = expandLayout;
@@ -153,6 +145,12 @@ public class MagiskFragment extends BaseFragment
return v;
}
@Override
public void onDestroyView() {
super.onDestroyView();
ViewBinder.unbind(this);
}
@Override
public void onRefresh() {
Data.loadMagiskInfo();
@@ -196,12 +194,6 @@ public class MagiskFragment extends BaseFragment
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public Container getContainer() {
return expandableContainer;

View File

@@ -1,10 +1,6 @@
package com.topjohnwu.magisk.fragments;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -13,19 +9,20 @@ import android.view.ViewGroup;
import android.widget.SearchView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.adapters.ApplicationAdapter;
import com.topjohnwu.magisk.components.BaseFragment;
import com.topjohnwu.magisk.utils.Topic;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber {
private Unbinder unbinder;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
@BindView(R.id.recyclerView) RecyclerView recyclerView;
public SwipeRefreshLayout mSwipeRefreshLayout;
public RecyclerView recyclerView;
SearchView search;
private ApplicationAdapter appAdapter;
@@ -42,7 +39,7 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false);
unbinder = ButterKnife.bind(this, view);
ViewBinder.bind(this, view);
appAdapter = new ApplicationAdapter(requireActivity());
recyclerView.setAdapter(appAdapter);
@@ -79,7 +76,7 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
ViewBinder.unbind(this);
}
@Override

View File

@@ -2,8 +2,6 @@ package com.topjohnwu.magisk.fragments;
import android.Manifest;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -16,8 +14,10 @@ import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;
import com.google.android.material.snackbar.Snackbar;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.components.BaseFragment;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Download;
@@ -28,24 +28,20 @@ import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import androidx.annotation.Nullable;
public class MagiskLogFragment extends BaseFragment {
private Unbinder unbinder;
@BindView(R.id.txtLog) TextView txtLog;
@BindView(R.id.svLog) ScrollView svLog;
@BindView(R.id.hsvLog) HorizontalScrollView hsvLog;
@BindView(R.id.progressBar) ProgressBar progressBar;
public TextView txtLog;
public ScrollView svLog;
public HorizontalScrollView hsvLog;
public ProgressBar progressBar;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_magisk_log, container, false);
unbinder = ButterKnife.bind(this, view);
ViewBinder.bind(this, view);
setHasOptionsMenu(true);
txtLog.setTextIsSelectable(true);
return view;
@@ -66,7 +62,7 @@ public class MagiskLogFragment extends BaseFragment {
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
ViewBinder.unbind(this);
}
@Override

View File

@@ -4,10 +4,6 @@ import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -17,8 +13,10 @@ import android.view.ViewGroup;
import android.widget.TextView;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.adapters.ModulesAdapter;
import com.topjohnwu.magisk.components.BaseFragment;
import com.topjohnwu.magisk.container.Module;
@@ -30,18 +28,17 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
private Unbinder unbinder;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
@BindView(R.id.recyclerView) RecyclerView recyclerView;
@BindView(R.id.empty_rv) TextView emptyRv;
@OnClick(R.id.fab)
public SwipeRefreshLayout mSwipeRefreshLayout;
public RecyclerView recyclerView;
public TextView emptyRv;
public void selectFile() {
runWithPermission(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
@@ -56,7 +53,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_modules, container, false);
unbinder = ButterKnife.bind(this, view);
ViewBinder.bind(this, view);
setHasOptionsMenu(true);
mSwipeRefreshLayout.setOnRefreshListener(() -> {
@@ -95,7 +92,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == Const.ID.FETCH_ZIP && resultCode == Activity.RESULT_OK && data != null) {
// Get the URI of the selected file
Intent intent = new Intent(getActivity(), FlashActivity.class);
Intent intent = new Intent(getActivity(), Data.classMap.get(FlashActivity.class));
intent.setData(data.getData()).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
startActivity(intent);
}
@@ -104,7 +101,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
ViewBinder.unbind(this);
}
@Override

View File

@@ -2,10 +2,6 @@ package com.topjohnwu.magisk.fragments;
import android.app.AlertDialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -18,6 +14,7 @@ import android.widget.TextView;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.adapters.ReposAdapter;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.components.BaseFragment;
@@ -26,16 +23,16 @@ import com.topjohnwu.magisk.utils.Topic;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
public class ReposFragment extends BaseFragment implements Topic.Subscriber {
private Unbinder unbinder;
@BindView(R.id.recyclerView) RecyclerView recyclerView;
@BindView(R.id.empty_rv) TextView emptyRv;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
public RecyclerView recyclerView;
public TextView emptyRv;
public SwipeRefreshLayout mSwipeRefreshLayout;
private ReposAdapter adapter;
@@ -49,7 +46,7 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_repos, container, false);
unbinder = ButterKnife.bind(this, view);
ViewBinder.bind(this, view);
mSwipeRefreshLayout.setRefreshing(true);
recyclerView.setVisibility(View.GONE);
@@ -123,6 +120,6 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
public void onDestroyView() {
super.onDestroyView();
mm.repoDB.unregisterAdapter();
unbinder.unbind();
ViewBinder.unbind(this);
}
}

View File

@@ -1,5 +1,6 @@
package com.topjohnwu.magisk.fragments;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
@@ -10,13 +11,6 @@ import android.hardware.fingerprint.FingerprintManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.app.AlertDialog;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.support.v7.preference.PreferenceScreen;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -44,6 +38,17 @@ import com.topjohnwu.superuser.ShellUtils;
import java.io.IOException;
import java.util.Locale;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceGroupAdapter;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference;
import androidx.recyclerview.widget.RecyclerView;
public class SettingsFragment extends PreferenceFragmentCompat
implements SharedPreferences.OnSharedPreferenceChangeListener,
Topic.Subscriber, Topic.AutoSubscriber {
@@ -221,7 +226,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
setSummary();
switch (key) {
case Const.Key.DARK_THEME:
Topic.publish(false, Topic.RELOAD_ACTIVITY);
requireActivity().recreate();
break;
case Const.Key.COREONLY:
if (prefs.getBoolean(key, false)) {
@@ -253,7 +258,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
break;
case Const.Key.LOCALE:
LocaleManager.setLocale(mm);
Topic.publish(false, Topic.RELOAD_ACTIVITY);
requireActivity().recreate();
break;
case Const.Key.UPDATE_CHANNEL:
case Const.Key.CUSTOM_CHANNEL:
@@ -352,4 +357,38 @@ public class SettingsFragment extends PreferenceFragmentCompat
public int[] getSubscribedTopics() {
return new int[] {Topic.LOCALE_FETCH_DONE};
}
@Override
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
return new PreferenceGroupAdapter(preferenceScreen) {
@SuppressLint("RestrictedApi")
@Override
public void onBindViewHolder(PreferenceViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
Preference preference = getItem(position);
if (preference instanceof PreferenceCategory)
setZeroPaddingToLayoutChildren(holder.itemView);
else {
View iconFrame = holder.itemView.findViewById(R.id.icon_frame);
if (iconFrame != null) {
iconFrame.setVisibility(preference.getIcon() == null ? View.GONE : View.VISIBLE);
}
}
}
};
}
private void setZeroPaddingToLayoutChildren(View view) {
if (!(view instanceof ViewGroup))
return;
ViewGroup viewGroup = (ViewGroup) view;
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
setZeroPaddingToLayoutChildren(viewGroup.getChildAt(i));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
viewGroup.setPaddingRelative(0, viewGroup.getPaddingTop(), viewGroup.getPaddingEnd(), viewGroup.getPaddingBottom());
else
viewGroup.setPadding(0, viewGroup.getPaddingTop(), viewGroup.getPaddingRight(), viewGroup.getPaddingBottom());
}
}
}

View File

@@ -1,8 +1,6 @@
package com.topjohnwu.magisk.fragments;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -12,19 +10,18 @@ import android.view.ViewGroup;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.adapters.SuLogAdapter;
import com.topjohnwu.magisk.components.BaseFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
public class SuLogFragment extends BaseFragment {
@BindView(R.id.empty_rv) TextView emptyRv;
@BindView(R.id.recyclerView) RecyclerView recyclerView;
public TextView emptyRv;
public RecyclerView recyclerView;
private Unbinder unbinder;
private SuLogAdapter adapter;
@Override
@@ -44,7 +41,7 @@ public class SuLogFragment extends BaseFragment {
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_su_log, container, false);
unbinder = ButterKnife.bind(this, v);
ViewBinder.bind(this, v);
adapter = new SuLogAdapter(mm.mDB);
recyclerView.setAdapter(adapter);
@@ -83,6 +80,6 @@ public class SuLogFragment extends BaseFragment {
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
ViewBinder.unbind(this);
}
}

View File

@@ -2,36 +2,34 @@ package com.topjohnwu.magisk.fragments;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ViewBinder;
import com.topjohnwu.magisk.adapters.PolicyAdapter;
import com.topjohnwu.magisk.components.BaseFragment;
import com.topjohnwu.magisk.container.Policy;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
public class SuperuserFragment extends BaseFragment {
private Unbinder unbinder;
public RecyclerView recyclerView;
public TextView emptyRv;
private PackageManager pm;
@BindView(R.id.recyclerView) RecyclerView recyclerView;
@BindView(R.id.empty_rv) TextView emptyRv;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_superuser, container, false);
unbinder = ButterKnife.bind(this, view);
ViewBinder.bind(this, view);
pm = getActivity().getPackageManager();
return view;
@@ -52,7 +50,7 @@ public class SuperuserFragment extends BaseFragment {
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
ViewBinder.unbind(this);
}
private void displayPolicyList() {

View File

@@ -5,14 +5,31 @@ import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.SuRequestActivity;
import com.topjohnwu.magisk.services.OnBootService;
import com.topjohnwu.magisk.utils.SuConnector;
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (TextUtils.equals(intent.getAction(), Intent.ACTION_BOOT_COMPLETED))
OnBootService.enqueueWork(context);
if (TextUtils.equals(intent.getAction(), Intent.ACTION_BOOT_COMPLETED)) {
switch (intent.getExtras().getString("action", "boot")) {
case "request":
Intent i = new Intent(context, Data.classMap.get(SuRequestActivity.class))
.putExtra("socket", intent.getStringExtra("socket"))
.putExtra("version", 2)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
break;
case "log":
SuConnector.handleLogs(intent, 2);
break;
case "boot":
OnBootService.enqueueWork(context);
break;
}
}
}
}

View File

@@ -7,7 +7,6 @@ import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.support.annotation.RequiresApi;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
@@ -18,6 +17,8 @@ import com.topjohnwu.superuser.Shell;
import java.util.ArrayList;
import androidx.annotation.RequiresApi;
public class ShortcutReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -36,7 +37,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
Data.multiuserMode == Const.Value.MULTIUSER_MODE_OWNER_MANAGED)) {
shortCuts.add(new ShortcutInfo.Builder(mm, "superuser")
.setShortLabel(mm.getString(R.string.superuser))
.setIntent(new Intent(mm, SplashActivity.class)
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
.putExtra(Const.Key.OPEN_SECTION, "superuser")
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
@@ -48,7 +49,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
&& mm.prefs.getBoolean(Const.Key.MAGISKHIDE, false)) {
shortCuts.add(new ShortcutInfo.Builder(mm, "magiskhide")
.setShortLabel(mm.getString(R.string.magiskhide))
.setIntent(new Intent(mm, SplashActivity.class)
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
.putExtra(Const.Key.OPEN_SECTION, "magiskhide")
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
@@ -59,7 +60,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
if (!mm.prefs.getBoolean(Const.Key.COREONLY, false) && root && Data.magiskVersionCode >= 0) {
shortCuts.add(new ShortcutInfo.Builder(mm, "modules")
.setShortLabel(mm.getString(R.string.modules))
.setIntent(new Intent(mm, SplashActivity.class)
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
.putExtra(Const.Key.OPEN_SECTION, "modules")
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
@@ -68,7 +69,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
.build());
shortCuts.add(new ShortcutInfo.Builder(mm, "downloads")
.setShortLabel(mm.getString(R.string.download))
.setIntent(new Intent(mm, SplashActivity.class)
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
.putExtra(Const.Key.OPEN_SECTION, "downloads")
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))

View File

@@ -2,18 +2,20 @@ package com.topjohnwu.magisk.services;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.utils.NotificationMgr;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils;
import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService;
public class OnBootService extends JobIntentService {
public static void enqueueWork(Context context) {
enqueueWork(context, OnBootService.class, Const.ID.ONBOOT_SERVICE_ID, new Intent());
enqueueWork(context, Data.classMap.get(OnBootService.class), Const.ID.ONBOOT_SERVICE_ID, new Intent());
}
@Override

View File

@@ -1,297 +1,21 @@
package com.topjohnwu.magisk.superuser;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.FileObserver;
import android.text.TextUtils;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.SuRequestActivity;
import com.topjohnwu.magisk.components.BaseActivity;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.utils.FingerprintHelper;
import java.io.DataInputStream;
import java.io.IOException;
import butterknife.BindView;
import butterknife.ButterKnife;
public class RequestActivity extends BaseActivity {
@BindView(R.id.su_popup) LinearLayout suPopup;
@BindView(R.id.timeout) Spinner timeout;
@BindView(R.id.app_icon) ImageView appIcon;
@BindView(R.id.app_name) TextView appNameView;
@BindView(R.id.package_name) TextView packageNameView;
@BindView(R.id.grant_btn) Button grant_btn;
@BindView(R.id.deny_btn) Button deny_btn;
@BindView(R.id.fingerprint) ImageView fingerprintImg;
@BindView(R.id.warning) TextView warning;
private String socketPath;
private LocalSocket socket;
private PackageManager pm;
private boolean hasTimeout;
private Policy policy;
private CountDownTimer timer;
private FingerprintHelper fingerprintHelper;
@Override
public int getDarkTheme() {
return R.style.SuRequest_Dark;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
pm = getPackageManager();
mm.mDB.clearOutdated();
Intent intent = getIntent();
socketPath = intent.getStringExtra("socket");
hasTimeout = intent.getBooleanExtra("timeout", true);
new FileObserver(socketPath) {
@Override
public void onEvent(int fileEvent, String path) {
if (fileEvent == FileObserver.DELETE_SELF) {
finish();
}
}
}.startWatching();
new SocketManager(this).exec();
}
@Override
public void finish() {
if (timer != null)
timer.cancel();
if (fingerprintHelper != null)
fingerprintHelper.cancel();
super.finish();
}
private boolean cancelTimeout() {
timer.cancel();
deny_btn.setText(getString(R.string.deny));
return false;
}
private void showRequest() {
switch (Data.suResponseType) {
case Const.Value.SU_AUTO_DENY:
handleAction(Policy.DENY, 0);
return;
case Const.Value.SU_AUTO_ALLOW:
handleAction(Policy.ALLOW, 0);
return;
case Const.Value.SU_PROMPT:
default:
}
// If not interactive, response directly
if (policy.policy != Policy.INTERACTIVE) {
handleAction();
return;
}
setContentView(R.layout.activity_request);
ButterKnife.bind(this);
appIcon.setImageDrawable(policy.info.loadIcon(pm));
appNameView.setText(policy.appName);
packageNameView.setText(policy.packageName);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.allow_timeout, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
timeout.setAdapter(adapter);
timer = new CountDownTimer(Data.suRequestTimeout * 1000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
deny_btn.setText(getString(R.string.deny_with_str, "(" + millisUntilFinished / 1000 + ")"));
}
@Override
public void onFinish() {
deny_btn.setText(getString(R.string.deny_with_str, "(0)"));
handleAction(Policy.DENY);
}
};
boolean useFingerprint = Data.suFingerprint && FingerprintHelper.canUseFingerprint();
if (useFingerprint) {
try {
fingerprintHelper = new FingerprintHelper() {
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
warning.setText(errString);
}
@Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
warning.setText(helpString);
}
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
handleAction(Policy.ALLOW);
}
@Override
public void onAuthenticationFailed() {
warning.setText(R.string.auth_fail);
}
};
fingerprintHelper.authenticate();
} catch (Exception e) {
e.printStackTrace();
useFingerprint = false;
}
}
if (!useFingerprint) {
grant_btn.setOnClickListener(v -> {
handleAction(Policy.ALLOW);
timer.cancel();
});
grant_btn.requestFocus();
}
grant_btn.setVisibility(useFingerprint ? View.GONE : View.VISIBLE);
fingerprintImg.setVisibility(useFingerprint ? View.VISIBLE : View.GONE);
deny_btn.setOnClickListener(v -> {
handleAction(Policy.DENY);
timer.cancel();
});
suPopup.setOnClickListener(v -> cancelTimeout());
timeout.setOnTouchListener((v, event) -> cancelTimeout());
if (hasTimeout) {
timer.start();
} else {
cancelTimeout();
}
}
@Override
public void onBackPressed() {
if (policy != null) {
handleAction(Policy.DENY);
} else {
finish();
}
}
void handleAction() {
String response;
if (policy.policy == Policy.ALLOW) {
response = "socket:ALLOW";
} else {
response = "socket:DENY";
}
try {
socket.getOutputStream().write((response).getBytes());
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
Intent intent = new Intent(this, Data.classMap.get(SuRequestActivity.class))
.putExtra("socket", getIntent().getStringExtra("socket"))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}
void handleAction(int action) {
handleAction(action, Const.Value.timeoutList[timeout.getSelectedItemPosition()]);
}
void handleAction(int action, int time) {
policy.policy = action;
if (time >= 0) {
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
mm.mDB.addPolicy(policy);
}
handleAction();
}
private class SocketManager extends ParallelTask<Void, Void, Boolean> {
SocketManager(BaseActivity context) {
super(context);
}
@Override
protected Boolean doInBackground(Void... params) {
try {
socket = new LocalSocket();
socket.connect(new LocalSocketAddress(socketPath, LocalSocketAddress.Namespace.FILESYSTEM));
DataInputStream is = new DataInputStream(socket.getInputStream());
ContentValues payload = new ContentValues();
while (true) {
int nameLen = is.readInt();
byte[] nameBytes = new byte[nameLen];
is.readFully(nameBytes);
String name = new String(nameBytes);
if (TextUtils.equals(name, "eof"))
break;
int dataLen = is.readInt();
byte[] dataBytes = new byte[dataLen];
is.readFully(dataBytes);
String data = new String(dataBytes);
payload.put(name, data);
}
if (payload.getAsInteger("uid") == null) {
return false;
}
int uid = payload.getAsInteger("uid");
policy = mm.mDB.getPolicy(uid);
if (policy == null) {
policy = new Policy(uid, pm);
}
/* Never allow com.topjohnwu.magisk (could be malware) */
if (TextUtils.equals(policy.packageName, Const.ORIG_PKG_NAME))
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
showRequest();
} else {
finish();
}
}
}
}

View File

@@ -3,88 +3,13 @@ package com.topjohnwu.magisk.superuser;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Process;
import android.widget.Toast;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.container.SuLogEntry;
import com.topjohnwu.magisk.utils.Utils;
import java.util.Date;
import com.topjohnwu.magisk.utils.SuConnector;
public class SuReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int fromUid, toUid, pid, mode;
String command, action;
Policy policy;
MagiskManager mm = Data.MM();
if (intent == null) return;
mode = intent.getIntExtra("mode", -1);
if (mode < 0) return;
if (mode == Const.Value.NOTIFY_USER_TO_OWNER) {
Utils.toast(R.string.multiuser_hint_owner_request, Toast.LENGTH_LONG);
return;
}
fromUid = intent.getIntExtra("from.uid", -1);
if (fromUid < 0) return;
if (fromUid == Process.myUid()) return; // Don't show anything if it's Magisk Manager
action = intent.getStringExtra("action");
if (action == null) return;
policy = mm.mDB.getPolicy(fromUid);
if (policy == null) {
try {
policy = new Policy(fromUid, mm.getPackageManager());
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return;
}
}
SuLogEntry log = new SuLogEntry(policy);
String message;
switch (action) {
case "allow":
message = mm.getString(R.string.su_allow_toast, policy.appName);
log.action = true;
break;
case "deny":
message = mm.getString(R.string.su_deny_toast, policy.appName);
log.action = false;
break;
default:
return;
}
if (policy.notification && Data.suNotificationType == Const.Value.NOTIFICATION_TOAST)
Utils.toast(message, Toast.LENGTH_SHORT);
if (mode == Const.Value.NOTIFY_NORMAL_LOG && policy.logging) {
toUid = intent.getIntExtra("to.uid", -1);
if (toUid < 0) return;
pid = intent.getIntExtra("pid", -1);
if (pid < 0) return;
command = intent.getStringExtra("command");
if (command == null) return;
log.toUid = toUid;
log.fromPid = pid;
log.command = command;
log.date = new Date();
mm.mDB.addLog(log);
}
SuConnector.handleLogs(intent, 1);
}
}

View File

@@ -1,12 +1,12 @@
package com.topjohnwu.magisk.utils;
import android.support.annotation.Keep;
import com.topjohnwu.utils.SignBoot;
import java.io.FileInputStream;
import java.io.InputStream;
import androidx.annotation.Keep;
public class BootSigner {
@Keep

View File

@@ -1,7 +1,5 @@
package com.topjohnwu.magisk.utils;
import android.support.annotation.Keep;
public interface ISafetyNetHelper {
int RESPONSE_ERR = 0x01;
@@ -10,14 +8,11 @@ public interface ISafetyNetHelper {
int BASIC_PASS = 0x10;
int CTS_PASS = 0x20;
@Keep
void attest();
@Keep
int getVersion();
interface Callback {
@Keep
void onResponse(int responseCode);
}
}

View File

@@ -3,7 +3,6 @@ package com.topjohnwu.magisk.utils;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.support.annotation.StringRes;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
@@ -16,6 +15,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import androidx.annotation.StringRes;
public class LocaleManager {
public static Locale locale = Locale.getDefault();
public final static Locale defaultLocale = Locale.getDefault();

View File

@@ -4,8 +4,6 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
@@ -15,15 +13,18 @@ import com.topjohnwu.magisk.SplashActivity;
import com.topjohnwu.magisk.receivers.ManagerUpdate;
import com.topjohnwu.magisk.receivers.RebootReceiver;
import androidx.core.app.NotificationCompat;
import androidx.core.app.TaskStackBuilder;
public class NotificationMgr {
public static void magiskUpdate() {
MagiskManager mm = Data.MM();
Intent intent = new Intent(mm, SplashActivity.class);
Intent intent = new Intent(mm, Data.classMap.get(SplashActivity.class));
intent.putExtra(Const.Key.OPEN_SECTION, "magisk");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mm);
stackBuilder.addParentStack(SplashActivity.class);
stackBuilder.addParentStack(Data.classMap.get(SplashActivity.class));
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
PendingIntent.FLAG_UPDATE_CURRENT);
@@ -46,7 +47,7 @@ public class NotificationMgr {
String filename = Utils.fmt("MagiskManager-v%s(%d).apk",
Data.remoteManagerVersionString, Data.remoteManagerVersionCode);
Intent intent = new Intent(mm, ManagerUpdate.class);
Intent intent = new Intent(mm, Data.classMap.get(ManagerUpdate.class));
intent.putExtra(Const.Key.INTENT_SET_LINK, Data.managerLink);
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
@@ -68,7 +69,7 @@ public class NotificationMgr {
public static void dtboPatched() {
MagiskManager mm = Data.MM();
Intent intent = new Intent(mm, RebootReceiver.class);
Intent intent = new Intent(mm, Data.classMap.get(RebootReceiver.class));
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);

View File

@@ -1,7 +1,6 @@
package com.topjohnwu.magisk.utils;
import android.content.Context;
import android.support.annotation.NonNull;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
@@ -14,6 +13,8 @@ import com.topjohnwu.superuser.io.SuFile;
import java.io.File;
import java.io.InputStream;
import androidx.annotation.NonNull;
public class RootUtils extends Shell.Initializer {
static {
@@ -49,7 +50,7 @@ public class RootUtils extends Shell.Initializer {
job.add(nonroot);
}
job.add("mount_partitions", "get_flags", "run_migrations").exec();
job.add("mount_partitions", "get_flags", "run_migrations", "export BOOTMODE=true").exec();
Data.keepVerity = Boolean.parseBoolean(ShellUtils.fastCmd("echo $KEEPVERITY"));
Data.keepEnc = Boolean.parseBoolean(ShellUtils.fastCmd("echo $KEEPFORCEENCRYPT"));

View File

@@ -0,0 +1,118 @@
package com.topjohnwu.magisk.utils;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.LocalSocket;
import android.os.Bundle;
import android.os.Process;
import android.text.TextUtils;
import android.widget.Toast;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.container.SuLogEntry;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Date;
public abstract class SuConnector {
protected LocalSocket socket = new LocalSocket();
private String readString(DataInputStream is) throws IOException {
int len = is.readInt();
byte[] buf = new byte[len];
is.readFully(buf);
return new String(buf);
}
public Bundle readSocketInput() throws IOException {
Bundle bundle = new Bundle();
DataInputStream is = new DataInputStream(socket.getInputStream());
while (true) {
String name = readString(is);
if (TextUtils.equals(name, "eof"))
break;
bundle.putString(name, readString(is));
}
return bundle;
}
protected DataOutputStream getOutputStream() throws IOException {
return new DataOutputStream(socket.getOutputStream());
}
public abstract void response();
public static void handleLogs(Intent intent, int version) {
MagiskManager mm = Data.MM();
if (intent == null) return;
int fromUid = intent.getIntExtra("from.uid", -1);
if (fromUid < 0) return;
if (fromUid == Process.myUid()) return;
Policy policy = mm.mDB.getPolicy(fromUid);
if (policy == null) {
try {
policy = new Policy(fromUid, mm.getPackageManager());
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return;
}
}
SuLogEntry log = new SuLogEntry(policy);
if (version == 1) {
String action = intent.getStringExtra("action");
if (action == null) return;
switch (action) {
case "allow":
log.action = true;
break;
case "deny":
log.action = false;
break;
default:
return;
}
} else {
switch (intent.getIntExtra("policy", -1)) {
case Policy.ALLOW:
log.action = true;
break;
case Policy.DENY:
log.action = false;
break;
default:
return;
}
}
String message = mm.getString(log.action ?
R.string.su_allow_toast : R.string.su_deny_toast, policy.appName);
if (policy.notification && Data.suNotificationType == Const.Value.NOTIFICATION_TOAST)
Utils.toast(message, Toast.LENGTH_SHORT);
if (policy.logging) {
int toUid = intent.getIntExtra("to.uid", -1);
if (toUid < 0) return;
int pid = intent.getIntExtra("pid", -1);
if (pid < 0) return;
String command = intent.getStringExtra("command");
if (command == null) return;
log.toUid = toUid;
log.fromPid = pid;
log.command = command;
log.date = new Date();
mm.mDB.addLog(log);
}
}
}

View File

@@ -1,7 +1,5 @@
package com.topjohnwu.magisk.utils;
import android.support.annotation.IntDef;
import com.topjohnwu.magisk.Data;
import java.lang.annotation.Retention;
@@ -9,23 +7,24 @@ import java.lang.annotation.RetentionPolicy;
import java.util.HashSet;
import java.util.Set;
import androidx.annotation.IntDef;
public class Topic {
public static final int MAGISK_HIDE_DONE = 0;
public static final int RELOAD_ACTIVITY = 1;
public static final int MODULE_LOAD_DONE = 2;
public static final int REPO_LOAD_DONE = 3;
public static final int UPDATE_CHECK_DONE = 4;
public static final int SNET_CHECK_DONE = 5;
public static final int LOCALE_FETCH_DONE = 6;
public static final int MODULE_LOAD_DONE = 1;
public static final int REPO_LOAD_DONE = 2;
public static final int UPDATE_CHECK_DONE = 3;
public static final int SNET_CHECK_DONE = 4;
public static final int LOCALE_FETCH_DONE = 5;
@IntDef({MAGISK_HIDE_DONE, RELOAD_ACTIVITY, MODULE_LOAD_DONE, REPO_LOAD_DONE,
@IntDef({MAGISK_HIDE_DONE, MODULE_LOAD_DONE, REPO_LOAD_DONE,
UPDATE_CHECK_DONE, SNET_CHECK_DONE, LOCALE_FETCH_DONE})
@Retention(RetentionPolicy.SOURCE)
public @interface TopicID {}
// We will not dynamically add topics, so use arrays instead of hash tables
private static Store[] topicList = new Store[7];
private static Store[] topicList = new Store[6];
public static void subscribe(Subscriber sub, @TopicID int... topics) {
for (int topic : topics) {

View File

@@ -18,12 +18,13 @@ import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.Module;
import com.topjohnwu.magisk.container.ValueSortedMap;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.superuser.io.SuFile;
import java.util.Locale;
import java.util.Map;
import a.n;
public class Utils {
public static int getPrefsInt(SharedPreferences prefs, String key, int def) {
@@ -77,7 +78,7 @@ public class Utils {
if (mm.prefs.getBoolean(Const.Key.CHECK_UPDATES, true)) {
if (scheduler.getAllPendingJobs().isEmpty() ||
Const.UPDATE_SERVICE_VER > mm.prefs.getInt(Const.Key.UPDATE_SERVICE_VER, -1)) {
ComponentName service = new ComponentName(mm, UpdateCheckService.class);
ComponentName service = new ComponentName(mm, n.class);
JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)

View File

@@ -20,7 +20,7 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
@@ -54,42 +54,42 @@
android:textAppearance="@style/TextAppearance.AppCompat.Headline"/>
</LinearLayout>
<com.topjohnwu.magisk.components.AboutCardRow
<a.o
android:id="@+id/app_version_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:icon="@drawable/ic_info_outline"
app:text="@string/app_version"/>
<com.topjohnwu.magisk.components.AboutCardRow
<a.o
android:id="@+id/app_changelog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:icon="@drawable/ic_history"
app:text="@string/app_changelog"/>
<com.topjohnwu.magisk.components.AboutCardRow
<a.o
android:id="@+id/app_translators"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:icon="@drawable/ic_language"
app:text="@string/app_translators"/>
<com.topjohnwu.magisk.components.AboutCardRow
<a.o
android:id="@+id/follow_twitter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:icon="@drawable/ic_twitter"
app:text="@string/follow_twitter"/>
<com.topjohnwu.magisk.components.AboutCardRow
<a.o
android:id="@+id/app_source_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:icon="@drawable/ic_github"
app:text="@string/app_source_code"/>
<com.topjohnwu.magisk.components.AboutCardRow
<a.o
android:id="@+id/support_thread"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -98,7 +98,7 @@
</LinearLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
</LinearLayout>

View File

@@ -20,7 +20,7 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
@@ -40,14 +40,14 @@
android:text="@string/donation"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"/>
<com.topjohnwu.magisk.components.AboutCardRow
<a.o
android:id="@+id/paypal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:icon="@drawable/ic_paypal"
app:text="PayPal"/>
<com.topjohnwu.magisk.components.AboutCardRow
<a.o
android:id="@+id/patreon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -56,7 +56,7 @@
</LinearLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
</LinearLayout>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
@@ -24,7 +24,7 @@
</FrameLayout>
<android.support.design.widget.NavigationView
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
@@ -32,4 +32,4 @@
android:fitsSystemWindows="true"
app:menu="@menu/drawer" />
</android.support.v4.widget.DrawerLayout>
</androidx.drawerlayout.widget.DrawerLayout>

View File

@@ -3,7 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/su_popup"
tools:context=".superuser.RequestActivity"
tools:context=".SuRequestActivity"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="350dp"

View File

@@ -7,7 +7,7 @@
android:orientation="vertical"
tools:context="com.topjohnwu.magisk.fragments.LogFragment">
<android.support.design.widget.TabLayout
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
@@ -17,10 +17,10 @@
android:elevation="4dp"
android:visibility="gone">
</android.support.design.widget.TabLayout>
</com.google.android.material.tabs.TabLayout>
<android.support.v4.view.ViewPager
<androidx.viewpager.widget.ViewPager
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/container"/>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/swipeRefreshLayout"
@@ -18,7 +18,7 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
android:id="@+id/core_only_notice"
style="?attr/cardStyle"
android:layout_width="match_parent"
@@ -55,9 +55,9 @@
android:text="@string/settings_core_only_title"
android:textStyle="bold" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
style="?attr/cardStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -141,9 +141,9 @@
</LinearLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
android:id="@+id/safetyNet_card"
style="?attr/cardStyle"
android:layout_width="match_parent"
@@ -259,9 +259,9 @@
</LinearLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
android:id="@+id/install_option_card"
style="?attr/cardStyle"
android:layout_width="match_parent"
@@ -308,9 +308,9 @@
android:text="@string/keep_dm_verity" />
</LinearLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
android:id="@+id/install_button"
style="?attr/cardStyle"
android:layout_width="match_parent"
@@ -361,9 +361,9 @@
</RelativeLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
android:id="@+id/uninstall_button"
style="?attr/cardStyle"
android:layout_width="match_parent"
@@ -392,10 +392,10 @@
android:textSize="20sp"
android:textStyle="bold" />
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
</LinearLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/swipeRefreshLayout"
@@ -12,15 +12,15 @@ android:orientation="vertical">
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:dividerHeight="@dimen/card_divider_space"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
@@ -9,20 +9,20 @@
android:orientation="vertical">
<android.support.design.widget.CoordinatorLayout
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:dividerHeight="@dimen/card_divider_space"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<TextView
android:id="@+id/empty_rv"
@@ -36,7 +36,7 @@
android:textStyle="italic"
android:visibility="gone" />
<android.support.design.widget.FloatingActionButton
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -47,6 +47,6 @@
tools:fabSize="normal"
tools:pressedTranslationZ="12dp" />
</android.support.design.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</android.support.v4.widget.SwipeRefreshLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout"
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
@@ -23,13 +23,13 @@
android:textStyle="italic"
android:visibility="gone" />
<android.support.v7.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="@dimen/card_divider_space"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@@ -18,11 +18,11 @@
android:textStyle="italic"
android:visibility="gone" />
<android.support.v7.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="@dimen/card_divider_space"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>

View File

@@ -17,11 +17,11 @@
android:textStyle="italic"
android:visibility="gone" />
<android.support.v7.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="@dimen/card_divider_space"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
<androidx.cardview.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"
@@ -73,6 +73,6 @@
</LinearLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
@@ -110,4 +110,4 @@
</RelativeLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
style="?attr/cardStyle"
@@ -167,6 +167,6 @@
</LinearLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
style="?attr/cardStyle"
@@ -93,6 +93,6 @@
</LinearLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
style="?attr/cardStyle"
@@ -140,6 +140,6 @@
</LinearLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar android:id="@+id/toolbar"
<androidx.appcompat.widget.Toolbar android:id="@+id/toolbar"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"

View File

@@ -1,9 +1,7 @@
### v5.9.0
- No more on boot notifications
- Support new mechanism for installing to inactive slot for OTAs on A/B devices
- Fix restore Magisk Manager settings on Android P
- Verify existing file checksums to prevent unnecessary re-downloads
- Update SNET extension to use new Google API, fix "Invalid Response" errors
- Move fingerprint settings to magisk database to prevent the settings to be easily removed
- Fingerprint settings are now guarded with fingerprint authentications before it can get changed
- Prevent any files to be downloaded to `/sdcard/MagiskManager`
### 6.0.0
- Update to latest AndroidX support library
- Fix crashes when online repos contain incomplete metadata
- Optimize BootSigner to use as little memory as possible, prevent OutOfMemoryError
- Support new communication scheme between Magisk v17.2 and Magisk Manager
- Enable excessive obfuscation to prevent APK analysis root detections (still not 100% obfuscated due to backwards compatibility with stable channel)

View File

@@ -10,11 +10,11 @@
<!--Status Fragment-->
<string name="magisk_version_error">Magisk ist nicht installiert</string>
<string name="checking_for_updates">Suche nach Aktualisierungen</string>
<string name="checking_for_updates">Suche nach Aktualisierungen...</string>
<string name="magisk_update_available">Magisk %1$s ist verfügbar!</string>
<string name="invalid_update_channel">Nicht valider Aktualisierungskanal</string>
<string name="invalid_update_channel">Ungültiger Aktualisierungskanal</string>
<string name="safetyNet_check_text">SafetyNet-Status abfragen</string>
<string name="checking_safetyNet_status">Prüfe SafetyNet-Status</string>
<string name="checking_safetyNet_status">Prüfe SafetyNet-Status...</string>
<string name="safetyNet_check_success">SafetyNet-Test erfolgreich</string>
<string name="safetyNet_api_error">SafetyNet API Fehler</string>
<string name="safetyNet_res_invalid">Die Antwort ist ungültig</string>
@@ -27,7 +27,7 @@
<string name="install_magisk_title">Neueste Version: %1$s</string>
<string name="uninstall">Deinstallieren</string>
<string name="uninstall_magisk_title">Magisk deinstallieren</string>
<string name="uninstall_magisk_msg">Alle Module werden deaktiviert/entfernt. Root wird entfernt und wenn die Daten nicht verschlüsselt sind, werden sie möglicherweise verschlüsselt.</string>
<string name="uninstall_magisk_msg">Alle Module werden deaktiviert/entfernt. Root wird entfernt und möglicherweise werden Ihre Daten verschlüsseln, falls Ihre Daten derzeit nicht verschlüsselt sind.</string>
<string name="update">Aktualisierung %1$s</string>
<!--Module Fragment-->
@@ -39,7 +39,7 @@
<string name="disable_file_created">Modul wird beim nächsten Neustart deaktiviert</string>
<string name="disable_file_removed">Modul wird beim nächsten Neustart aktiviert</string>
<string name="author">Erstellt von %1$s</string>
<string name="reboot_recovery">Neustart in die Recovery</string>
<string name="reboot_recovery">Neustart in das Recovery</string>
<string name="reboot_bootloader">Neustart in den Bootloader</string>
<string name="reboot_download">Neustart in den Download-Modus</string>
@@ -50,24 +50,25 @@
<string name="updated_on">Zuletzt aktualisiert: %1$s</string>
<string name="sorting_order">Sortierung</string>
<string name="sort_by_name">Nach Namen sortiert</string>
<string name="sort_by_update">Nach Aktualisierung sortiert</string>
<string name="sort_by_update">Nach Aktualisierungsdatum sortiert</string>
<!--Log Fragment-->
<string name="menuSaveLog">Protokoll speichern</string>
<string name="menuSaveLog">Log speichern</string>
<string name="menuReload">Log erneut laden</string>
<string name="menuClearLog">Log löschen</string>
<string name="logs_cleared">Log gelöscht</string>
<string name="log_is_empty">Log ist leer</string>
<!--About Activity-->
<string name="about">Über</string>
<string name="app_changelog">Änderungen</string>
<string name="translators">skalnet, c727, jenslody</string>
<string name="about">Info</string>
<string name="app_changelog">Änderungsprotokoll</string>
<string name="translators">skalnet, c727, jenslody, SuperSandro2000</string>
<string name="app_version">Version</string>
<string name="app_source_code">Quelltext</string>
<string name="donation">Spende</string>
<string name="donation">Spenden</string>
<string name="app_translators">Übersetzer</string>
<string name="support_thread">Hilfeforum</string>
<string name="follow_twitter">Folge mir auf Twitter</string>
<!--Toasts, Dialogs-->
<string name="close">Schließen</string>
@@ -75,12 +76,12 @@
<string name="repo_install_msg">Möchtest du %1$s installieren?</string>
<string name="download">Herunterladen</string>
<string name="reboot">Neustart</string>
<string name="magisk_update_title">Neue Magisk-Aktualisierung verfügbar!</string>
<string name="settings_reboot_toast">Neustarten, um die Änderungen anzuwenden</string>
<string name="release_notes">Änderungen</string>
<string name="repo_cache_cleared">Repo-Cache gelöscht</string>
<string name="magisk_update_title">Neue Magisk Update verfügbar!</string>
<string name="settings_reboot_toast">Neustarten, um die Änderungen zu übernehmen</string>
<string name="release_notes">Versionshinweise</string>
<string name="repo_cache_cleared">Repo-Cache geleert</string>
<string name="process_error">Prozessfehler</string>
<string name="internal_storage">Die zip-Datei ist gespeichert unter:\n[Interner Speicher]%1$s</string>
<string name="internal_storage">Die Zip-Datei ist gespeichert unter:\n[Interner Speicher]%1$s</string>
<string name="zip_download_title">Herunterladen</string>
<string name="zip_download_msg">Lade Zip-Datei herunter (%1$d%%) …</string>
<string name="zip_process_title">Verarbeite</string>
@@ -88,30 +89,34 @@
<string name="manager_update_title">Aktualisierung für Magisk Manager verfügbar!</string>
<string name="manager_download_install">Herunterladen und installieren</string>
<string name="dtbo_patched_title">DTBO wurde gepatched!</string>
<string name="dtbo_patched_reboot">Magisk Manager hat dtbo.img gepatched, bitte Neustart durchführen</string>
<string name="magisk_updates">Magisk Aktualisierungen</string>
<string name="dtbo_patched_reboot">Magisk Manager hat dtbo.img gepatched, bitte neustarten</string>
<string name="magisk_updates">Magisk Update</string>
<string name="flashing">Flashing</string>
<string name="hide_manager_toast">Verberge Magisk Manager…</string>
<string name="hide_manager_toast2">Dies könnte einige Zeit in Anspruch nehmen…</string>
<string name="hide_manager_toast2">Das könnte einige Zeit dauern...</string>
<string name="hide_manager_fail_toast">Verbergen von Magisk Manager fehlgeschlagen…</string>
<string name="download_zip_only">Zip-Datei nur herunterladen</string>
<string name="open_link_failed_toast">Es wurde keine Anwendung gefunden, um diesen Link zu öffnen...</string>
<string name="download_zip_only">Nur Zip-Datei herunterladen</string>
<string name="patch_boot_file">Boot-Image-Datei patchen</string>
<string name="direct_install">Direkt installieren (empfohlen)</string>
<string name="install_inactive_slot">Installiere auf inaktiven Slot (Nach OTA)</string>
<string name="warning">Warnung</string>
<string name="install_inactive_slot_msg">Dein Gerät wird GEZWUNGEN in den aktuell inaktiven Slot zu starten, nachdem nach dem ein Neustart durchgeführt wurde!\nBenutze diese Option nur, nachdem das OTA beendet wurde.\nFortsetzen?</string>
<string name="select_method">Methode auswählen</string>
<string name="no_boot_file_patch_support">Magisk Zielversion unterstützt das Patchen des Boot-Images nicht</string>
<string name="boot_file_patch_msg">Selektiere das originale Boot image dump im Format .img oder .img.tar</string>
<string name="no_boot_file_patch_support">Magisk Zielversion unterstützt das Patchen von Boot-Images nicht</string>
<string name="boot_file_patch_msg">Wähle das original Boot-Image-Dump im Format .img oder .img.tar</string>
<string name="complete_uninstall">Komplette Deinstallation</string>
<string name="restore_img">Images wiederherstellen</string>
<string name="restore_img_msg">Wiederherstellen...</string>
<string name="restore_done">Wiederherstellung durchgeführt!</string>
<string name="restore_done">Wiederherstellung erfolgreich!</string>
<string name="restore_fail">Kein Original Backup vorhanden!</string>
<string name="proprietary_title">Lade proprietären Code herunter</string>
<string name="proprietary_notice">Magisk Manager ist FOSS und enthält keinen proprietären SafetyNet API Code von Google. Magisk Manager erlauben eine Erweiterung (enthält GoogleApiClient) für SafetyNet-Checks herunterzuladen?</string>
<string name="su_db_corrupt">Datenbank für SU ist fehlerhaft, es wird eine neue erstellt</string>
<string name="su_db_corrupt">SU-Datenbank ist fehlerhaft, es wird eine neue erstellt</string>
<string name="setup_done">Einrichtung abgeschlossen</string>
<string name="setup_fail">Einrichtung fehlgeschlagen</string>
<string name="env_fix_title">Zusätzliche Einrichtung erforderlich</string>
<string name="env_fix_msg">Um Magisk ordnungsgemäß zu nutzen, benötigt das Geräte eine zusätzliche Einrichtung. Magisk Einrichtungs-zip wird heruntergeladen, fortsetzen?</string>
<string name="env_fix_msg">Ihr Gerät benötigt zusätzliche Einrichtung, damit Magisk ordnungsgemäß funktioniert. Es wird eine Magisk-Installations-Zip wird heruntergeladen, fortfahren?</string>
<string name="setup_title">Zusätzliche Einrichtung</string>
<string name="setup_msg">Umgebungseinrichtung läuft…</string>
@@ -119,12 +124,12 @@
<string name="settings_general_category">Allgemein</string>
<string name="settings_dark_theme_title">Dunkles Theme</string>
<string name="settings_dark_theme_summary">Dunkles Theme aktivieren</string>
<string name="settings_clear_cache_title">Repo-Cache löschen</string>
<string name="settings_clear_cache_summary">Löscht die zwischengespeicherten Informationen der Online-Repos. Erzwingt eine Online-Aktualisierung</string>
<string name="settings_clear_cache_title">Repo-Cache leeren</string>
<string name="settings_clear_cache_summary">Löscht die zwischengespeicherten Informationen des Online-Repos. Erzwingt eine Aktualisierung</string>
<string name="settings_hide_manager_title">Magisk Manager verbergen</string>
<string name="settings_hide_manager_summary">Magisk Manager mit zufälligem Paketnamen neu packen</string>
<string name="settings_restore_manager_title">Stelle Magisk Manager wieder her</string>
<string name="settings_restore_manager_summary">Stelle Magisk Manager mit ursprünglichem Paket wieder her</string>
<string name="settings_restore_manager_title">Magisk Manager wiederherstellen</string>
<string name="settings_restore_manager_summary">Stellt Magisk Manager mit ursprünglichem Paketnamen wieder her</string>
<string name="language">Sprache</string>
<string name="system_default">(Systemstandard)</string>
<string name="settings_update">Aktualisierungs-Einstellungen</string>
@@ -134,13 +139,13 @@
<string name="settings_update_stable">Stabil</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Benutzerdefiniert</string>
<string name="settings_update_custom_msg">Gebe eine benutzerdefinierte URL ein</string>
<string name="settings_update_custom_msg">Gib eine benutzerdefinierte URL ein</string>
<string name="settings_boot_format_title">Ausgabeformat des gepatchten Boot-Images</string>
<string name="settings_boot_format_summary">Wähle das Ausgabeformat des gepatchten Boot-Images.\nWähle .img, um mit \"fastboot/download mode\" zu flashen; wähle .img.tar zum Flashen mit ODIN.</string>
<string name="settings_core_only_title">Nur Kernfunktionen</string>
<string name="settings_core_only_summary">Aktiviert lediglich die Kernfunktionen, Module werden nicht geladen. MagiskSU, Magisk Hide und Systemless hosts bleiben weiterhin aktiv</string>
<string name="settings_magiskhide_summary">Versteckt Magisk vor diversen Entdeckungsmethoden</string>
<string name="settings_hosts_title">Systemlose hosts-Datei</string>
<string name="settings_hosts_title">Systemlose Hosts-Datei</string>
<string name="settings_hosts_summary">Systemlose Unterstützung für Werbeblocker</string>
<string name="settings_su_app_adb">Apps und ADB</string>
@@ -160,6 +165,7 @@
<string name="settings_su_reauth_summary">Superuser-Zugriff nach App-Aktualisierung erneut abfragen</string>
<string name="settings_su_fingerprint_title">Aktiviere Authentifizierung durch Fingerabdruck</string>
<string name="settings_su_fingerprint_summary">Fingerabdrucksensor benutzen um Superuser-Anfragen zu erlauben</string>
<string name="auth_fingerprint">Authentifiziere Fingerabdruck</string>
<string name="multiuser_mode">Mehrbenutzermodus</string>
<string name="settings_owner_only">Nur der Gerätebesitzer</string>
@@ -168,15 +174,15 @@
<string name="owner_only_summary">Nur der Besitzer hat Root-Zugriff</string>
<string name="owner_manage_summary">Nur der Besitzer verwaltet den Root-Zugriff und erhält Zugriffs-Anfragen</string>
<string name="user_indepenent_summary">Jeder Nutzer hat seine eingenen Root-Regeln</string>
<string name="multiuser_hint_owner_request">Eine Anfrage wurde an den Gerätebesitzer gesendet. Bitte wechsle zum Bersitzerkonto und gewähre die Rechte</string>
<string name="multiuser_hint_owner_request">Eine Anfrage wurde an den Gerätebesitzer gesendet. Bitte wechsel zum Bersitzerkonto und gewähre die Rechte.</string>
<string name="mount_namespace_mode">Namensraum-Modus</string>
<string name="settings_ns_global">Globaler Namensraum</string>
<string name="settings_ns_requester">Geerbter Namensraum</string>
<string name="settings_ns_isolate">Isolierter Namensraum</string>
<string name="global_summary">Alle Root-Sitzungen benutzen den global angelegten Namensraum</string>
<string name="requester_summary">Root-Sitzungen erben den Namensraum des Abfragenden</string>
<string name="isolate_summary">Jede Root-Sitzung hat ihren isolierten Namensraum</string>
<string name="mount_namespace_mode">Mount-Namespace-Modus</string>
<string name="settings_ns_global">Globaler Namespace</string>
<string name="settings_ns_requester">Geerbter Namespace</string>
<string name="settings_ns_isolate">Isolierter Namespace</string>
<string name="global_summary">Alle Root-Sitzungen benutzen den global angelegten Namespace</string>
<string name="requester_summary">Root-Sitzungen erben den Namespace des Abfragenden</string>
<string name="isolate_summary">Jede Root-Sitzung hat ihren isolierten Namespace</string>
<string name="android_o_not_support">Android 8.0+ wird nicht unterstützt</string>
<string name="disable_fingerprint">Keine Fingerabdrücke gespeichert oder keine Geräteunterstützung</string>

View File

@@ -68,6 +68,7 @@
<string name="donation">Dons</string>
<string name="app_translators">Traducteurs de l\'application</string>
<string name="support_thread">Fil d\'assistance</string>
<string name="follow_twitter">Me suivre sur Twitter</string>
<!--Toasts, Dialogs-->
<string name="close">Fermer</string>
@@ -89,11 +90,12 @@
<string name="manager_download_install">Appuyer pour télécharger et installer</string>
<string name="dtbo_patched_title">DTBO a été patché!</string>
<string name="dtbo_patched_reboot">Le Gestionnaire Magisk a vient de patcher dtbo.img, merci de redémarrer</string>
<string name="magisk_updates">Mises à jours Magisk</string>
<string name="flashing">Flashage</string>
<string name="hide_manager_toast">Masquage du Gestionnaire Magisk…</string>
<string name="magisk_updates">Mises à jours Magisk</string>
<string name="flashing">Installation</string>
<string name="hide_manager_toast">Masquer le Gestionnaire Magisk…</string>
<string name="hide_manager_toast2">Cela pourrait prendre un certain temps …</string>
<string name="hide_manager_fail_toast">Masquage du Gestionnaire Magisk échoué…</string>
<string name="open_link_failed_toast">Aucune application trouvée pour ouvrir le lien…</string>
<string name="download_zip_only">Uniquement télécharger le zip</string>
<string name="patch_boot_file">Patch Fichier Image Démarrage</string>
<string name="direct_install">Installation directe (Recommendée)</string>
@@ -110,7 +112,7 @@
<string name="restore_fail">Le sauvegarde par défaut n\'existe pas!</string>
<string name="proprietary_title">Télécharger Code Propriétaire</string>
<string name="proprietary_notice">Magisk Manager est Libre, il ne contient pas le code API SafetyNet propriétaire de Google. \ N \ nAutorisez vous le Gestionnaire Magisk à télécharger une extension (contenant GoogleApiClient) pour les contrôles SafetyNet? </string>
<string name = "su_db_corrupt"> La base de données SU est corrompue, une nouvelle base de donnée va être re-créé</string>
<string name = "su_db_corrupt"> La base de données SU est corrompue, une nouvelle base de donnée va être re-créée</string>
<string name="setup_done">Installation terminée</string>
<string name="setup_fail">Échec de l\'installation</string>
<string name="env_fix_title">Installation additionnelle requise</string>
@@ -156,11 +158,11 @@
<string name="settings_su_request_60">60 secondes</string>
<string name="superuser_access">Accès Superuser</string>
<string name="auto_response">Réponse automatique</string>
<string name="request_timeout">Délai de requête</string>
<string name="request_timeout">Délai d\'attente de la demande</string>
<string name="superuser_notification">Notification Superutilisateur</string>
<string name="request_timeout_summary">%1$s secondes</string>
<string name="settings_su_reauth_title">Réauthentifier après la mise à niveau</string>
<string name="settings_su_reauth_summary">Réauthentifier les autorisations superutilisateur après une mise à jour de l\'application</string>
<string name="settings_su_reauth_title">Authentifier à nouveau après la mise à niveau</string>
<string name="settings_su_reauth_summary">Authentifier à nouveau les autorisations superutilisateur après une mise à jour de l\'application</string>
<string name="settings_su_fingerprint_title">Activer l\'authentification par empreinte digitale</string>
<string name="settings_su_fingerprint_summary">Utiliser le scanner d\'empreintes digitales pour autoriser les demandes superutilisateur</string>
<string name="auth_fingerprint">Authentifier l\'empreinte digitale</string>
@@ -181,7 +183,7 @@
<string name="global_summary">Toutes les sessions racines utilisent l\'espace de noms de montage global</string>
<string name="requester_summary">Les sessions racines hériteront de l\'espace de noms de son demandeur</string>
<string name="isolate_summary">Chaque session racine aura son propre espace de noms isolé</string>
<string name="android_o_not_support">Android 8.0+ n\'est pas supporté</string>
<string name="android_o_not_support">Android 8.0+ non supporté</string>
<string name="disable_fingerprint">Aucune empreinte digitale n\'a été définie ou aucun support de périphérique</string>
<!--Superuser-->

View File

@@ -67,6 +67,7 @@
<string name="donation">Donasi</string>
<string name="app_translators">Penerjemah</string>
<string name="support_thread">Thread dukungan</string>
<string name="follow_twitter">Ikuti saya di Twitter</string>
<!--Toasts, Dialogs-->
<string name="close">Tutup</string>
@@ -161,6 +162,7 @@
<string name="settings_su_reauth_summary">Otentikasi ulang izin superuser setelah pembaruan sebuah aplikasi</string>
<string name="settings_su_fingerprint_title">Aktifkan Otentikasi Sidik Jari</string>
<string name="settings_su_fingerprint_summary">Gunakan pemindai sidik jari untuk mengizinkan permintaan superuser</string>
<string name="auth_fingerprint">Otentikasi Sidik Jari</string>
<string name="multiuser_mode">Mode Multipengguna</string>
<string name="settings_owner_only">Pemilik Perangkat Saja</string>

View File

@@ -6,7 +6,7 @@
<string name="superuser">Superuser</string>
<string name="log">Záznamy</string>
<string name="settings">Nastavenia</string>
<string name="install">Inštalácia</string>
<string name="install">Inštalovať</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk nie je nainštalovaný</string>
@@ -74,7 +74,7 @@
<string name="repo_install_title">Nainštalovať %1$s</string>
<string name="repo_install_msg">Chcete teraz nainštalovať %1$s?</string>
<string name="download">Stiahnuť</string>
<string name="reboot">Reštartovať</string>
<string name="reboot">Reštart</string>
<string name="magisk_update_title">Nová aktualizácia Magisk!</string>
<string name="settings_reboot_toast">Pre aplikovanie nastavení je potrebný reštart</string>
<string name="release_notes">Poznámky k vydaniu</string>

View File

@@ -68,6 +68,7 @@
<string name="donation">Підтримати проект</string>
<string name="app_translators">Перекладачі</string>
<string name="support_thread">Сторінка підтримки</string>
<string name="follow_twitter">Читати мене в Twitter</string>
<!--Toasts, Dialogs-->
<string name="close">Закрити</string>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:tools="http://schemas.android.com/tools"
tools:discard="@raw/busybox_arm,@raw/busybox_x86" />

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