mirror of
				https://github.com/topjohnwu/Magisk
				synced 2025-10-31 10:40:52 +01:00 
			
		
		
		
	Compare commits
	
		
			49 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 018c0064cd | ||
|   | c2b016370b | ||
|   | fc791b4371 | ||
|   | f76bb009f4 | ||
|   | 8a1292b295 | ||
|   | d7d80d3fc1 | ||
|   | 41b01003fd | ||
|   | 6557070ae1 | ||
|   | e7e580e177 | ||
|   | dd9ddd2019 | ||
|   | 74aae523ba | ||
|   | 48c40f9516 | ||
|   | e0e7674715 | ||
|   | e1a65276b9 | ||
|   | 469adc85ad | ||
|   | e1b181ca4e | ||
|   | a4f0fbf8b7 | ||
|   | 190cdaddf8 | ||
|   | 5c4ba13839 | ||
|   | e62630cf3e | ||
|   | 36fe7846c0 | ||
|   | 8d150dd67a | ||
|   | 506df00d81 | ||
|   | a9121fa28f | ||
|   | d5a56d9e85 | ||
|   | acf7c0c665 | ||
|   | 619d48c97a | ||
|   | 2cb198c38c | ||
|   | e8e39e0f3c | ||
|   | 37860181d4 | ||
|   | d119dd9a0c | ||
|   | 09ef19f7ec | ||
|   | 6a06c92fa6 | ||
|   | 58ae596b0f | ||
|   | f1ca21678d | ||
|   | d7eeef2c8a | ||
|   | 4f626897f2 | ||
|   | b127e01845 | ||
|   | 2118beeb23 | ||
|   | 5020cd1bbf | ||
|   | cce636224c | ||
|   | 60b3b8ddce | ||
|   | 41446ec9ba | ||
|   | df8b047bca | ||
|   | 12ced52012 | ||
|   | 1d53335ae5 | ||
|   | 971a50d290 | ||
|   | 36dd9106a8 | ||
|   | 0a4ee3ffc7 | 
							
								
								
									
										22
									
								
								README.MD
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								README.MD
									
									
									
									
									
								
							| @@ -1,5 +1,13 @@ | ||||
| # Magisk | ||||
| [XDA Announcement Thread](https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445) | ||||
| [Downloads](https://github.com/topjohnwu/Magisk/releases) | [Documentation](https://topjohnwu.github.io/Magisk/) | [XDA Thread](https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445) | ||||
|  | ||||
| ## Introduction | ||||
| Magisk is a suite of open source tools for customizing Android, supporting devices higher than Android 5.0 (API 21). It covers the fundamental parts for Android customization: root, boot scripts, SELinux patches, AVB2.0 / dm-verity / forceencrypt removals etc. | ||||
|  | ||||
| Furthermore, Magisk provides a **Systemless Interface** to alter the system (or vendor) arbitrarily while the actual partitions stay completely intact. With its systemless nature along with several other hacks, Magisk can hide modifications from nearly any system integrity verifications used in banking apps, corporation monitoring apps, game cheat detections, and most importantly [Google's SafetyNet API](https://developer.android.com/training/safetynet/index.html). | ||||
|  | ||||
| ## Bug Reports | ||||
| **Make sure to install the latest [Canary Build](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337) before reporting any bugs!** **DO NOT** report bugs that is already fixed upstream. Follow the instructions in the [Canary Channel XDA Thread](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337), and report a bug either by opening an issue on GitHub or directly in the thread. | ||||
|  | ||||
| ## Building Environment Requirements | ||||
| 1. Python 3.5+: run `build.py` script | ||||
| @@ -15,20 +23,12 @@ | ||||
| 4. Run `build.py` with argument `-h` to see the built-in help message. The `-h` option also works for each supported actions, e.g. `./build.py binary -h` | ||||
| 5. By default, `build.py` build binaries and Magisk Manager in debug mode. If you want to build Magisk Manager in release mode (via the `-r, --release` flag), you need a Java Keystore file `release-key.jks` (only `JKS` format is supported) to sign APKs and zips. For more information, check out [Google's Official Documentation](https://developer.android.com/studio/publish/app-signing.html#signing-manually). | ||||
|  | ||||
| ## Bug Reports | ||||
| **Make sure to install the latest [Canary Build](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337) before reporting any bugs!** Please **DO NOT** report bugs that is already fixed upstream. | ||||
|  | ||||
| Follow the instructions in the [Canary Channel XDA Thread](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337), and report a bug either by opening an issue on GitHub or directly in the thread. | ||||
|  | ||||
| ## Documentation | ||||
| [Link to Documentation](docs/README.MD) | ||||
|  | ||||
| ## License | ||||
|  | ||||
| ``` | ||||
| Magisk, including all git submodules are free software: | ||||
| you can redistribute it and/or modify it under the terms of the  | ||||
| GNU General Public License as published by the Free Software Foundation,  | ||||
| you can redistribute it and/or modify it under the terms of the | ||||
| GNU General Public License as published by the Free Software Foundation, | ||||
| either version 3 of the License, or (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
|   | ||||
| @@ -79,4 +79,12 @@ dependencies { | ||||
|     fullImplementation 'com.github.topjohnwu:libsu:2.0.2' | ||||
|     fullImplementation 'com.atlassian.commonmark:commonmark:0.11.0' | ||||
|     fullImplementation 'org.kamranzafar:jtar:2.3' | ||||
|  | ||||
|     def butterKnifeVersion = '9.0.0-rc1' | ||||
|     if (properties.containsKey('android.injected.invoked.from.ide')) { | ||||
|         fullImplementation "com.jakewharton:butterknife-reflect:${butterKnifeVersion}" | ||||
|     } else { | ||||
|         fullImplementation "com.jakewharton:butterknife-runtime:${butterKnifeVersion}" | ||||
|         fullAnnotationProcessor "com.jakewharton:butterknife-compiler:${butterKnifeVersion}" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -15,16 +15,17 @@ import java.util.Locale; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.appcompat.app.ActionBar; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class AboutActivity extends BaseActivity { | ||||
|  | ||||
|     Toolbar toolbar; | ||||
|     AboutCardRow appVersionInfo; | ||||
|     AboutCardRow appChangelog; | ||||
|     AboutCardRow appTranslators; | ||||
|     AboutCardRow appSourceCode; | ||||
|     AboutCardRow supportThread; | ||||
|     AboutCardRow twitter; | ||||
|     @BindView(R.id.toolbar) Toolbar toolbar; | ||||
|     @BindView(R.id.app_version_info) AboutCardRow appVersionInfo; | ||||
|     @BindView(R.id.app_changelog) AboutCardRow appChangelog; | ||||
|     @BindView(R.id.app_translators) AboutCardRow appTranslators; | ||||
|     @BindView(R.id.app_source_code) AboutCardRow appSourceCode; | ||||
|     @BindView(R.id.support_thread) AboutCardRow supportThread; | ||||
|     @BindView(R.id.follow_twitter) AboutCardRow twitter; | ||||
|  | ||||
|     @Override | ||||
|     public int getDarkTheme() { | ||||
| @@ -35,7 +36,7 @@ public class AboutActivity extends BaseActivity { | ||||
|     protected void onCreate(@Nullable Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_about); | ||||
|         ViewBinder.bind(this); | ||||
|         new AboutActivity_ViewBinding(this); | ||||
|  | ||||
|         setSupportActionBar(toolbar); | ||||
|         toolbar.setNavigationOnClickListener(view -> finish()); | ||||
|   | ||||
| @@ -41,7 +41,6 @@ public class Const { | ||||
|  | ||||
|     /* A list of apps that should not be shown as hide-able */ | ||||
|     public static final List<String> HIDE_BLACKLIST =  Arrays.asList( | ||||
|             "android", | ||||
|             Data.MM().getPackageName(), | ||||
|             "com.google.android.gms" | ||||
|     ); | ||||
| @@ -49,11 +48,6 @@ public class Const { | ||||
|     public static final int USER_ID = Process.myUid() / 100000; | ||||
|  | ||||
|     public static final class MAGISK_VER { | ||||
|         public static final int UNIFIED = 1300; | ||||
|         public static final int FBE_AWARE = 1410; | ||||
|         public static final int RESETPROP_PERSIST = 1436; | ||||
|         public static final int MANAGER_HIDE = 1440; | ||||
|         public static final int HIDDEN_PATH = 1460; | ||||
|         public static final int REMOVE_LEGACY_LINK = 1630; | ||||
|         public static final int SEPOL_REFACTOR = 1640; | ||||
|         public static final int FIX_ENV = 1650; | ||||
|   | ||||
| @@ -95,8 +95,7 @@ public class Data { | ||||
|         try { | ||||
|             magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0]; | ||||
|             magiskVersionCode = Integer.parseInt(ShellUtils.fastCmd("magisk -V")); | ||||
|             String s = ShellUtils.fastCmd((magiskVersionCode >= Const.MAGISK_VER.RESETPROP_PERSIST ? | ||||
|                     "resetprop -p " : "getprop ") + Const.MAGISKHIDE_PROP); | ||||
|             String s = ShellUtils.fastCmd(("resetprop -p ") + Const.MAGISKHIDE_PROP); | ||||
|             magiskHide = s.isEmpty() || Integer.parseInt(s) != 0; | ||||
|         } catch (NumberFormatException ignored) {} | ||||
|     } | ||||
|   | ||||
| @@ -10,12 +10,13 @@ import com.topjohnwu.magisk.utils.Utils; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.appcompat.app.ActionBar; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class DonationActivity extends BaseActivity { | ||||
|  | ||||
|     Toolbar toolbar; | ||||
|     AboutCardRow paypal; | ||||
|     AboutCardRow patreon; | ||||
|     @BindView(R.id.toolbar) Toolbar toolbar; | ||||
|     @BindView(R.id.paypal) AboutCardRow paypal; | ||||
|     @BindView(R.id.patreon) AboutCardRow patreon; | ||||
|  | ||||
|     @Override | ||||
|     public int getDarkTheme() { | ||||
| @@ -26,7 +27,7 @@ public class DonationActivity extends BaseActivity { | ||||
|     protected void onCreate(@Nullable Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_donation); | ||||
|         ViewBinder.bind(this); | ||||
|         new DonationActivity_ViewBinding(this); | ||||
|  | ||||
|         setSupportActionBar(toolbar); | ||||
|         toolbar.setNavigationOnClickListener(view -> finish()); | ||||
|   | ||||
| @@ -31,25 +31,25 @@ import java.util.Locale; | ||||
|  | ||||
| import androidx.appcompat.app.ActionBar; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import butterknife.BindView; | ||||
| import butterknife.OnClick; | ||||
|  | ||||
| public class FlashActivity extends BaseActivity { | ||||
|  | ||||
|     Toolbar toolbar; | ||||
|     TextView flashLogs; | ||||
|     public LinearLayout buttonPanel; | ||||
|     public Button reboot; | ||||
|     ScrollView sv; | ||||
|     @BindView(R.id.toolbar) Toolbar toolbar; | ||||
|     @BindView(R.id.txtLog) TextView flashLogs; | ||||
|     @BindView(R.id.button_panel) public LinearLayout buttonPanel; | ||||
|     @BindView(R.id.reboot) public Button reboot; | ||||
|     @BindView(R.id.scrollView) ScrollView sv; | ||||
|  | ||||
|     private List<String> logs; | ||||
|  | ||||
|     void dismiss() { | ||||
|         finish(); | ||||
|     } | ||||
|  | ||||
|     @OnClick(R.id.reboot) | ||||
|     void reboot() { | ||||
|         Shell.su("/system/bin/reboot").submit(); | ||||
|     } | ||||
|  | ||||
|     @OnClick(R.id.save_logs) | ||||
|     void saveLogs() { | ||||
|         runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> { | ||||
|             Calendar now = Calendar.getInstance(); | ||||
| @@ -82,7 +82,8 @@ public class FlashActivity extends BaseActivity { | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_flash); | ||||
|         ViewBinder.bind(this); | ||||
|         new FlashActivity_ViewBinding(this); | ||||
|  | ||||
|         setSupportActionBar(toolbar); | ||||
|         ActionBar ab = getSupportActionBar(); | ||||
|         if (ab != null) { | ||||
| @@ -133,13 +134,18 @@ public class FlashActivity extends BaseActivity { | ||||
|                 new InstallMagisk(this, console, logs, InstallMagisk.SECOND_SLOT_MODE).exec(); | ||||
|                 break; | ||||
|             case Const.Value.PATCH_BOOT: | ||||
|                 runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, | ||||
|                         () -> new InstallMagisk(this, console, logs, | ||||
|                                 intent.getParcelableExtra(Const.Key.FLASH_SET_BOOT)).exec()); | ||||
|                 new InstallMagisk(this, console, logs, | ||||
|                         intent.getParcelableExtra(Const.Key.FLASH_SET_BOOT)).exec(); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @OnClick(R.id.close) | ||||
|     @Override | ||||
|     public void finish() { | ||||
|         super.finish(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onBackPressed() { | ||||
|         // Prevent user accidentally press back button | ||||
|   | ||||
| @@ -38,7 +38,7 @@ public class MagiskManager extends ContainerApp { | ||||
|         Shell.Config.setInitializer(RootUtils.class); | ||||
|  | ||||
|         prefs = PreferenceManager.getDefaultSharedPreferences(this); | ||||
|         mDB = MagiskDatabaseHelper.getInstance(this); | ||||
|         mDB = MagiskDatabaseHelper.getInstance(); | ||||
|  | ||||
|         String pkg = mDB.getStrings(Const.Key.SU_MANAGER, null); | ||||
|         if (pkg != null && getPackageName().equals(Const.ORIG_PKG_NAME)) { | ||||
|   | ||||
| @@ -26,6 +26,7 @@ import androidx.appcompat.widget.Toolbar; | ||||
| import androidx.drawerlayout.widget.DrawerLayout; | ||||
| import androidx.fragment.app.Fragment; | ||||
| import androidx.fragment.app.FragmentTransaction; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class MainActivity extends BaseActivity | ||||
|         implements NavigationView.OnNavigationItemSelectedListener, Topic.Subscriber { | ||||
| @@ -34,9 +35,9 @@ public class MainActivity extends BaseActivity | ||||
|     private int mDrawerItem; | ||||
|     private static boolean fromShortcut = false; | ||||
|  | ||||
|     public Toolbar toolbar; | ||||
|     DrawerLayout drawer; | ||||
|     NavigationView navigationView; | ||||
|     @BindView(R.id.toolbar) public Toolbar toolbar; | ||||
|     @BindView(R.id.drawer_layout) DrawerLayout drawer; | ||||
|     @BindView(R.id.nav_view) NavigationView navigationView; | ||||
|  | ||||
|     private float toolbarElevation; | ||||
|  | ||||
| @@ -54,7 +55,7 @@ public class MainActivity extends BaseActivity | ||||
|  | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_main); | ||||
|         ViewBinder.bind(this); | ||||
|         new MainActivity_ViewBinding(this); | ||||
|  | ||||
|         setSupportActionBar(toolbar); | ||||
|  | ||||
| @@ -118,7 +119,6 @@ public class MainActivity extends BaseActivity | ||||
|     public void checkHideSection() { | ||||
|         Menu menu = navigationView.getMenu(); | ||||
|         menu.findItem(R.id.magiskhide).setVisible(Shell.rootAccess() && | ||||
|                 Data.magiskVersionCode >= Const.MAGISK_VER.UNIFIED && | ||||
|                 mm.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) | ||||
|   | ||||
| @@ -27,17 +27,18 @@ import java.io.IOException; | ||||
| import java.io.OutputStream; | ||||
|  | ||||
| import androidx.annotation.Nullable; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class SuRequestActivity extends BaseActivity { | ||||
|     LinearLayout suPopup; | ||||
|     Spinner timeout; | ||||
|     ImageView appIcon; | ||||
|     TextView appNameView; | ||||
|     TextView packageNameView; | ||||
|     Button grant_btn; | ||||
|     Button deny_btn; | ||||
|     ImageView fingerprintImg; | ||||
|     TextView warning; | ||||
|     @BindView(R.id.su_popup) LinearLayout suPopup; | ||||
|     @BindView(R.id.timeout) Spinner timeout; | ||||
|     @BindView(R.id.app_icon) ImageView appIcon; | ||||
|     @BindView(R.id.app_name) TextView appNameView; | ||||
|     @BindView(R.id.package_name) TextView packageNameView; | ||||
|     @BindView(R.id.grant_btn) Button grant_btn; | ||||
|     @BindView(R.id.deny_btn) Button deny_btn; | ||||
|     @BindView(R.id.fingerprint) ImageView fingerprintImg; | ||||
|     @BindView(R.id.warning) TextView warning; | ||||
|  | ||||
|     private SuConnector connector; | ||||
|     private Policy policy; | ||||
| @@ -157,7 +158,7 @@ public class SuRequestActivity extends BaseActivity { | ||||
|         } | ||||
|  | ||||
|         setContentView(R.layout.activity_request); | ||||
|         ViewBinder.bind(this); | ||||
|         new SuRequestActivity_ViewBinding(this); | ||||
|  | ||||
|         appIcon.setImageDrawable(policy.info.loadIcon(pm)); | ||||
|         appNameView.setText(policy.appName); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -3,8 +3,6 @@ package com.topjohnwu.magisk.adapters; | ||||
| import android.content.Context; | ||||
| import android.content.pm.ApplicationInfo; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.content.res.Configuration; | ||||
| import android.content.res.Resources; | ||||
| import android.os.AsyncTask; | ||||
| import android.text.TextUtils; | ||||
| import android.view.LayoutInflater; | ||||
| @@ -17,9 +15,8 @@ import android.widget.TextView; | ||||
|  | ||||
| import com.topjohnwu.magisk.Const; | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.utils.LocaleManager; | ||||
| import com.topjohnwu.magisk.utils.Topic; | ||||
| import com.topjohnwu.magisk.utils.Utils; | ||||
| import com.topjohnwu.superuser.Shell; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| @@ -29,6 +26,7 @@ import java.util.List; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.ViewHolder> { | ||||
|  | ||||
| @@ -52,25 +50,12 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter. | ||||
|         return new ViewHolder(v); | ||||
|     } | ||||
|  | ||||
|     private String getLabel(ApplicationInfo info) { | ||||
|         if (info.labelRes > 0) { | ||||
|             try { | ||||
|                 Resources res = pm.getResourcesForApplication(info); | ||||
|                 Configuration config = new Configuration(); | ||||
|                 config.setLocale(LocaleManager.locale); | ||||
|                 res.updateConfiguration(config, res.getDisplayMetrics()); | ||||
|                 return res.getString(info.labelRes); | ||||
|             } catch (PackageManager.NameNotFoundException ignored) { /* Impossible */ } | ||||
|         } | ||||
|         return info.loadLabel(pm).toString(); | ||||
|     } | ||||
|  | ||||
|     private void loadApps() { | ||||
|         fullList = pm.getInstalledApplications(0); | ||||
|         hideList = Shell.su("magiskhide --ls").exec().getOut(); | ||||
|         for (Iterator<ApplicationInfo> i = fullList.iterator(); i.hasNext(); ) { | ||||
|             ApplicationInfo info = i.next(); | ||||
|             if (Const.HIDE_BLACKLIST.contains(info.packageName) || !info.enabled) { | ||||
|             if (Const.HIDE_BLACKLIST.contains(info.packageName) || !info.enabled || info.uid == 1000) { | ||||
|                 i.remove(); | ||||
|             } | ||||
|         } | ||||
| @@ -78,7 +63,8 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter. | ||||
|             boolean ah = hideList.contains(a.packageName); | ||||
|             boolean bh = hideList.contains(b.packageName); | ||||
|             if (ah == bh) { | ||||
|                 return getLabel(a).toLowerCase().compareTo(getLabel(b).toLowerCase()); | ||||
|                 return Utils.getAppLabel(a, pm).toLowerCase() | ||||
|                         .compareTo(Utils.getAppLabel(b, pm).toLowerCase()); | ||||
|             } else if (ah) { | ||||
|                 return -1; | ||||
|             } else { | ||||
| @@ -93,7 +79,7 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter. | ||||
|         ApplicationInfo info = showList.get(position); | ||||
|  | ||||
|         holder.appIcon.setImageDrawable(info.loadIcon(pm)); | ||||
|         holder.appName.setText(getLabel(info)); | ||||
|         holder.appName.setText(Utils.getAppLabel(info, pm)); | ||||
|         holder.appPackage.setText(info.packageName); | ||||
|  | ||||
|         holder.checkBox.setOnCheckedChangeListener(null); | ||||
| @@ -122,20 +108,20 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter. | ||||
|         AsyncTask.THREAD_POOL_EXECUTOR.execute(this::loadApps); | ||||
|     } | ||||
|  | ||||
|     public static class ViewHolder extends RecyclerView.ViewHolder { | ||||
|     static class ViewHolder extends RecyclerView.ViewHolder { | ||||
|  | ||||
|         public ImageView appIcon; | ||||
|         public TextView appName; | ||||
|         public TextView appPackage; | ||||
|         public CheckBox checkBox; | ||||
|         @BindView(R.id.app_icon) ImageView appIcon; | ||||
|         @BindView(R.id.app_name) TextView appName; | ||||
|         @BindView(R.id.package_name) TextView appPackage; | ||||
|         @BindView(R.id.checkbox) CheckBox checkBox; | ||||
|  | ||||
|         ViewHolder(View itemView) { | ||||
|             super(itemView); | ||||
|             ViewBinder.bind(this, itemView); | ||||
|             new ApplicationAdapter$ViewHolder_ViewBinding(this, itemView); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private class ApplicationFilter extends Filter { | ||||
|     class ApplicationFilter extends Filter { | ||||
|  | ||||
|         private boolean lowercaseContains(String s, CharSequence filter) { | ||||
|             return !TextUtils.isEmpty(s) && s.toLowerCase().contains(filter); | ||||
| @@ -149,7 +135,7 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter. | ||||
|                 showList = new ArrayList<>(); | ||||
|                 String filter = constraint.toString().toLowerCase(); | ||||
|                 for (ApplicationInfo info : fullList) { | ||||
|                     if (lowercaseContains(getLabel(info), filter) | ||||
|                     if (lowercaseContains(Utils.getAppLabel(info, pm), filter) | ||||
|                             || lowercaseContains(info.packageName, filter)) { | ||||
|                         showList.add(info); | ||||
|                     } | ||||
|   | ||||
| @@ -11,14 +11,15 @@ import android.widget.TextView; | ||||
|  | ||||
| import com.google.android.material.snackbar.Snackbar; | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.components.SnackbarMaker; | ||||
| import com.topjohnwu.magisk.container.Module; | ||||
| import com.topjohnwu.superuser.Shell; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> { | ||||
|  | ||||
| @@ -28,6 +29,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold | ||||
|         mList = list; | ||||
|     } | ||||
|  | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | ||||
|         View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_module, parent, false); | ||||
| @@ -101,19 +103,19 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold | ||||
|         return mList.size(); | ||||
|     } | ||||
|  | ||||
|     public static class ViewHolder extends RecyclerView.ViewHolder { | ||||
|     static class ViewHolder extends RecyclerView.ViewHolder { | ||||
|  | ||||
|         public TextView title; | ||||
|         public TextView versionName; | ||||
|         public TextView description; | ||||
|         public TextView notice; | ||||
|         public CheckBox checkBox; | ||||
|         public TextView author; | ||||
|         public ImageView delete; | ||||
|         @BindView(R.id.title) TextView title; | ||||
|         @BindView(R.id.version_name) TextView versionName; | ||||
|         @BindView(R.id.description) TextView description; | ||||
|         @BindView(R.id.notice) TextView notice; | ||||
|         @BindView(R.id.checkbox) CheckBox checkBox; | ||||
|         @BindView(R.id.author) TextView author; | ||||
|         @BindView(R.id.delete) ImageView delete; | ||||
|  | ||||
|         ViewHolder(View itemView) { | ||||
|             super(itemView); | ||||
|             ViewBinder.bind(this, itemView); | ||||
|             new ModulesAdapter$ViewHolder_ViewBinding(this, itemView); | ||||
|  | ||||
|             if (!Shell.rootAccess()) { | ||||
|                 checkBox.setEnabled(false); | ||||
|   | ||||
| @@ -10,19 +10,22 @@ import android.widget.Switch; | ||||
| import android.widget.TextView; | ||||
|  | ||||
| import com.google.android.material.snackbar.Snackbar; | ||||
| import com.topjohnwu.magisk.Data; | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.components.CustomAlertDialog; | ||||
| import com.topjohnwu.magisk.components.ExpandableView; | ||||
| import com.topjohnwu.magisk.components.SnackbarMaker; | ||||
| import com.topjohnwu.magisk.container.Policy; | ||||
| import com.topjohnwu.magisk.database.MagiskDatabaseHelper; | ||||
| import com.topjohnwu.magisk.utils.FingerprintHelper; | ||||
|  | ||||
| import java.util.HashSet; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder> { | ||||
|  | ||||
| @@ -37,6 +40,7 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder | ||||
|         this.pm = pm; | ||||
|     } | ||||
|  | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | ||||
|         View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_policy, parent, false); | ||||
| @@ -62,14 +66,34 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder | ||||
|         holder.appName.setText(policy.appName); | ||||
|         holder.packageName.setText(policy.packageName); | ||||
|         holder.appIcon.setImageDrawable(policy.info.loadIcon(pm)); | ||||
|         holder.masterSwitch.setOnCheckedChangeListener((v, isChecked) -> { | ||||
|             if ((isChecked && policy.policy == Policy.DENY) || | ||||
|                     (!isChecked && policy.policy == Policy.ALLOW)) { | ||||
|                 policy.policy = isChecked ? Policy.ALLOW : Policy.DENY; | ||||
|                 String message = v.getContext().getString( | ||||
|                         isChecked ? R.string.su_snack_grant : R.string.su_snack_deny, policy.appName); | ||||
|                 SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show(); | ||||
|                 dbHelper.updatePolicy(policy); | ||||
|  | ||||
|         holder.notificationSwitch.setOnCheckedChangeListener(null); | ||||
|         holder.loggingSwitch.setOnCheckedChangeListener(null); | ||||
|  | ||||
|         holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW); | ||||
|         holder.notificationSwitch.setChecked(policy.notification); | ||||
|         holder.loggingSwitch.setChecked(policy.logging); | ||||
|  | ||||
|         holder.masterSwitch.setOnClickListener(v -> { | ||||
|             boolean isChecked = holder.masterSwitch.isChecked(); | ||||
|             Runnable r = () -> { | ||||
|                 if ((isChecked && policy.policy == Policy.DENY) || | ||||
|                         (!isChecked && policy.policy == Policy.ALLOW)) { | ||||
|                     policy.policy = isChecked ? Policy.ALLOW : Policy.DENY; | ||||
|                     String message = v.getContext().getString( | ||||
|                             isChecked ? R.string.su_snack_grant : R.string.su_snack_deny, policy.appName); | ||||
|                     SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show(); | ||||
|                     dbHelper.updatePolicy(policy); | ||||
|                 } | ||||
|             }; | ||||
|             if (Data.suFingerprint) { | ||||
|                 holder.masterSwitch.setChecked(!isChecked); | ||||
|                 FingerprintHelper.showAuthDialog((Activity) v.getContext(), () -> { | ||||
|                     holder.masterSwitch.setChecked(isChecked); | ||||
|                     r.run(); | ||||
|                 }); | ||||
|             } else { | ||||
|                 r.run(); | ||||
|             } | ||||
|         }); | ||||
|         holder.notificationSwitch.setOnCheckedChangeListener((v, isChecked) -> { | ||||
| @@ -106,9 +130,6 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder | ||||
|                 .setNegativeButton(R.string.no_thanks, null) | ||||
|                 .setCancelable(true) | ||||
|                 .show()); | ||||
|         holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW); | ||||
|         holder.notificationSwitch.setChecked(policy.notification); | ||||
|         holder.loggingSwitch.setChecked(policy.logging); | ||||
|  | ||||
|         // Hide for now | ||||
|         holder.moreInfo.setVisibility(View.GONE); | ||||
| @@ -119,24 +140,24 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder | ||||
|         return policyList.size(); | ||||
|     } | ||||
|  | ||||
|     public static class ViewHolder extends RecyclerView.ViewHolder implements ExpandableView { | ||||
|     static class ViewHolder extends RecyclerView.ViewHolder implements ExpandableView { | ||||
|  | ||||
|         public TextView appName; | ||||
|         public TextView packageName; | ||||
|         public ImageView appIcon; | ||||
|         public Switch masterSwitch; | ||||
|         public Switch notificationSwitch; | ||||
|         public Switch loggingSwitch; | ||||
|         public ViewGroup expandLayout; | ||||
|         @BindView(R.id.app_name) TextView appName; | ||||
|         @BindView(R.id.package_name) TextView packageName; | ||||
|         @BindView(R.id.app_icon) ImageView appIcon; | ||||
|         @BindView(R.id.master_switch) Switch masterSwitch; | ||||
|         @BindView(R.id.notification_switch) Switch notificationSwitch; | ||||
|         @BindView(R.id.logging_switch) Switch loggingSwitch; | ||||
|         @BindView(R.id.expand_layout) ViewGroup expandLayout; | ||||
|  | ||||
|         public ImageView delete; | ||||
|         public ImageView moreInfo; | ||||
|         @BindView(R.id.delete) ImageView delete; | ||||
|         @BindView(R.id.more_info) ImageView moreInfo; | ||||
|  | ||||
|         private Container container = new Container(); | ||||
|  | ||||
|         public ViewHolder(View itemView) { | ||||
|             super(itemView); | ||||
|             ViewBinder.bind(this, itemView); | ||||
|             new PolicyAdapter$ViewHolder_ViewBinding(this, itemView); | ||||
|             container.expandLayout = expandLayout; | ||||
|             setupExpandable(); | ||||
|         } | ||||
|   | ||||
| @@ -12,7 +12,6 @@ import android.widget.LinearLayout; | ||||
| import android.widget.TextView; | ||||
|  | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.asyncs.MarkDownWindow; | ||||
| import com.topjohnwu.magisk.asyncs.ProcessRepoZip; | ||||
| import com.topjohnwu.magisk.components.BaseActivity; | ||||
| @@ -26,6 +25,7 @@ import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, ReposAdapter.RepoHolder> { | ||||
|  | ||||
| @@ -163,29 +163,29 @@ public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, R | ||||
|         notifyDataSetChanged(); | ||||
|     } | ||||
|  | ||||
|     public static class SectionHolder extends RecyclerView.ViewHolder { | ||||
|     static class SectionHolder extends RecyclerView.ViewHolder { | ||||
|  | ||||
|         public TextView sectionText; | ||||
|         @BindView(R.id.section_text) TextView sectionText; | ||||
|  | ||||
|         SectionHolder(View itemView) { | ||||
|             super(itemView); | ||||
|             ViewBinder.bind(this, itemView); | ||||
|             new ReposAdapter$SectionHolder_ViewBinding(this, itemView); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static class RepoHolder extends RecyclerView.ViewHolder { | ||||
|     static class RepoHolder extends RecyclerView.ViewHolder { | ||||
|  | ||||
|         public TextView title; | ||||
|         public TextView versionName; | ||||
|         public TextView description; | ||||
|         public TextView author; | ||||
|         public LinearLayout infoLayout; | ||||
|         public ImageView downloadImage; | ||||
|         public TextView updateTime; | ||||
|         @BindView(R.id.title) TextView title; | ||||
|         @BindView(R.id.version_name) TextView versionName; | ||||
|         @BindView(R.id.description) TextView description; | ||||
|         @BindView(R.id.author) TextView author; | ||||
|         @BindView(R.id.info_layout) LinearLayout infoLayout; | ||||
|         @BindView(R.id.download) ImageView downloadImage; | ||||
|         @BindView(R.id.update_time) TextView updateTime; | ||||
|  | ||||
|         RepoHolder(View itemView) { | ||||
|             super(itemView); | ||||
|             ViewBinder.bind(this, itemView); | ||||
|             new ReposAdapter$RepoHolder_ViewBinding(this, itemView); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|   | ||||
| @@ -10,7 +10,6 @@ import android.widget.ImageView; | ||||
| import android.widget.TextView; | ||||
|  | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.components.ExpandableView; | ||||
| import com.topjohnwu.magisk.container.SuLogEntry; | ||||
| import com.topjohnwu.magisk.database.MagiskDatabaseHelper; | ||||
| @@ -21,6 +20,7 @@ import java.util.List; | ||||
| import java.util.Set; | ||||
|  | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, SuLogAdapter.LogViewHolder> { | ||||
|  | ||||
| @@ -116,32 +116,32 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S | ||||
|         notifyDataSetChanged(); | ||||
|     } | ||||
|  | ||||
|     public static class SectionHolder extends RecyclerView.ViewHolder { | ||||
|     static class SectionHolder extends RecyclerView.ViewHolder { | ||||
|  | ||||
|         public TextView date; | ||||
|         public ImageView arrow; | ||||
|         @BindView(R.id.date) TextView date; | ||||
|         @BindView(R.id.arrow) ImageView arrow; | ||||
|  | ||||
|         SectionHolder(View itemView) { | ||||
|             super(itemView); | ||||
|             ViewBinder.bind(this, itemView); | ||||
|             new SuLogAdapter$SectionHolder_ViewBinding(this, itemView); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static class LogViewHolder extends RecyclerView.ViewHolder implements ExpandableView { | ||||
|     static class LogViewHolder extends RecyclerView.ViewHolder implements ExpandableView { | ||||
|  | ||||
|         public TextView appName; | ||||
|         public TextView action; | ||||
|         public TextView time; | ||||
|         public TextView fromPid; | ||||
|         public TextView toUid; | ||||
|         public TextView command; | ||||
|         public ViewGroup expandLayout; | ||||
|         @BindView(R.id.app_name) TextView appName; | ||||
|         @BindView(R.id.action) TextView action; | ||||
|         @BindView(R.id.time) TextView time; | ||||
|         @BindView(R.id.fromPid) TextView fromPid; | ||||
|         @BindView(R.id.toUid) TextView toUid; | ||||
|         @BindView(R.id.command) TextView command; | ||||
|         @BindView(R.id.expand_layout) ViewGroup expandLayout; | ||||
|  | ||||
|         private Container container = new Container(); | ||||
|  | ||||
|         LogViewHolder(View itemView) { | ||||
|             super(itemView); | ||||
|             ViewBinder.bind(this, itemView); | ||||
|             new SuLogAdapter$LogViewHolder_ViewBinding(this, itemView); | ||||
|             container.expandLayout = expandLayout; | ||||
|             setupExpandable(); | ||||
|         } | ||||
|   | ||||
| @@ -111,6 +111,7 @@ public class PatchAPK { | ||||
|         repack.delete(); | ||||
|  | ||||
|         mm.mDB.setStrings(Const.Key.SU_MANAGER, pkg); | ||||
|         mm.mDB.flush(); | ||||
|         Data.exportPrefs(); | ||||
|         RootUtils.uninstallPkg(Const.ORIG_PKG_NAME); | ||||
|  | ||||
|   | ||||
| @@ -66,17 +66,15 @@ public class UpdateRepos { | ||||
|  | ||||
|         for (int i = 0; i < jsonArray.length(); i++) { | ||||
|             JSONObject rawRepo = jsonArray.getJSONObject(i); | ||||
|             String id = rawRepo.getString("description"); | ||||
|             String name = rawRepo.getString("name"); | ||||
|             String id = rawRepo.getString("name"); | ||||
|             Date date = dateFormat.parse(rawRepo.getString("pushed_at")); | ||||
|             Set<String> set = Collections.synchronizedSet(cached); | ||||
|             threadPool.execute(() -> { | ||||
|                 Repo repo = mm.repoDB.getRepo(id); | ||||
|                 try { | ||||
|                     if (repo == null) | ||||
|                         repo = new Repo(name); | ||||
|                         repo = new Repo(id); | ||||
|                     else | ||||
|                         set.remove(id); | ||||
|                         cached.remove(id); | ||||
|                     repo.update(date); | ||||
|                     mm.repoDB.addRepo(repo); | ||||
|                 } catch (Repo.IllegalRepoException e) { | ||||
| @@ -141,7 +139,7 @@ public class UpdateRepos { | ||||
|     public void exec(boolean force) { | ||||
|         Topic.reset(Topic.REPO_LOAD_DONE); | ||||
|         AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { | ||||
|             cached = mm.repoDB.getRepoIDSet(); | ||||
|             cached = Collections.synchronizedSet(mm.repoDB.getRepoIDSet()); | ||||
|             threadPool = Executors.newFixedThreadPool(CORE_POOL_SIZE); | ||||
|  | ||||
|             if (loadPage(0)) { | ||||
|   | ||||
| @@ -27,17 +27,18 @@ import android.widget.LinearLayout; | ||||
| import android.widget.TextView; | ||||
|  | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
|  | ||||
| import butterknife.BindView; | ||||
|  | ||||
| /** | ||||
|  * @author dvdandroid | ||||
|  */ | ||||
| public class AboutCardRow extends LinearLayout { | ||||
|  | ||||
|     public TextView mTitle; | ||||
|     public TextView mSummary; | ||||
|     public ImageView mIcon; | ||||
|     public View mView; | ||||
|     @BindView(android.R.id.title) TextView mTitle; | ||||
|     @BindView(android.R.id.summary) TextView mSummary; | ||||
|     @BindView(android.R.id.icon) ImageView mIcon; | ||||
|     @BindView(R.id.container) View mView; | ||||
|  | ||||
|     public AboutCardRow(Context context) { | ||||
|         this(context, null); | ||||
| @@ -50,7 +51,7 @@ public class AboutCardRow extends LinearLayout { | ||||
|     public AboutCardRow(Context context, AttributeSet attrs, int defStyleAttr) { | ||||
|         super(context, attrs, defStyleAttr); | ||||
|         LayoutInflater.from(context).inflate(R.layout.info_item_row, this); | ||||
|         ViewBinder.bind(this, this); | ||||
|         new AboutCardRow_ViewBinding(this, this); | ||||
|  | ||||
|         TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AboutCardRow, 0, 0); | ||||
|         String title; | ||||
|   | ||||
| @@ -7,10 +7,12 @@ import com.topjohnwu.magisk.MagiskManager; | ||||
| import com.topjohnwu.magisk.utils.Topic; | ||||
|  | ||||
| import androidx.fragment.app.Fragment; | ||||
| import butterknife.Unbinder; | ||||
|  | ||||
| public class BaseFragment extends Fragment implements Topic.AutoSubscriber { | ||||
|  | ||||
|     public MagiskManager mm; | ||||
|     protected Unbinder unbinder = null; | ||||
|  | ||||
|     public BaseFragment() { | ||||
|         mm = Data.MM(); | ||||
| @@ -28,6 +30,13 @@ public class BaseFragment extends Fragment implements Topic.AutoSubscriber { | ||||
|         super.onPause(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroyView() { | ||||
|         super.onDestroyView(); | ||||
|         if (unbinder != null) | ||||
|             unbinder.unbind(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void startActivityForResult(Intent intent, int requestCode) { | ||||
|         startActivityForResult(intent, requestCode, this::onActivityResult); | ||||
|   | ||||
| @@ -9,13 +9,13 @@ import android.widget.LinearLayout; | ||||
| import android.widget.TextView; | ||||
|  | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.annotation.StringRes; | ||||
| import androidx.annotation.StyleRes; | ||||
| import androidx.appcompat.app.AlertDialog; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class CustomAlertDialog extends AlertDialog.Builder { | ||||
|  | ||||
| @@ -27,16 +27,16 @@ public class CustomAlertDialog extends AlertDialog.Builder { | ||||
|     private ViewHolder vh; | ||||
|  | ||||
|     public class ViewHolder { | ||||
|         public LinearLayout dialogLayout; | ||||
|         public LinearLayout buttons; | ||||
|         @BindView(R.id.dialog_layout) public LinearLayout dialogLayout; | ||||
|         @BindView(R.id.button_panel) public LinearLayout buttons; | ||||
|  | ||||
|         public TextView messageView; | ||||
|         public Button negative; | ||||
|         public Button positive; | ||||
|         public Button neutral; | ||||
|         @BindView(R.id.message) public TextView messageView; | ||||
|         @BindView(R.id.negative) public Button negative; | ||||
|         @BindView(R.id.positive) public Button positive; | ||||
|         @BindView(R.id.neutral) public Button neutral; | ||||
|  | ||||
|         ViewHolder(View v) { | ||||
|             ViewBinder.bind(this, v); | ||||
|             new CustomAlertDialog$ViewHolder_ViewBinding(this, v); | ||||
|             messageView.setVisibility(View.GONE); | ||||
|             negative.setVisibility(View.GONE); | ||||
|             positive.setVisibility(View.GONE); | ||||
|   | ||||
| @@ -1,11 +1,12 @@ | ||||
| package com.topjohnwu.magisk.components; | ||||
|  | ||||
| import android.Manifest; | ||||
| import android.app.Activity; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.net.Uri; | ||||
| import android.widget.Toast; | ||||
|  | ||||
| import com.google.android.material.snackbar.Snackbar; | ||||
| import com.topjohnwu.magisk.Const; | ||||
| import com.topjohnwu.magisk.Data; | ||||
| import com.topjohnwu.magisk.FlashActivity; | ||||
| @@ -27,23 +28,21 @@ class InstallMethodDialog extends AlertDialog.Builder { | ||||
|             Intent intent; | ||||
|             switch (idx) { | ||||
|                 case 1: | ||||
|                     if (Data.remoteMagiskVersionCode < 1400) { | ||||
|                         SnackbarMaker.make(activity, R.string.no_boot_file_patch_support, | ||||
|                                 Snackbar.LENGTH_LONG).show(); | ||||
|                         return; | ||||
|                     } | ||||
|                     Utils.toast(R.string.boot_file_patch_msg, Toast.LENGTH_LONG); | ||||
|                     intent = new Intent(Intent.ACTION_GET_CONTENT).setType("*/*"); | ||||
|                     activity.startActivityForResult(intent, Const.ID.SELECT_BOOT, | ||||
|                             (requestCode, resultCode, data) -> { | ||||
|                                 if (requestCode == Const.ID.SELECT_BOOT && | ||||
|                                         resultCode == BaseActivity.RESULT_OK && data != null) { | ||||
|                                     Intent i = new Intent(activity, Data.classMap.get(FlashActivity.class)) | ||||
|                                             .putExtra(Const.Key.FLASH_SET_BOOT, data.getData()) | ||||
|                                             .putExtra(Const.Key.FLASH_ACTION, Const.Value.PATCH_BOOT); | ||||
|                                     activity.startActivity(i); | ||||
|                                 } | ||||
|                             }); | ||||
|                     activity.runWithPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> | ||||
|                         activity.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(activity, Data.classMap.get(FlashActivity.class)) | ||||
|                                         .putExtra(Const.Key.FLASH_SET_BOOT, data.getData()) | ||||
|                                         .putExtra(Const.Key.FLASH_ACTION, Const.Value.PATCH_BOOT); | ||||
|                                 activity.startActivity(i); | ||||
|                             } | ||||
|                         }) | ||||
|                     ); | ||||
|  | ||||
|                     break; | ||||
|                 case 0: | ||||
|                     String filename = Utils.fmt("Magisk-v%s(%d).zip", | ||||
| @@ -62,16 +61,16 @@ class InstallMethodDialog extends AlertDialog.Builder { | ||||
|                     break; | ||||
|                 case 3: | ||||
|                     new CustomAlertDialog(activity) | ||||
|                             .setTitle(R.string.warning) | ||||
|                             .setMessage(R.string.install_inactive_slot_msg) | ||||
|                             .setCancelable(true) | ||||
|                             .setPositiveButton(R.string.yes, (d, i) -> { | ||||
|                                 Intent it = new Intent(activity, Data.classMap.get(FlashActivity.class)) | ||||
|                                         .putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_INACTIVE_SLOT); | ||||
|                                 activity.startActivity(it); | ||||
|                             }) | ||||
|                             .setNegativeButton(R.string.no_thanks, null) | ||||
|                             .show(); | ||||
|                         .setTitle(R.string.warning) | ||||
|                         .setMessage(R.string.install_inactive_slot_msg) | ||||
|                         .setCancelable(true) | ||||
|                         .setPositiveButton(R.string.yes, (d, i) -> { | ||||
|                             Intent it = new Intent(activity, Data.classMap.get(FlashActivity.class)) | ||||
|                                     .putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_INACTIVE_SLOT); | ||||
|                             activity.startActivity(it); | ||||
|                         }) | ||||
|                         .setNegativeButton(R.string.no_thanks, null) | ||||
|                         .show(); | ||||
|                     break; | ||||
|                 default: | ||||
|             } | ||||
|   | ||||
| @@ -5,6 +5,8 @@ import android.content.pm.ApplicationInfo; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.database.Cursor; | ||||
|  | ||||
| import com.topjohnwu.magisk.utils.Utils; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
|  | ||||
|  | ||||
| @@ -26,7 +28,7 @@ public class Policy implements Comparable<Policy>{ | ||||
|         this.uid = uid; | ||||
|         packageName = pkgs[0]; | ||||
|         info = pm.getApplicationInfo(packageName, 0); | ||||
|         appName = info.loadLabel(pm).toString(); | ||||
|         appName = Utils.getAppLabel(info, pm); | ||||
|     } | ||||
|  | ||||
|     public Policy(Cursor c, PackageManager pm) throws PackageManager.NameNotFoundException { | ||||
|   | ||||
| @@ -2,7 +2,6 @@ package com.topjohnwu.magisk.container; | ||||
|  | ||||
| import android.content.ContentValues; | ||||
| import android.database.Cursor; | ||||
| import android.text.TextUtils; | ||||
|  | ||||
| import com.topjohnwu.magisk.Const; | ||||
| import com.topjohnwu.magisk.utils.Download; | ||||
| @@ -15,16 +14,14 @@ import java.util.Date; | ||||
|  | ||||
| public class Repo extends BaseModule { | ||||
|  | ||||
|     private String repoName; | ||||
|     private Date mLastUpdate; | ||||
|  | ||||
|     public Repo(String name) { | ||||
|         repoName = name; | ||||
|     public Repo(String id) { | ||||
|         setId(id); | ||||
|     } | ||||
|  | ||||
|     public Repo(Cursor c) { | ||||
|         super(c); | ||||
|         repoName = c.getString(c.getColumnIndex("repo_name")); | ||||
|         mLastUpdate = new Date(c.getLong(c.getColumnIndex("last_update"))); | ||||
|     } | ||||
|  | ||||
| @@ -33,17 +30,14 @@ public class Repo extends BaseModule { | ||||
|         try { | ||||
|             parseProps(props); | ||||
|         } catch (NumberFormatException e) { | ||||
|             throw new IllegalRepoException("Repo [" + repoName + "] parse error: " + e.getMessage()); | ||||
|             throw new IllegalRepoException("Repo [" + getId() + "] parse error: " + e.getMessage()); | ||||
|         } | ||||
|  | ||||
|         if (TextUtils.isEmpty(getId())) { | ||||
|             throw new IllegalRepoException("Repo [" + repoName + "] does not contain id"); | ||||
|         } | ||||
|         if (getVersionCode() < 0) { | ||||
|             throw new IllegalRepoException("Repo [" + repoName + "] does not contain versionCode"); | ||||
|             throw new IllegalRepoException("Repo [" + getId() + "] does not contain versionCode"); | ||||
|         } | ||||
|         if (getMinMagiskVersion() < Const.MIN_MODULE_VER()) { | ||||
|             Logger.debug("Repo [" + repoName + "] is outdated"); | ||||
|             Logger.debug("Repo [" + getId() + "] is outdated"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -55,25 +49,20 @@ public class Repo extends BaseModule { | ||||
|     @Override | ||||
|     public ContentValues getContentValues() { | ||||
|         ContentValues values = super.getContentValues(); | ||||
|         values.put("repo_name", repoName); | ||||
|         values.put("last_update", mLastUpdate.getTime()); | ||||
|         return values; | ||||
|     } | ||||
|  | ||||
|     public String getRepoName() { | ||||
|         return repoName; | ||||
|     } | ||||
|  | ||||
|     public String getZipUrl() { | ||||
|         return String.format(Const.Url.ZIP_URL, repoName); | ||||
|         return String.format(Const.Url.ZIP_URL, getId()); | ||||
|     } | ||||
|  | ||||
|     public String getManifestUrl() { | ||||
|         return String.format(Const.Url.FILE_URL, repoName, "module.prop"); | ||||
|         return String.format(Const.Url.FILE_URL, getId(), "module.prop"); | ||||
|     } | ||||
|  | ||||
|     public String getDetailUrl() { | ||||
|         return String.format(Const.Url.FILE_URL, repoName, "README.md"); | ||||
|         return String.format(Const.Url.FILE_URL, getId(), "README.md"); | ||||
|     } | ||||
|  | ||||
|     public String getLastUpdateString() { | ||||
|   | ||||
| @@ -38,26 +38,30 @@ public class MagiskDatabaseHelper { | ||||
|     private static final String LOG_TABLE = "logs"; | ||||
|     private static final String SETTINGS_TABLE = "settings"; | ||||
|     private static final String STRINGS_TABLE = "strings"; | ||||
|     private static final File MANAGER_DB = | ||||
|             new File(Utils.fmt("/sbin/.core/db-%d/magisk.db", Const.USER_ID)); | ||||
|  | ||||
|     private PackageManager pm; | ||||
|     private SQLiteDatabase db; | ||||
|     private MagiskManager mm; | ||||
|  | ||||
|     @NonNull | ||||
|     public static MagiskDatabaseHelper getInstance(MagiskManager mm) { | ||||
|     public static MagiskDatabaseHelper getInstance() { | ||||
|         try { | ||||
|             return new MagiskDatabaseHelper(mm); | ||||
|             return new MagiskDatabaseHelper(); | ||||
|         } catch (Exception e) { | ||||
|             // Let's cleanup everything and try again | ||||
|             Shell.su("db_clean '*'").exec(); | ||||
|             return new MagiskDatabaseHelper(mm); | ||||
|             return new MagiskDatabaseHelper(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private MagiskDatabaseHelper(MagiskManager context) { | ||||
|         mm = context; | ||||
|         pm = mm.getPackageManager(); | ||||
|         db = openDatabase(mm); | ||||
|     private MagiskDatabaseHelper() { | ||||
|         pm = Data.MM().getPackageManager(); | ||||
|         init(); | ||||
|     } | ||||
|  | ||||
|     private void init() { | ||||
|         db = openDatabase(); | ||||
|         db.disableWriteAheadLogging(); | ||||
|         int version = Data.magiskVersionCode >= Const.MAGISK_VER.DBVER_SIX ? DATABASE_VER : OLD_DATABASE_VER; | ||||
|         int curVersion = db.getVersion(); | ||||
| @@ -71,48 +75,37 @@ public class MagiskDatabaseHelper { | ||||
|         clearOutdated(); | ||||
|     } | ||||
|  | ||||
|     private SQLiteDatabase openDatabase(MagiskManager mm) { | ||||
|         final File DB_FILE = new File(Utils.fmt("/sbin/.core/db-%d/magisk.db", Const.USER_ID)); | ||||
|     private SQLiteDatabase openDatabase() { | ||||
|         MagiskManager mm = Data.MM(); | ||||
|         Context de = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N | ||||
|                 ? mm.createDeviceProtectedStorageContext() : mm; | ||||
|         if (!DB_FILE.canWrite()) { | ||||
|         if (!MANAGER_DB.canWrite()) { | ||||
|             if (!Shell.rootAccess()) { | ||||
|                 // We don't want the app to crash, create a db and return | ||||
|                 return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null); | ||||
|             } | ||||
|             // Cleanup | ||||
|             Shell.su("db_clean " + Const.USER_ID).exec(); | ||||
|             if (Data.magiskVersionCode < Const.MAGISK_VER.FBE_AWARE) { | ||||
|                 // Super old legacy mode | ||||
|                 return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null); | ||||
|             } else if (Data.magiskVersionCode < Const.MAGISK_VER.HIDDEN_PATH) { | ||||
|                 // Legacy mode with FBE aware | ||||
|                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||
|                     de.moveDatabaseFrom(mm, "su.db"); | ||||
|                 } | ||||
|                 return de.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null); | ||||
|             } else { | ||||
|                 // Global database | ||||
|                 final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db"); | ||||
|                 mm.deleteDatabase("su.db"); | ||||
|                 de.deleteDatabase("su.db"); | ||||
|                 if (Data.magiskVersionCode < Const.MAGISK_VER.SEPOL_REFACTOR) { | ||||
|                     // We need some additional policies on old versions | ||||
|                     Shell.su("db_sepatch").exec(); | ||||
|                 } | ||||
|                 if (!GLOBAL_DB.exists()) { | ||||
|                     Shell.su("db_init").exec(); | ||||
|                     SQLiteDatabase.openOrCreateDatabase(GLOBAL_DB, null).close(); | ||||
|                     Shell.su("db_restore").exec(); | ||||
|                 } | ||||
|             // Global database | ||||
|             final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db"); | ||||
|             mm.deleteDatabase("su.db"); | ||||
|             de.deleteDatabase("su.db"); | ||||
|             if (Data.magiskVersionCode < Const.MAGISK_VER.SEPOL_REFACTOR) { | ||||
|                 // We need some additional policies on old versions | ||||
|                 Shell.su("db_sepatch").exec(); | ||||
|             } | ||||
|             if (!GLOBAL_DB.exists()) { | ||||
|                 Shell.su("db_init").exec(); | ||||
|                 SQLiteDatabase.openOrCreateDatabase(GLOBAL_DB, null).close(); | ||||
|                 Shell.su("db_restore").exec(); | ||||
|             } | ||||
|             Shell.su("db_setup " + Process.myUid()).exec(); | ||||
|         } | ||||
|         // Not using legacy mode, open the mounted global DB | ||||
|         return SQLiteDatabase.openOrCreateDatabase(DB_FILE, null); | ||||
|         return SQLiteDatabase.openOrCreateDatabase(MANAGER_DB, null); | ||||
|     } | ||||
|  | ||||
|     public void onUpgrade(SQLiteDatabase db, int oldVersion) { | ||||
|     private void onUpgrade(SQLiteDatabase db, int oldVersion) { | ||||
|         if (oldVersion == 0) { | ||||
|             createTables(db); | ||||
|             oldVersion = 3; | ||||
| @@ -147,13 +140,13 @@ public class MagiskDatabaseHelper { | ||||
|         } | ||||
|         if (oldVersion == 5) { | ||||
|             setSettings(Const.Key.SU_FINGERPRINT, | ||||
|                     mm.prefs.getBoolean(Const.Key.SU_FINGERPRINT, false) ? 1 : 0); | ||||
|                     Data.MM().prefs.getBoolean(Const.Key.SU_FINGERPRINT, false) ? 1 : 0); | ||||
|             ++oldVersion; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Remove everything, we do not support downgrade | ||||
|     public void onDowngrade(SQLiteDatabase db) { | ||||
|     private void onDowngrade(SQLiteDatabase db) { | ||||
|         Utils.toast(R.string.su_db_corrupt, Toast.LENGTH_LONG); | ||||
|         db.execSQL("DROP TABLE IF EXISTS " + POLICY_TABLE); | ||||
|         db.execSQL("DROP TABLE IF EXISTS " + LOG_TABLE); | ||||
| @@ -182,6 +175,11 @@ public class MagiskDatabaseHelper { | ||||
|                 "(key TEXT, value INT, PRIMARY KEY(key))"); | ||||
|     } | ||||
|  | ||||
|     public void flush() { | ||||
|         db.close(); | ||||
|         init(); | ||||
|     } | ||||
|  | ||||
|     public void clearOutdated() { | ||||
|         // Clear outdated policies | ||||
|         db.delete(POLICY_TABLE, Utils.fmt("until > 0 AND until < %d", System.currentTimeMillis() / 1000), null); | ||||
|   | ||||
| @@ -16,7 +16,7 @@ import java.util.Set; | ||||
|  | ||||
| public class RepoDatabaseHelper extends SQLiteOpenHelper { | ||||
|  | ||||
|     private static final int DATABASE_VER = 3; | ||||
|     private static final int DATABASE_VER = 4; | ||||
|     private static final String TABLE_NAME = "repos"; | ||||
|  | ||||
|     private SQLiteDatabase mDb; | ||||
| @@ -40,21 +40,14 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper { | ||||
|  | ||||
|     @Override | ||||
|     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { | ||||
|         try { | ||||
|             if (oldVersion < 3) { | ||||
|                 db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); | ||||
|                 db.execSQL( | ||||
|                         "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " + | ||||
|                                 "(id TEXT, name TEXT, version TEXT, versionCode INT, minMagisk INT, " + | ||||
|                                 "author TEXT, description TEXT, repo_name TEXT, last_update INT, " + | ||||
|                                 "PRIMARY KEY(id))"); | ||||
|                 mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply(); | ||||
|                 oldVersion = 3; | ||||
|             } | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|             // Reset database | ||||
|             onDowngrade(db, DATABASE_VER, 0); | ||||
|         if (oldVersion != newVersion) { | ||||
|             // Nuke old DB and create new table | ||||
|             db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); | ||||
|             db.execSQL( | ||||
|                     "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(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -75,8 +68,7 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper { | ||||
|     } | ||||
|  | ||||
|     public void removeRepo(Repo repo) { | ||||
|         mDb.delete(TABLE_NAME, "repo_name=?", new String[] { repo.getRepoName() }); | ||||
|         notifyAdapter(); | ||||
|         removeRepo(repo.getId()); | ||||
|     } | ||||
|  | ||||
|     public void removeRepo(Iterable<String> list) { | ||||
|   | ||||
| @@ -11,23 +11,23 @@ import com.topjohnwu.magisk.Const; | ||||
| import com.topjohnwu.magisk.Data; | ||||
| import com.topjohnwu.magisk.MainActivity; | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.adapters.TabFragmentAdapter; | ||||
| import com.topjohnwu.magisk.components.BaseFragment; | ||||
|  | ||||
| import androidx.viewpager.widget.ViewPager; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class LogFragment extends BaseFragment { | ||||
|  | ||||
|     public ViewPager viewPager; | ||||
|     public TabLayout tab; | ||||
|     @BindView(R.id.container) ViewPager viewPager; | ||||
|     @BindView(R.id.tab) TabLayout tab; | ||||
|  | ||||
|     @Override | ||||
|     public View onCreateView(LayoutInflater inflater, ViewGroup container, | ||||
|                              Bundle savedInstanceState) { | ||||
|         // Inflate the layout for this fragment | ||||
|         View v = inflater.inflate(R.layout.fragment_log, container, false); | ||||
|         ViewBinder.bind(this, v); | ||||
|         unbinder = new LogFragment_ViewBinding(this, v); | ||||
|  | ||||
|         ((MainActivity) requireActivity()).toolbar.setElevation(0); | ||||
|  | ||||
| @@ -44,10 +44,4 @@ public class LogFragment extends BaseFragment { | ||||
|  | ||||
|         return v; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroyView() { | ||||
|         super.onDestroyView(); | ||||
|         ViewBinder.unbind(this); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -20,7 +20,6 @@ import com.topjohnwu.magisk.Const; | ||||
| import com.topjohnwu.magisk.Data; | ||||
| import com.topjohnwu.magisk.MainActivity; | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.asyncs.CheckSafetyNet; | ||||
| import com.topjohnwu.magisk.asyncs.CheckUpdates; | ||||
| import com.topjohnwu.magisk.components.BaseActivity; | ||||
| @@ -42,6 +41,9 @@ import androidx.annotation.Nullable; | ||||
| import androidx.annotation.StringRes; | ||||
| import androidx.cardview.widget.CardView; | ||||
| import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | ||||
| import butterknife.BindColor; | ||||
| import butterknife.BindView; | ||||
| import butterknife.OnClick; | ||||
|  | ||||
| public class MagiskFragment extends BaseFragment | ||||
|         implements SwipeRefreshLayout.OnRefreshListener, ExpandableView, Topic.Subscriber { | ||||
| @@ -49,41 +51,42 @@ public class MagiskFragment extends BaseFragment | ||||
|     private Container expandableContainer = new Container(); | ||||
|     private static boolean shownDialog = false; | ||||
|  | ||||
|     public SwipeRefreshLayout mSwipeRefreshLayout; | ||||
|     @BindView(R.id.swipeRefreshLayout) public SwipeRefreshLayout mSwipeRefreshLayout; | ||||
|  | ||||
|     public CardView coreOnlyNotice; | ||||
|     @BindView(R.id.core_only_notice) CardView coreOnlyNotice; | ||||
|  | ||||
|     public RelativeLayout magiskUpdate; | ||||
|     public ImageView magiskUpdateIcon; | ||||
|     public TextView magiskUpdateText; | ||||
|     public ProgressBar magiskUpdateProgress; | ||||
|     public ImageView magiskStatusIcon; | ||||
|     public TextView magiskVersionText; | ||||
|     @BindView(R.id.magisk_update) RelativeLayout magiskUpdate; | ||||
|     @BindView(R.id.magisk_update_icon) ImageView magiskUpdateIcon; | ||||
|     @BindView(R.id.magisk_update_status) TextView magiskUpdateText; | ||||
|     @BindView(R.id.magisk_update_progress) ProgressBar magiskUpdateProgress; | ||||
|     @BindView(R.id.magisk_status_icon) ImageView magiskStatusIcon; | ||||
|     @BindView(R.id.magisk_version) TextView magiskVersionText; | ||||
|  | ||||
|     public CardView safetyNetCard; | ||||
|     public ImageView safetyNetRefreshIcon; | ||||
|     public TextView safetyNetStatusText; | ||||
|     public ProgressBar safetyNetProgress; | ||||
|     public LinearLayout expandLayout; | ||||
|     public ImageView ctsStatusIcon; | ||||
|     public TextView ctsStatusText; | ||||
|     public ImageView basicStatusIcon; | ||||
|     public TextView basicStatusText; | ||||
|     @BindView(R.id.safetyNet_card) CardView safetyNetCard; | ||||
|     @BindView(R.id.safetyNet_refresh) ImageView safetyNetRefreshIcon; | ||||
|     @BindView(R.id.safetyNet_status) TextView safetyNetStatusText; | ||||
|     @BindView(R.id.safetyNet_check_progress) ProgressBar safetyNetProgress; | ||||
|     @BindView(R.id.expand_layout) LinearLayout expandLayout; | ||||
|     @BindView(R.id.cts_status_icon) ImageView ctsStatusIcon; | ||||
|     @BindView(R.id.cts_status) TextView ctsStatusText; | ||||
|     @BindView(R.id.basic_status_icon) ImageView basicStatusIcon; | ||||
|     @BindView(R.id.basic_status) TextView basicStatusText; | ||||
|  | ||||
|     public CardView installOptionCard; | ||||
|     public CheckBox keepEncChkbox; | ||||
|     public CheckBox keepVerityChkbox; | ||||
|     public CardView installButton; | ||||
|     public TextView installText; | ||||
|     public CardView uninstallButton; | ||||
|     @BindView(R.id.install_option_card) CardView installOptionCard; | ||||
|     @BindView(R.id.keep_force_enc) CheckBox keepEncChkbox; | ||||
|     @BindView(R.id.keep_verity) CheckBox keepVerityChkbox; | ||||
|     @BindView(R.id.install_button) CardView installButton; | ||||
|     @BindView(R.id.install_text) TextView installText; | ||||
|     @BindView(R.id.uninstall_button) CardView uninstallButton; | ||||
|  | ||||
|     public int colorBad; | ||||
|     public int colorOK; | ||||
|     public int colorWarn; | ||||
|     public int colorNeutral; | ||||
|     public int colorInfo; | ||||
|     @BindColor(R.color.red500) int colorBad; | ||||
|     @BindColor(R.color.green500) int colorOK; | ||||
|     @BindColor(R.color.yellow500) int colorWarn; | ||||
|     @BindColor(R.color.green500) int colorNeutral; | ||||
|     @BindColor(R.color.blue500) int colorInfo; | ||||
|  | ||||
|     public void safetyNet() { | ||||
|     @OnClick(R.id.safetyNet_title) | ||||
|     void safetyNet() { | ||||
|         Runnable task = () -> { | ||||
|             safetyNetProgress.setVisibility(View.VISIBLE); | ||||
|             safetyNetRefreshIcon.setVisibility(View.GONE); | ||||
| @@ -106,7 +109,8 @@ public class MagiskFragment extends BaseFragment | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public void install() { | ||||
|     @OnClick(R.id.install_button) | ||||
|     void install() { | ||||
|         shownDialog = true; | ||||
|  | ||||
|         // Show Manager update first | ||||
| @@ -119,7 +123,8 @@ public class MagiskFragment extends BaseFragment | ||||
|         new MagiskInstallDialog((BaseActivity) getActivity()).show(); | ||||
|     } | ||||
|  | ||||
|     public void uninstall() { | ||||
|     @OnClick(R.id.uninstall_button) | ||||
|     void uninstall() { | ||||
|         new UninstallDialog(requireActivity()).show(); | ||||
|     } | ||||
|  | ||||
| @@ -128,7 +133,7 @@ public class MagiskFragment extends BaseFragment | ||||
|     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, | ||||
|                              @Nullable Bundle savedInstanceState) { | ||||
|         View v = inflater.inflate(R.layout.fragment_magisk, container, false); | ||||
|         ViewBinder.bind(this, v); | ||||
|         unbinder = new MagiskFragment_ViewBinding(this, v); | ||||
|         requireActivity().setTitle(R.string.magisk); | ||||
|  | ||||
|         expandableContainer.expandLayout = expandLayout; | ||||
| @@ -145,12 +150,6 @@ public class MagiskFragment extends BaseFragment | ||||
|         return v; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroyView() { | ||||
|         super.onDestroyView(); | ||||
|         ViewBinder.unbind(this); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onRefresh() { | ||||
|         Data.loadMagiskInfo(); | ||||
| @@ -215,11 +214,10 @@ public class MagiskFragment extends BaseFragment | ||||
|  | ||||
|         boolean hasNetwork = Download.checkNetworkStatus(mm); | ||||
|         boolean hasRoot = Shell.rootAccess(); | ||||
|         boolean isUpToDate = Data.magiskVersionCode > Const.MAGISK_VER.UNIFIED; | ||||
|  | ||||
|         magiskUpdate.setVisibility(hasNetwork ? View.VISIBLE : View.GONE); | ||||
|         installOptionCard.setVisibility(hasNetwork ? View.VISIBLE : View.GONE); | ||||
|         uninstallButton.setVisibility(isUpToDate && hasRoot ? View.VISIBLE : View.GONE); | ||||
|         uninstallButton.setVisibility(hasRoot ? View.VISIBLE : View.GONE); | ||||
|         coreOnlyNotice.setVisibility(mm.prefs.getBoolean(Const.Key.COREONLY, false) ? View.VISIBLE : View.GONE); | ||||
|  | ||||
|         int image, color; | ||||
|   | ||||
| @@ -9,7 +9,6 @@ import android.view.ViewGroup; | ||||
| import android.widget.SearchView; | ||||
|  | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.adapters.ApplicationAdapter; | ||||
| import com.topjohnwu.magisk.components.BaseFragment; | ||||
| import com.topjohnwu.magisk.utils.Topic; | ||||
| @@ -18,11 +17,12 @@ import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber { | ||||
|  | ||||
|     public SwipeRefreshLayout mSwipeRefreshLayout; | ||||
|     public RecyclerView recyclerView; | ||||
|     @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; | ||||
|     @BindView(R.id.recyclerView) RecyclerView recyclerView; | ||||
|     SearchView search; | ||||
|  | ||||
|     private ApplicationAdapter appAdapter; | ||||
| @@ -39,7 +39,7 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber | ||||
|     @Override | ||||
|     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||||
|         View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false); | ||||
|         ViewBinder.bind(this, view); | ||||
|         unbinder = new MagiskHideFragment_ViewBinding(this, view); | ||||
|  | ||||
|         appAdapter = new ApplicationAdapter(requireActivity()); | ||||
|         recyclerView.setAdapter(appAdapter); | ||||
| @@ -73,12 +73,6 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber | ||||
|         search.setOnQueryTextListener(searchListener); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroyView() { | ||||
|         super.onDestroyView(); | ||||
|         ViewBinder.unbind(this); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int[] getSubscribedTopics() { | ||||
|         return new int[] {Topic.MAGISK_HIDE_DONE}; | ||||
|   | ||||
| @@ -17,7 +17,6 @@ import android.widget.TextView; | ||||
| import com.google.android.material.snackbar.Snackbar; | ||||
| import com.topjohnwu.magisk.Const; | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.components.BaseFragment; | ||||
| import com.topjohnwu.magisk.components.SnackbarMaker; | ||||
| import com.topjohnwu.magisk.utils.Download; | ||||
| @@ -29,19 +28,20 @@ import java.io.IOException; | ||||
| import java.util.Calendar; | ||||
|  | ||||
| import androidx.annotation.Nullable; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class MagiskLogFragment extends BaseFragment { | ||||
|  | ||||
|     public TextView txtLog; | ||||
|     public ScrollView svLog; | ||||
|     public HorizontalScrollView hsvLog; | ||||
|     public ProgressBar progressBar; | ||||
|     @BindView(R.id.txtLog) TextView txtLog; | ||||
|     @BindView(R.id.svLog) ScrollView svLog; | ||||
|     @BindView(R.id.hsvLog) HorizontalScrollView hsvLog; | ||||
|     @BindView(R.id.progressBar) ProgressBar progressBar; | ||||
|  | ||||
|     @Nullable | ||||
|     @Override | ||||
|     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { | ||||
|         View view = inflater.inflate(R.layout.fragment_magisk_log, container, false); | ||||
|         ViewBinder.bind(this, view); | ||||
|         unbinder = new MagiskLogFragment_ViewBinding(this, view); | ||||
|         setHasOptionsMenu(true); | ||||
|         txtLog.setTextIsSelectable(true); | ||||
|         return view; | ||||
| @@ -59,12 +59,6 @@ public class MagiskLogFragment extends BaseFragment { | ||||
|         readLogs(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroyView() { | ||||
|         super.onDestroyView(); | ||||
|         ViewBinder.unbind(this); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { | ||||
|         inflater.inflate(R.menu.menu_log, menu); | ||||
| @@ -87,7 +81,7 @@ public class MagiskLogFragment extends BaseFragment { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void readLogs() { | ||||
|     private void readLogs() { | ||||
|         Shell.su("cat " + Const.MAGISK_LOG + " | tail -n 5000").submit(result -> { | ||||
|             progressBar.setVisibility(View.GONE); | ||||
|             if (result.getOut().isEmpty()) | ||||
| @@ -99,7 +93,7 @@ public class MagiskLogFragment extends BaseFragment { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public void saveLogs() { | ||||
|     private void saveLogs() { | ||||
|         Calendar now = Calendar.getInstance(); | ||||
|         String filename = Utils.fmt("magisk_log_%04d%02d%02d_%02d%02d%02d.log", | ||||
|                 now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1, | ||||
| @@ -117,7 +111,7 @@ public class MagiskLogFragment extends BaseFragment { | ||||
|                         SnackbarMaker.make(txtLog, logFile.getPath(), Snackbar.LENGTH_SHORT).show()); | ||||
|     } | ||||
|  | ||||
|     public void clearLogs() { | ||||
|     private void clearLogs() { | ||||
|         Shell.su("echo -n > " + Const.MAGISK_LOG).submit(); | ||||
|         txtLog.setText(R.string.log_is_empty); | ||||
|         SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show(); | ||||
|   | ||||
| @@ -16,7 +16,6 @@ import com.topjohnwu.magisk.Const; | ||||
| import com.topjohnwu.magisk.Data; | ||||
| import com.topjohnwu.magisk.FlashActivity; | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.adapters.ModulesAdapter; | ||||
| import com.topjohnwu.magisk.components.BaseFragment; | ||||
| import com.topjohnwu.magisk.container.Module; | ||||
| @@ -32,14 +31,17 @@ import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | ||||
| import butterknife.BindView; | ||||
| import butterknife.OnClick; | ||||
|  | ||||
| public class ModulesFragment extends BaseFragment implements Topic.Subscriber { | ||||
|  | ||||
|     public SwipeRefreshLayout mSwipeRefreshLayout; | ||||
|     public RecyclerView recyclerView; | ||||
|     public TextView emptyRv; | ||||
|     @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; | ||||
|     @BindView(R.id.recyclerView) RecyclerView recyclerView; | ||||
|     @BindView(R.id.empty_rv) TextView emptyRv; | ||||
|  | ||||
|     public void selectFile() { | ||||
|     @OnClick(R.id.fab) | ||||
|     void selectFile() { | ||||
|         runWithPermission(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> { | ||||
|             Intent intent = new Intent(Intent.ACTION_GET_CONTENT); | ||||
|             intent.setType("application/zip"); | ||||
| @@ -53,7 +55,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber { | ||||
|     @Override | ||||
|     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||||
|         View view = inflater.inflate(R.layout.fragment_modules, container, false); | ||||
|         ViewBinder.bind(this, view); | ||||
|         unbinder = new ModulesFragment_ViewBinding(this, view); | ||||
|         setHasOptionsMenu(true); | ||||
|  | ||||
|         mSwipeRefreshLayout.setOnRefreshListener(() -> { | ||||
| @@ -98,12 +100,6 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroyView() { | ||||
|         super.onDestroyView(); | ||||
|         ViewBinder.unbind(this); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { | ||||
|         inflater.inflate(R.menu.menu_reboot, menu); | ||||
|   | ||||
| @@ -14,7 +14,6 @@ import android.widget.TextView; | ||||
| import com.topjohnwu.magisk.Const; | ||||
| import com.topjohnwu.magisk.Data; | ||||
| import com.topjohnwu.magisk.R; | ||||
| import com.topjohnwu.magisk.ViewBinder; | ||||
| import com.topjohnwu.magisk.adapters.ReposAdapter; | ||||
| import com.topjohnwu.magisk.asyncs.UpdateRepos; | ||||
| import com.topjohnwu.magisk.components.BaseFragment; | ||||
| @@ -27,12 +26,13 @@ import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | ||||
| import butterknife.BindView; | ||||
|  | ||||
| public class ReposFragment extends BaseFragment implements Topic.Subscriber { | ||||
|  | ||||
|     public RecyclerView recyclerView; | ||||
|     public TextView emptyRv; | ||||
|     public SwipeRefreshLayout mSwipeRefreshLayout; | ||||
|     @BindView(R.id.recyclerView) RecyclerView recyclerView; | ||||
|     @BindView(R.id.empty_rv) TextView emptyRv; | ||||
|     @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; | ||||
|  | ||||
|     private ReposAdapter adapter; | ||||
|  | ||||
| @@ -46,7 +46,7 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber { | ||||
|     @Override | ||||
|     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||||
|         View view = inflater.inflate(R.layout.fragment_repos, container, false); | ||||
|         ViewBinder.bind(this, view); | ||||
|         unbinder = new ReposFragment_ViewBinding(this, view); | ||||
|  | ||||
|         mSwipeRefreshLayout.setRefreshing(true); | ||||
|         recyclerView.setVisibility(View.GONE); | ||||
| @@ -120,6 +120,5 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber { | ||||
|     public void onDestroyView() { | ||||
|         super.onDestroyView(); | ||||
|         mm.repoDB.unregisterAdapter(); | ||||
|         ViewBinder.unbind(this); | ||||
|     } | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user