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