More root stuff
Because we can can can...
This commit is contained in:
parent
3fe5647a15
commit
8a8aa1337b
@ -12,12 +12,24 @@
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
|
||||
<application
|
||||
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="AllowBackup,GoogleAppIndexingWarning">
|
||||
<service
|
||||
android:label="@string/accessibility_service_name"
|
||||
android:name=".MonitorService"
|
||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
|
||||
<intent-filter>
|
||||
<action android:name="android.accessibilityservice.AccessibilityService"/>
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.accessibilityservice"
|
||||
android:resource="@xml/accessibilityservice"/>
|
||||
</service>
|
||||
<activity
|
||||
android:name=".WelcomeActivity"
|
||||
android:exported="true"
|
||||
@ -73,9 +85,6 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name=".MonitorService"
|
||||
android:exported="false" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -9,7 +9,6 @@ import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@ -30,7 +29,7 @@ public class AutoRootFragment extends ListFragment {
|
||||
private ApplicationAdapter listadaptor = null;
|
||||
public ListView listView;
|
||||
public SharedPreferences prefs;
|
||||
List<String> arrayBlackList, arrayWhiteList;
|
||||
List<String> arrayBlackList;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
@ -49,9 +48,6 @@ public class AutoRootFragment extends ListFragment {
|
||||
set.add("com.google.android.apps.walletnfcrel");
|
||||
set.add("com.google.android.gms");
|
||||
editor.putStringSet("auto_blacklist", set);
|
||||
set.clear();
|
||||
set.add("com.kermidas.TitaniumBackupPro");
|
||||
editor.putStringSet("auto_whitelist", set);
|
||||
editor.apply();
|
||||
}
|
||||
new LoadApplications().execute();
|
||||
@ -75,29 +71,15 @@ public class AutoRootFragment extends ListFragment {
|
||||
private void ToggleApp(String appToCheck, int position, View v) {
|
||||
|
||||
Set<String> blackListSet = prefs.getStringSet("auto_blacklist", null);
|
||||
Set<String> whiteListSet = prefs.getStringSet("auto_whitelist", null);
|
||||
|
||||
|
||||
assert blackListSet != null;
|
||||
arrayBlackList = new ArrayList<>(blackListSet);
|
||||
assert whiteListSet != null;
|
||||
arrayWhiteList = new ArrayList<>(whiteListSet);
|
||||
Log.d("Magisk", "Trying to toggle for " + appToCheck + " stringset is " + arrayBlackList.toString());
|
||||
|
||||
if ((!arrayBlackList.contains(appToCheck)) && (!arrayWhiteList.contains(appToCheck))) {
|
||||
Log.d("Magisk", "App is not in any array, adding to whitelist");
|
||||
arrayWhiteList.add(appToCheck);
|
||||
|
||||
} else if (arrayWhiteList.contains(appToCheck)) {
|
||||
Log.d("Magisk", "App is in whitelist, moving to blacklist");
|
||||
for (int i = 0; i < arrayWhiteList.size(); i++) {
|
||||
if (appToCheck.equals(arrayWhiteList.get(i))) {
|
||||
arrayWhiteList.remove(i);
|
||||
}
|
||||
}
|
||||
if (!arrayBlackList.contains(appToCheck)) {
|
||||
arrayBlackList.add(appToCheck);
|
||||
|
||||
} else if (arrayBlackList.contains(appToCheck)) {
|
||||
Log.d("Magisk", "App is in Blacklist, removing");
|
||||
} else {
|
||||
for (int i = 0; i < arrayBlackList.size(); i++) {
|
||||
if (appToCheck.equals(arrayBlackList.get(i))) {
|
||||
arrayBlackList.remove(i);
|
||||
@ -105,12 +87,7 @@ public class AutoRootFragment extends ListFragment {
|
||||
}
|
||||
|
||||
}
|
||||
Set<String> set2 = new HashSet<>(arrayBlackList);
|
||||
Log.d("Magisk", "Committing set, value is: " + set2);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putStringSet("auto_blacklist", new HashSet<>(arrayBlackList));
|
||||
editor.putStringSet("auto_whitelist", new HashSet<>(arrayWhiteList));
|
||||
editor.apply();
|
||||
prefs.edit().putStringSet("auto_blacklist", new HashSet<>(arrayBlackList)).apply();
|
||||
listadaptor.UpdateRootStatusView(position, v);
|
||||
|
||||
}
|
||||
|
@ -1,36 +1,28 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.app.usage.UsageStats;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.content.Context;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class MonitorService extends Service
|
||||
|
||||
{
|
||||
|
||||
public class MonitorService extends AccessibilityService {
|
||||
private static final String TAG = "Magisk";
|
||||
private final Handler handler = new Handler();
|
||||
private Boolean disableroot;
|
||||
@ -38,65 +30,85 @@ public class MonitorService extends Service
|
||||
private int counter = 0;
|
||||
private String mPackageName = "";
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
protected void onServiceConnected() {
|
||||
super.onServiceConnected();
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return START_STICKY;
|
||||
//Configure these here for compatibility with API 13 and below.
|
||||
AccessibilityServiceInfo config = new AccessibilityServiceInfo();
|
||||
config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
|
||||
config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
|
||||
disableroot = false;
|
||||
disablerootprev = disableroot;
|
||||
if (Build.VERSION.SDK_INT >= 16)
|
||||
//Just in case this helps
|
||||
config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
|
||||
|
||||
setServiceInfo(config);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
checkProcesses.run();
|
||||
Log.d("Magisk","MonitorService: Service created");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
Log.d("Magisk","MonitorService: Service destroyed");
|
||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
||||
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
|
||||
ComponentName componentName = new ComponentName(
|
||||
event.getPackageName().toString(),
|
||||
event.getClassName().toString()
|
||||
);
|
||||
|
||||
ActivityInfo activityInfo = tryGetActivity(componentName);
|
||||
boolean isActivity = activityInfo != null;
|
||||
if (isActivity) {
|
||||
Log.i("Magisk","CurrentActivity: " + componentName.getPackageName());
|
||||
String mPackage = componentName.getPackageName();
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
if (prefs.getBoolean("autoRootEnable", false)) {
|
||||
|
||||
Set<String> setBlackList = prefs.getStringSet("auto_blacklist", null);
|
||||
Set<String> setWhiteList = prefs.getStringSet("auto_whitelist", null);
|
||||
|
||||
if (setBlackList != null) {
|
||||
disableroot = setBlackList.contains(mPackage);
|
||||
if (disableroot) {
|
||||
ForceDisableRoot();
|
||||
} else {
|
||||
ForceEnableRoot();
|
||||
}
|
||||
String appFriendly = getAppName(mPackage);
|
||||
ShowNotification(disableroot,appFriendly);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable checkProcesses = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
if (prefs.getBoolean("autoRootEnable", false)) {
|
||||
|
||||
Set<String> setBlackList = prefs.getStringSet("auto_blacklist", null);
|
||||
Set<String> setWhiteList = prefs.getStringSet("auto_whitelist", null);
|
||||
|
||||
if (setBlackList != null) {
|
||||
disableroot = getStats(setBlackList);
|
||||
}
|
||||
|
||||
if (disableroot != disablerootprev) {
|
||||
|
||||
String rootstatus = (disableroot ? "disabled" : "enabled");
|
||||
if (disableroot) {
|
||||
ForceDisableRoot();
|
||||
} else {
|
||||
ForceEnableRoot();
|
||||
}
|
||||
|
||||
ShowNotification(disableroot);
|
||||
|
||||
}
|
||||
disablerootprev = disableroot;
|
||||
//Log.d(TAG,"Root check completed, set to " + (disableroot ? "disabled" : "enabled"));
|
||||
|
||||
}
|
||||
handler.postDelayed(checkProcesses, 500);
|
||||
private String getAppName (String packageName) {
|
||||
PackageManager pkManager = getPackageManager();
|
||||
ApplicationInfo appInfo;
|
||||
String appname = "";
|
||||
try {
|
||||
appInfo = pkManager.getApplicationInfo(packageName, 0);
|
||||
appname = (String) ((appInfo != null) ? pkManager.getApplicationLabel(appInfo) : "???");
|
||||
return appname;
|
||||
} catch (final PackageManager.NameNotFoundException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
private ActivityInfo tryGetActivity(ComponentName componentName) {
|
||||
try {
|
||||
return getPackageManager().getActivityInfo(componentName, 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ForceDisableRoot() {
|
||||
Log.d("Magisk", "MonitorService: Forcedisable called.");
|
||||
@ -113,10 +125,10 @@ public class MonitorService extends Service
|
||||
Utils.toggleRoot(true);
|
||||
if (!Utils.rootEnabled()) {
|
||||
Utils.toggleRoot(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowNotification(boolean rootAction) {
|
||||
private void ShowNotification(boolean rootAction, String packageName) {
|
||||
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
NotificationCompat.Builder mBuilder;
|
||||
|
||||
@ -130,10 +142,10 @@ public class MonitorService extends Service
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
if (mPackageName.equals("")) {
|
||||
if (packageName.equals("")) {
|
||||
rootMessage = "Root has been disabled";
|
||||
} else {
|
||||
rootMessage = "Root has been disabled for " + mPackageName;
|
||||
rootMessage = "Root has been disabled for " + packageName;
|
||||
}
|
||||
mBuilder =
|
||||
new NotificationCompat.Builder(getApplicationContext())
|
||||
@ -149,64 +161,7 @@ public class MonitorService extends Service
|
||||
|
||||
}
|
||||
|
||||
private boolean getStats(Set<String> seti) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
boolean inStats = false;
|
||||
if (seti != null) {
|
||||
ArrayList<String> statList = new ArrayList<>(seti);
|
||||
for (int i = 0; i < statList.size(); i++) {
|
||||
if (isAppForeground(statList.get(i))) {
|
||||
inStats = (isAppForeground(statList.get(i)));
|
||||
}
|
||||
}
|
||||
return inStats;
|
||||
}
|
||||
Log.d(TAG, "SDK check failed.");
|
||||
}
|
||||
return false;
|
||||
@Override
|
||||
public void onInterrupt() {
|
||||
}
|
||||
|
||||
private String getAppName (String packageName) {
|
||||
PackageManager pkManager = getPackageManager();
|
||||
ApplicationInfo appInfo;
|
||||
String appname = "";
|
||||
try {
|
||||
appInfo = pkManager.getApplicationInfo(packageName, 0);
|
||||
appname = (String) ((appInfo != null) ? pkManager.getApplicationLabel(appInfo) : "???");
|
||||
return appname;
|
||||
} catch (final PackageManager.NameNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean isAppForeground(String packageName) {
|
||||
UsageStatsManager usageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
|
||||
long time = System.currentTimeMillis();
|
||||
List<UsageStats> stats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 10, time);
|
||||
String topPackageName = "";
|
||||
if (stats != null) {
|
||||
|
||||
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<>();
|
||||
for (UsageStats usageStats : stats) {
|
||||
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
|
||||
|
||||
}
|
||||
if (!mySortedMap.isEmpty()) {
|
||||
topPackageName = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
|
||||
if (topPackageName.equals("com.topjohnwu.magisk")) {
|
||||
mySortedMap.remove(mySortedMap.lastKey());
|
||||
topPackageName = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
|
||||
Log.d("Magisk","MonitorService: Package is " + topPackageName);
|
||||
mPackageName = getAppName(topPackageName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return topPackageName.equals(packageName);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,6 @@ import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
@ -126,13 +125,7 @@ public class RootFragment extends Fragment {
|
||||
}
|
||||
|
||||
|
||||
private void CheckAccessPermissions() {
|
||||
if (!Utils.hasStatsPermission(getActivity())) {
|
||||
Toast.makeText(getActivity(),"Please allow Usage Access for auto root to work.",Toast.LENGTH_LONG).show();
|
||||
startActivityForResult(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS), 100);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
@ -141,24 +134,27 @@ public class RootFragment extends Fragment {
|
||||
// Make sure the request was successful
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Log.d("Magisk","Got result code OK for permissions");
|
||||
Toast.makeText(getActivity(),"Auto-root disabled, permissions required.",Toast.LENGTH_LONG).show();
|
||||
|
||||
|
||||
} else {
|
||||
autoRootToggle.setEnabled(false);
|
||||
Toast.makeText(getActivity(),"Auto-root disabled, permissions required.",Toast.LENGTH_LONG).show();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void ToggleAutoRoot(boolean toggleState) {
|
||||
CheckAccessPermissions();
|
||||
if (Utils.hasStatsPermission(getActivity())) {
|
||||
autoRootStatus = toggleState;
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putBoolean("autoRootEnable", (toggleState));
|
||||
editor.apply();
|
||||
if (toggleState) {
|
||||
if (!Utils.hasStatsPermission(getActivity(),"com.topjohnwu.magisk/WindowChangeDetectingService")) {
|
||||
Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
|
||||
startActivityForResult(intent, 100);
|
||||
}
|
||||
Intent myIntent = new Intent(getActivity(), MonitorService.class);
|
||||
getActivity().startService(myIntent);
|
||||
rootToggle.setEnabled(false);
|
||||
@ -172,7 +168,7 @@ public class RootFragment extends Fragment {
|
||||
getActivity().stopService(myIntent);
|
||||
rootToggle.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -9,7 +9,6 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.NavigationView;
|
||||
@ -86,7 +85,7 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
|
||||
@Override
|
||||
public void onDrawerOpened(View drawerView) {
|
||||
super.onDrawerOpened(drawerView);
|
||||
super.onDrawerSlide(drawerView, 0); // this disables the arrow @ completed state
|
||||
super.onDrawerSlide(drawerView, 0); // this disables the arrow @ completed tate
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -9,6 +9,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -24,8 +25,6 @@ public class ApplicationAdapter extends ArrayAdapter<ApplicationInfo> {
|
||||
private PackageManager packageManager;
|
||||
public ArrayList arrayList;
|
||||
public SharedPreferences prefs;
|
||||
private int BLACKLIST_LIST = 1;
|
||||
private int WHITELIST_LIST = 2;
|
||||
|
||||
public ApplicationAdapter(Context context, int textViewResourceId,
|
||||
List<ApplicationInfo> appsList) {
|
||||
@ -66,14 +65,14 @@ public class ApplicationAdapter extends ArrayAdapter<ApplicationInfo> {
|
||||
TextView appName = (TextView) view.findViewById(R.id.app_name);
|
||||
TextView packageName = (TextView) view.findViewById(R.id.app_paackage);
|
||||
ImageView iconview = (ImageView) view.findViewById(R.id.app_icon);
|
||||
ImageView statusview = (ImageView) view.findViewById(R.id.app_status);
|
||||
CheckBox statusview = (CheckBox) view.findViewById(R.id.checkbox);
|
||||
appName.setText(applicationInfo.loadLabel(packageManager));
|
||||
packageName.setText(applicationInfo.packageName);
|
||||
iconview.setImageDrawable(applicationInfo.loadIcon(packageManager));
|
||||
if (CheckApp(applicationInfo.packageName, BLACKLIST_LIST)) {
|
||||
statusview.setImageDrawable(this.context.getDrawable(R.drawable.root));
|
||||
if (CheckApp(applicationInfo.packageName)) {
|
||||
statusview.setChecked(true);
|
||||
} else {
|
||||
statusview.setImageDrawable(null);
|
||||
statusview.setChecked(false);
|
||||
}
|
||||
}
|
||||
return view;
|
||||
@ -88,21 +87,18 @@ public class ApplicationAdapter extends ArrayAdapter<ApplicationInfo> {
|
||||
}
|
||||
ApplicationInfo applicationInfo = appsList.get(position);
|
||||
if (null != applicationInfo) {
|
||||
ImageView statusview = (ImageView) view.findViewById(R.id.app_status);
|
||||
if (CheckApp(applicationInfo.packageName, BLACKLIST_LIST)) {
|
||||
statusview.setImageDrawable(this.context.getDrawable(R.drawable.root));
|
||||
} else if (CheckApp(applicationInfo.packageName, WHITELIST_LIST)) {
|
||||
statusview.setImageDrawable(this.context.getDrawable(R.drawable.ic_stat_notification_autoroot_off));
|
||||
CheckBox statusview = (CheckBox) view.findViewById(R.id.checkbox);
|
||||
if (CheckApp(applicationInfo.packageName)) {
|
||||
statusview.setChecked(true);
|
||||
} else {
|
||||
statusview.setImageDrawable(null);
|
||||
statusview.setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean CheckApp(String appToCheck, int list) {
|
||||
private boolean CheckApp(String appToCheck) {
|
||||
boolean starter = false;
|
||||
if (list == BLACKLIST_LIST) {
|
||||
Set<String> set = prefs.getStringSet("auto_blacklist", null);
|
||||
if (set != null) {
|
||||
arrayList = new ArrayList<>(set);
|
||||
@ -113,18 +109,6 @@ public class ApplicationAdapter extends ArrayAdapter<ApplicationInfo> {
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Set<String> set = prefs.getStringSet("auto_whitelist", null);
|
||||
if (set != null) {
|
||||
arrayList = new ArrayList<>(set);
|
||||
for (String string : set) {
|
||||
if (string.equals(appToCheck)) {
|
||||
starter = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return starter;
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.topjohnwu.magisk.utils;
|
||||
|
||||
import android.Manifest;
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppOpsManager;
|
||||
@ -23,6 +24,8 @@ import android.support.v7.app.AlertDialog;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.ModulesFragment;
|
||||
@ -171,14 +174,24 @@ public class Utils {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static boolean hasStatsPermission(Context context) {
|
||||
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
||||
int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
|
||||
android.os.Process.myUid(), context.getPackageName());
|
||||
return mode == AppOpsManager.MODE_ALLOWED;
|
||||
|
||||
|
||||
public static boolean hasStatsPermission(Context context, String id) {
|
||||
|
||||
AccessibilityManager am = (AccessibilityManager) context
|
||||
.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||
|
||||
List<AccessibilityServiceInfo> runningServices = am
|
||||
.getEnabledAccessibilityServiceList(AccessibilityEvent.TYPES_ALL_MASK);
|
||||
for (AccessibilityServiceInfo service : runningServices) {
|
||||
if (id.equals(service.getId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public abstract static class DownloadReceiver extends BroadcastReceiver {
|
||||
public Context mContext;
|
||||
|
@ -1,59 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="5dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:padding="3dp"
|
||||
android:scaleType="centerCrop"/>
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="3dip"
|
||||
android:layout_marginLeft="8dip"
|
||||
android:layout_marginRight="8dip"
|
||||
android:layout_marginTop="3dip"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
|
||||
card_view:cardCornerRadius="2dp"
|
||||
card_view:cardElevation="2dp"
|
||||
style="@style/Base.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="horizontal">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:padding="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/lynn"
|
||||
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerVertical="true"
|
||||
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="50dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_paackage"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"></RelativeLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/app_status"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:padding="3dp"
|
||||
android:scaleType="centerCrop"/>
|
||||
android:layout_toEndOf="@+id/app_icon"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingEnd="3dp"
|
||||
android:paddingStart="3dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_paackage"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@+id/app_name"
|
||||
android:layout_toEndOf="@+id/app_icon"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingEnd="3dp"
|
||||
android:paddingStart="3dp" />
|
||||
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="68dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:focusable="false"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_menu_overflow_material"
|
||||
/>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
|
||||
|
@ -6,7 +6,10 @@
|
||||
<ListView android:id="@android:id/list"
|
||||
android:paddingTop="5dip"
|
||||
android:paddingBottom="5dip"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"/>
|
||||
android:divider="@android:color/transparent"
|
||||
android:dividerHeight="10.0sp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="15dp" />
|
||||
|
||||
</LinearLayout>
|
@ -5,10 +5,7 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="3dip"
|
||||
android:layout_marginLeft="8dip"
|
||||
android:layout_marginRight="8dip"
|
||||
android:layout_marginTop="3dip"
|
||||
android:layout_margin="8dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
card_view:cardCornerRadius="2dp"
|
||||
|
@ -82,6 +82,8 @@
|
||||
<string name="permissionNotGranted">This feature will not work without permission to write external storage.</string>
|
||||
<string name="no_root_access">No root access, functionality limited</string>
|
||||
<string name="no_thanks">No thanks</string>
|
||||
<string name="accessibility_service_description">Accessibility service required for Magisk auto-unroot feature</string>
|
||||
<string name="accessibility_service_name">Magisk Manager</string>
|
||||
<string name="update_title">%1$s Update!</string>
|
||||
<string name="update_msg">New version v%2$s of %1$s is available!\nChangelog:\n%3$s</string>
|
||||
<string name="download_install">Download and install</string>
|
||||
|
11
app/src/main/res/xml/accessibilityservice.xml
Normal file
11
app/src/main/res/xml/accessibilityservice.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- These options MUST be specified here in order for the events to be received on first
|
||||
start in Android 4.1.1 -->
|
||||
<accessibility-service
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:accessibilityEventTypes="typeWindowStateChanged"
|
||||
android:accessibilityFeedbackType="feedbackGeneric"
|
||||
android:accessibilityFlags="flagIncludeNotImportantViews"
|
||||
android:description="@string/accessibility_service_description"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
tools:ignore="UnusedAttribute"/>
|
Loading…
Reference in New Issue
Block a user