163 lines
6.0 KiB
Java
163 lines
6.0 KiB
Java
package com.topjohnwu.magisk.uicomponents;
|
|
|
|
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 androidx.annotation.StringRes;
|
|
import androidx.cardview.widget.CardView;
|
|
|
|
import com.topjohnwu.magisk.App;
|
|
import com.topjohnwu.magisk.Const;
|
|
import com.topjohnwu.magisk.R;
|
|
import com.topjohnwu.magisk.dialogs.CustomAlertDialog;
|
|
import com.topjohnwu.magisk.utils.ISafetyNetHelper;
|
|
import com.topjohnwu.net.Networking;
|
|
import com.topjohnwu.superuser.Shell;
|
|
|
|
import java.io.File;
|
|
|
|
import butterknife.BindColor;
|
|
import butterknife.BindView;
|
|
import butterknife.OnClick;
|
|
import butterknife.Unbinder;
|
|
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;
|
|
|
|
public Unbinder unbinder;
|
|
private ExpandableViewHolder expandable;
|
|
|
|
public SafetyNet(View v) {
|
|
unbinder = 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;
|
|
}
|
|
}
|