diff --git a/app-core/src/main/java/com/topjohnwu/magisk/tasks/SafetyNet.java b/app-core/src/main/java/com/topjohnwu/magisk/tasks/SafetyNet.java deleted file mode 100644 index be56faeab..000000000 --- a/app-core/src/main/java/com/topjohnwu/magisk/tasks/SafetyNet.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.topjohnwu.magisk.tasks; - -import android.app.Activity; - -import com.topjohnwu.magisk.App; -import com.topjohnwu.magisk.Const; -import com.topjohnwu.magisk.utils.ISafetyNetHelper; -import com.topjohnwu.magisk.utils.Topic; -import com.topjohnwu.net.Networking; -import com.topjohnwu.superuser.Shell; - -import java.io.File; - -import dalvik.system.DexClassLoader; - -public class SafetyNet { - - public static final File EXT_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(), - null, ISafetyNetHelper.class.getClassLoader()); - Class clazz = loader.loadClass("com.topjohnwu.snet.Snet"); - ISafetyNetHelper helper = (ISafetyNetHelper) clazz.getMethod("newHelper", - Class.class, String.class, Activity.class, Object.class) - .invoke(null, ISafetyNetHelper.class, EXT_APK.getPath(), activity, - (ISafetyNetHelper.Callback) code -> - Topic.publish(false, Topic.SNET_CHECK_DONE, code)); - if (helper.getVersion() < Const.SNET_EXT_VER) - throw new Exception(); - helper.attest(); - } - - public static void check(Activity activity) { - try { - dyRun(activity); - } catch (Exception ignored) { - Shell.sh("rm -rf " + EXT_APK.getParent()).exec(); - EXT_APK.getParentFile().mkdir(); - Networking.get(Const.Url.SNET_URL).getAsFile(EXT_APK, f -> { - try { - dyRun(activity); - } catch (Exception e) { - e.printStackTrace(); - Topic.publish(false, Topic.SNET_CHECK_DONE, -1); - } - }); - } - } -} diff --git a/app/src/full/java/com/topjohnwu/magisk/components/SafetyNet.java b/app/src/full/java/com/topjohnwu/magisk/components/SafetyNet.java new file mode 100644 index 000000000..bff0dbaee --- /dev/null +++ b/app/src/full/java/com/topjohnwu/magisk/components/SafetyNet.java @@ -0,0 +1,158 @@ +package com.topjohnwu.magisk.components; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.topjohnwu.magisk.App; +import com.topjohnwu.magisk.Const; +import com.topjohnwu.magisk.R; +import com.topjohnwu.magisk.utils.ISafetyNetHelper; +import com.topjohnwu.net.Networking; +import com.topjohnwu.superuser.Shell; + +import java.io.File; + +import androidx.annotation.StringRes; +import androidx.cardview.widget.CardView; +import butterknife.BindColor; +import butterknife.BindView; +import butterknife.OnClick; +import dalvik.system.DexClassLoader; + +public class SafetyNet implements ISafetyNetHelper.Callback { + + private static final File EXT_APK = + new File(App.self.getFilesDir().getParent() + "/snet", "snet.apk"); + + @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.safetyNet_expand) ViewGroup 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; + + @BindColor(R.color.red500) int colorBad; + @BindColor(R.color.green500) int colorOK; + + private ExpandableViewHolder expandable; + + public SafetyNet(View v) { + new SafetyNet_ViewBinding(this, v); + expandable = new ExpandableViewHolder(expandLayout); + Context context = v.getContext(); + safetyNetCard.setVisibility(hasGms(context) && Networking.checkNetworkStatus(context) ? + View.VISIBLE : View.GONE); + } + + @OnClick(R.id.safetyNet_refresh) + void safetyNet(View v) { + Runnable task = () -> { + safetyNetProgress.setVisibility(View.VISIBLE); + safetyNetRefreshIcon.setVisibility(View.INVISIBLE); + safetyNetStatusText.setText(R.string.checking_safetyNet_status); + check((Activity) v.getContext()); + expandable.collapse(); + }; + if (!SafetyNet.EXT_APK.exists()) { + // Show dialog + new CustomAlertDialog((Activity) v.getContext()) + .setTitle(R.string.proprietary_title) + .setMessage(R.string.proprietary_notice) + .setCancelable(true) + .setPositiveButton(R.string.yes, (d, i) -> task.run()) + .setNegativeButton(R.string.no_thanks, null) + .show(); + } else { + task.run(); + } + } + + public void reset() { + safetyNetStatusText.setText(R.string.safetyNet_check_text); + expandable.setExpanded(false); + } + + @Override + public void onResponse(int response) { + safetyNetProgress.setVisibility(View.GONE); + safetyNetRefreshIcon.setVisibility(View.VISIBLE); + if ((response & 0x0F) == 0) { + safetyNetStatusText.setText(R.string.safetyNet_check_success); + + boolean b; + b = (response & ISafetyNetHelper.CTS_PASS) != 0; + ctsStatusText.setText("ctsProfile: " + b); + ctsStatusIcon.setImageResource(b ? R.drawable.ic_check_circle : R.drawable.ic_cancel); + ctsStatusIcon.setColorFilter(b ? colorOK : colorBad); + + b = (response & ISafetyNetHelper.BASIC_PASS) != 0; + basicStatusText.setText("basicIntegrity: " + b); + basicStatusIcon.setImageResource(b ? R.drawable.ic_check_circle : R.drawable.ic_cancel); + basicStatusIcon.setColorFilter(b ? colorOK : colorBad); + + expandable.expand(); + } else { + @StringRes int resid; + switch (response) { + case ISafetyNetHelper.RESPONSE_ERR: + resid = R.string.safetyNet_res_invalid; + break; + case ISafetyNetHelper.CONNECTION_FAIL: + default: + resid = R.string.safetyNet_api_error; + break; + } + safetyNetStatusText.setText(resid); + } + } + + private void dyRun(Activity activity) throws Exception { + DexClassLoader loader = new DexClassLoader(EXT_APK.getPath(), EXT_APK.getParent(), + null, ISafetyNetHelper.class.getClassLoader()); + Class clazz = loader.loadClass("com.topjohnwu.snet.Snet"); + ISafetyNetHelper helper = (ISafetyNetHelper) clazz.getMethod("newHelper", + Class.class, String.class, Activity.class, Object.class) + .invoke(null, ISafetyNetHelper.class, EXT_APK.getPath(), activity, this); + if (helper.getVersion() < Const.SNET_EXT_VER) + throw new Exception(); + helper.attest(); + } + + private void check(Activity activity) { + try { + dyRun(activity); + } catch (Exception ignored) { + Shell.sh("rm -rf " + EXT_APK.getParent()).exec(); + EXT_APK.getParentFile().mkdir(); + Networking.get(Const.Url.SNET_URL).getAsFile(EXT_APK, f -> { + try { + dyRun(activity); + } catch (Exception e) { + e.printStackTrace(); + onResponse(-1); + } + }); + } + } + + private boolean hasGms(Context context) { + PackageManager pm = context.getPackageManager(); + PackageInfo info; + try { + info = pm.getPackageInfo("com.google.android.gms", 0); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + return info.applicationInfo.enabled; + } +} 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 79878ecee..f71d0dafd 100644 --- a/app/src/full/java/com/topjohnwu/magisk/fragments/MagiskFragment.java +++ b/app/src/full/java/com/topjohnwu/magisk/fragments/MagiskFragment.java @@ -7,10 +7,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; -import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; import com.topjohnwu.magisk.BuildConfig; import com.topjohnwu.magisk.Config; @@ -18,16 +15,13 @@ import com.topjohnwu.magisk.MainActivity; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.components.BaseActivity; import com.topjohnwu.magisk.components.BaseFragment; -import com.topjohnwu.magisk.components.CustomAlertDialog; import com.topjohnwu.magisk.components.EnvFixDialog; -import com.topjohnwu.magisk.components.ExpandableViewHolder; import com.topjohnwu.magisk.components.MagiskInstallDialog; import com.topjohnwu.magisk.components.ManagerInstallDialog; +import com.topjohnwu.magisk.components.SafetyNet; import com.topjohnwu.magisk.components.UninstallDialog; import com.topjohnwu.magisk.components.UpdateCardHolder; import com.topjohnwu.magisk.tasks.CheckUpdates; -import com.topjohnwu.magisk.tasks.SafetyNet; -import com.topjohnwu.magisk.utils.ISafetyNetHelper; import com.topjohnwu.magisk.utils.Topic; import com.topjohnwu.net.Networking; import com.topjohnwu.superuser.Shell; @@ -37,7 +31,6 @@ import java.util.Locale; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.StringRes; import androidx.cardview.widget.CardView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.transition.ChangeBounds; @@ -57,16 +50,6 @@ public class MagiskFragment extends BaseFragment @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; @BindView(R.id.linearLayout) LinearLayout root; - @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; - @BindView(R.id.install_option_card) CardView installOptionCard; @BindView(R.id.keep_force_enc) CheckBox keepEncChkbox; @BindView(R.id.keep_verity) CheckBox keepVerityChkbox; @@ -80,32 +63,9 @@ public class MagiskFragment extends BaseFragment private UpdateCardHolder magisk; private UpdateCardHolder manager; - private ExpandableViewHolder snExpandableHolder; + private SafetyNet safetyNet; private Transition transition; - @OnClick(R.id.safetyNet_title) - void safetyNet() { - Runnable task = () -> { - safetyNetProgress.setVisibility(View.VISIBLE); - safetyNetRefreshIcon.setVisibility(View.GONE); - safetyNetStatusText.setText(R.string.checking_safetyNet_status); - SafetyNet.check(requireActivity()); - snExpandableHolder.collapse(); - }; - if (!SafetyNet.EXT_APK.exists()) { - // Show dialog - new CustomAlertDialog(requireActivity()) - .setTitle(R.string.proprietary_title) - .setMessage(R.string.proprietary_notice) - .setCancelable(true) - .setPositiveButton(R.string.yes, (d, i) -> task.run()) - .setNegativeButton(R.string.no_thanks, null) - .show(); - } else { - task.run(); - } - } - private void magiskInstall(View v) { // Show Manager update first if (Config.remoteManagerVersionCode > BuildConfig.VERSION_CODE) { @@ -132,8 +92,7 @@ public class MagiskFragment extends BaseFragment unbinder = new MagiskFragment_ViewBinding(this, v); requireActivity().setTitle(R.string.magisk); - snExpandableHolder = new ExpandableViewHolder(expandLayout); - + safetyNet = new SafetyNet(v); magisk = new UpdateCardHolder(inflater, root); manager = new UpdateCardHolder(inflater, root); root.addView(magisk.itemView, 0); @@ -157,9 +116,6 @@ public class MagiskFragment extends BaseFragment manager.additional.setVisibility(View.VISIBLE); } - safetyNetCard.setVisibility(hasGms() && Networking.checkNetworkStatus(app) ? - View.VISIBLE : View.GONE); - transition = new TransitionSet() .setOrdering(TransitionSet.ORDERING_TOGETHER) .addTransition(new Fade(Fade.OUT)) @@ -172,11 +128,9 @@ public class MagiskFragment extends BaseFragment @Override public void onRefresh() { - safetyNetStatusText.setText(R.string.safetyNet_check_text); - snExpandableHolder.setExpanded(false); - mSwipeRefreshLayout.setRefreshing(false); TransitionManager.beginDelayedTransition(root, transition); + safetyNet.reset(); magisk.reset(); manager.reset(); @@ -197,19 +151,12 @@ public class MagiskFragment extends BaseFragment @Override public int[] getSubscribedTopics() { - return new int[] {Topic.SNET_CHECK_DONE, Topic.UPDATE_CHECK_DONE}; + return new int[] {Topic.UPDATE_CHECK_DONE}; } @Override public void onPublish(int topic, Object[] result) { - switch (topic) { - case Topic.SNET_CHECK_DONE: - updateSafetyNetUI((int) result[0]); - break; - case Topic.UPDATE_CHECK_DONE: - updateCheckUI(); - break; - } + updateCheckUI(); } private boolean hasGms() { @@ -334,38 +281,5 @@ public class MagiskFragment extends BaseFragment new EnvFixDialog(requireActivity()).show(); } } - - private void updateSafetyNetUI(int response) { - safetyNetProgress.setVisibility(View.GONE); - safetyNetRefreshIcon.setVisibility(View.VISIBLE); - if ((response & 0x0F) == 0) { - safetyNetStatusText.setText(R.string.safetyNet_check_success); - - boolean b; - b = (response & ISafetyNetHelper.CTS_PASS) != 0; - ctsStatusText.setText("ctsProfile: " + b); - ctsStatusIcon.setImageResource(b ? R.drawable.ic_check_circle : R.drawable.ic_cancel); - ctsStatusIcon.setColorFilter(b ? colorOK : colorBad); - - b = (response & ISafetyNetHelper.BASIC_PASS) != 0; - basicStatusText.setText("basicIntegrity: " + b); - basicStatusIcon.setImageResource(b ? R.drawable.ic_check_circle : R.drawable.ic_cancel); - basicStatusIcon.setColorFilter(b ? colorOK : colorBad); - - snExpandableHolder.expand(); - } else { - @StringRes int resid; - switch (response) { - case ISafetyNetHelper.RESPONSE_ERR: - resid = R.string.safetyNet_res_invalid; - break; - case ISafetyNetHelper.CONNECTION_FAIL: - default: - resid = R.string.safetyNet_api_error; - break; - } - safetyNetStatusText.setText(resid); - } - } } diff --git a/app/src/full/res/drawable/ic_safetynet.xml b/app/src/full/res/drawable/ic_safetynet.xml index a380b9bb4..f47a5deae 100644 --- a/app/src/full/res/drawable/ic_safetynet.xml +++ b/app/src/full/res/drawable/ic_safetynet.xml @@ -1,9 +1,5 @@ - - + + diff --git a/app/src/full/res/layout/fragment_magisk.xml b/app/src/full/res/layout/fragment_magisk.xml index 32a767000..e8044685c 100644 --- a/app/src/full/res/layout/fragment_magisk.xml +++ b/app/src/full/res/layout/fragment_magisk.xml @@ -36,101 +36,105 @@ android:layout_height="wrap_content" android:orientation="vertical"> - + android:layout_height="wrap_content"> - - + android:id="@+id/sn_logo" + android:layout_width="30dp" + android:layout_height="30dp" + android:layout_marginTop="12dp" + android:layout_marginEnd="24dp" + android:layout_marginBottom="12dp" + android:tint="@color/green500" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@+id/safetyNet_status" + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/ic_safetynet" /> + android:textStyle="bold" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - + - + + + + + android:paddingBottom="10dp"> - + + + android:padding="6dp" + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="@+id/basic_status" + app:layout_constraintStart_toStartOf="@+id/basic_status" + app:layout_constraintTop_toTopOf="parent" /> - + - - - - - + android:padding="6dp" + android:textStyle="bold" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/cts_status" /> - - - - - - + diff --git a/app/src/full/res/values/strings.xml b/app/src/full/res/values/strings.xml index 38b03baaa..83805b8e7 100644 --- a/app/src/full/res/values/strings.xml +++ b/app/src/full/res/values/strings.xml @@ -13,7 +13,7 @@ Checking for updates… Magisk v%1$s is available! Invalid Update Channel - Tap to start SafetyNet check. + Tap to start SafetyNet check Checking SafetyNet status… SafetyNet Check Success SafetyNet API Error