From 2cdb6b811f8d801957e5a7fcaeba79287ffa23ce Mon Sep 17 00:00:00 2001 From: d8ahazard Date: Tue, 20 Sep 2016 00:05:41 -0500 Subject: [PATCH] Quicksettings Tile, more AutoRoot fun It's so purdy... --- app/src/main/AndroidManifest.xml | 51 +++++--- .../com/topjohnwu/magisk/MonitorService.java | 22 ++-- .../magisk/QuickSettingTileService.java | 77 ++++++++++++ .../com/topjohnwu/magisk/RootFragment.java | 116 +++++++++--------- .../com/topjohnwu/magisk/WelcomeActivity.java | 4 + .../com/topjohnwu/magisk/utils/Utils.java | 64 +++++++--- 6 files changed, 223 insertions(+), 111 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/QuickSettingTileService.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f3d05d832..c75618436 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,15 +1,15 @@ - + - + + tools:ignore="ProtectedPermissions"/> @@ -30,10 +30,20 @@ android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice"/> + + + + + + + android:configChanges="orientation|screenSize" + android:exported="true"> @@ -42,28 +52,29 @@ + android:icon="@drawable/ic_chooser" + android:label="@string/choose_file"> - + - - + + - + + + android:permission="android.permission.MANAGE_DOCUMENTS"> - + + android:exported="false" + android:grantUriPermissions="true"> + android:resource="@xml/file_paths"/> - + diff --git a/app/src/main/java/com/topjohnwu/magisk/MonitorService.java b/app/src/main/java/com/topjohnwu/magisk/MonitorService.java index 49faf019e..476e34250 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MonitorService.java +++ b/app/src/main/java/com/topjohnwu/magisk/MonitorService.java @@ -11,7 +11,6 @@ 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.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.util.Log; @@ -19,16 +18,11 @@ import android.view.accessibility.AccessibilityEvent; import com.topjohnwu.magisk.utils.Utils; -import java.util.ArrayList; import java.util.Set; public class MonitorService extends AccessibilityService { private static final String TAG = "Magisk"; - private final Handler handler = new Handler(); private Boolean disableroot; - private Boolean disablerootprev; - private int counter = 0; - private String mPackageName = ""; @Override protected void onServiceConnected() { @@ -39,7 +33,6 @@ public class MonitorService extends AccessibilityService { 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; @@ -51,7 +44,7 @@ public class MonitorService extends AccessibilityService { @Override public void onCreate() { super.onCreate(); - Log.d("Magisk","MonitorService: Service created"); + Log.d("Magisk", "MonitorService: Service created"); } @Override @@ -65,14 +58,13 @@ public class MonitorService extends AccessibilityService { ActivityInfo activityInfo = tryGetActivity(componentName); boolean isActivity = activityInfo != null; if (isActivity) { - Log.i("Magisk","CurrentActivity: " + componentName.getPackageName()); + Log.i("Magisk", "CurrentActivity: " + componentName.getPackageName()); String mPackage = componentName.getPackageName(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); if (prefs.getBoolean("autoRootEnable", false)) { Set setBlackList = prefs.getStringSet("auto_blacklist", null); - Set setWhiteList = prefs.getStringSet("auto_whitelist", null); if (setBlackList != null) { disableroot = setBlackList.contains(mPackage); @@ -82,21 +74,21 @@ public class MonitorService extends AccessibilityService { ForceEnableRoot(); } String appFriendly = getAppName(mPackage); - ShowNotification(disableroot,appFriendly); + ShowNotification(disableroot, appFriendly); } } } } } - private String getAppName (String packageName) { + private String getAppName(String packageName) { PackageManager pkManager = getPackageManager(); ApplicationInfo appInfo; - String appname = ""; + String appName; try { appInfo = pkManager.getApplicationInfo(packageName, 0); - appname = (String) ((appInfo != null) ? pkManager.getApplicationLabel(appInfo) : "???"); - return appname; + appName = (String) ((appInfo != null) ? pkManager.getApplicationLabel(appInfo) : "???"); + return appName; } catch (final PackageManager.NameNotFoundException e) { return ""; } diff --git a/app/src/main/java/com/topjohnwu/magisk/QuickSettingTileService.java b/app/src/main/java/com/topjohnwu/magisk/QuickSettingTileService.java new file mode 100644 index 000000000..02b820412 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/QuickSettingTileService.java @@ -0,0 +1,77 @@ +package com.topjohnwu.magisk; + +import android.annotation.SuppressLint; +import android.graphics.drawable.Icon; +import android.service.quicksettings.Tile; +import android.service.quicksettings.TileService; +import android.util.Log; + +import com.topjohnwu.magisk.utils.Utils; + +@SuppressLint("NewApi") +public class QuickSettingTileService extends TileService { + private int STATE_CURRENT; + + public QuickSettingTileService() { + } + + @Override + public void onTileAdded() { + super.onTileAdded(); + setupState(); + } + + @Override + public void onClick() { + switchState(); + + } + + private void setupState() { + Icon iconRoot = Icon.createWithResource(getApplicationContext(), R.drawable.root); + Icon iconAuto = Icon.createWithResource(getApplicationContext(), R.drawable.ic_autoroot); + Tile tile = this.getQsTile(); + boolean autoRootStatus = Utils.autoRootEnabled(getApplicationContext()); + boolean rootStatus = Utils.rootStatus(); + Log.d("Magisk", "QST: Auto and root are " + autoRootStatus + " and " + rootStatus); + if (autoRootStatus) { + tile.setLabel("Auto-root"); + tile.setIcon(iconAuto); + tile.setState(Tile.STATE_ACTIVE); + STATE_CURRENT = 0; + } else { + if (rootStatus) { + tile.setLabel("Root enabled"); + tile.setIcon(iconRoot); + tile.setState(Tile.STATE_ACTIVE); + STATE_CURRENT = 1; + + } else { + tile.setLabel("Root disabled"); + tile.setIcon(iconRoot); + tile.setState(Tile.STATE_INACTIVE); + STATE_CURRENT = 2; + + } + } + tile.updateTile(); + } + + private void switchState() { + Log.d("Magisk", "QST: Switching state to " + STATE_CURRENT); + switch (STATE_CURRENT) { + case 0: + Utils.toggleRoot(false); + Utils.toggleAutoRoot(false, getApplicationContext()); + break; + case 1: + Utils.toggleAutoRoot(true, getApplicationContext()); + break; + case 2: + Utils.toggleRoot(true); + break; + } + setupState(); + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/RootFragment.java b/app/src/main/java/com/topjohnwu/magisk/RootFragment.java index 7865c76a9..8e1b11a87 100644 --- a/app/src/main/java/com/topjohnwu/magisk/RootFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/RootFragment.java @@ -94,9 +94,8 @@ public class RootFragment extends Fragment { prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); - if (prefs.contains("autoRootEnable")) { - autoRootStatus = prefs.getBoolean("autoRootEnable",false); + autoRootStatus = prefs.getBoolean("autoRootEnable", false); rootToggle.setEnabled(false); } else { autoRootStatus = false; @@ -124,21 +123,18 @@ public class RootFragment extends Fragment { return view; } - - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { // Check which request we're responding to + Log.d("Magisk", "Got result: " + requestCode + " and " + resultCode); if (requestCode == 100) { // Make sure the request was successful if (resultCode == Activity.RESULT_OK) { - Log.d("Magisk","Got result code OK for permissions"); - + Log.d("Magisk", "Got result code OK for permissions"); } else { autoRootToggle.setEnabled(false); - Toast.makeText(getActivity(),"Auto-root disabled, permissions required.",Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity(), "Auto-root disabled, permissions required.", Toast.LENGTH_LONG).show(); } @@ -146,28 +142,28 @@ public class RootFragment extends Fragment { } private void ToggleAutoRoot(boolean toggleState) { - 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); - boolean boo = Utils.isMyServiceRunning(MonitorService.class, getActivity()); - if (boo) { - Intent myServiceIntent = new Intent(getActivity(), MonitorService.class); - getActivity().startService(myServiceIntent); - } - } else { - Intent myIntent = new Intent(getActivity(), MonitorService.class); - getActivity().stopService(myIntent); - rootToggle.setEnabled(true); + autoRootStatus = toggleState; + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean("autoRootEnable", (toggleState)); + editor.apply(); + if (toggleState) { + if (!Utils.hasServicePermission(getActivity())) { + 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); + boolean boo = Utils.isMyServiceRunning(MonitorService.class, getActivity()); + if (boo) { + Intent myServiceIntent = new Intent(getActivity(), MonitorService.class); + getActivity().startService(myServiceIntent); + } + } else { + Intent myIntent = new Intent(getActivity(), MonitorService.class); + getActivity().stopService(myIntent); + rootToggle.setEnabled(true); + } } @@ -254,39 +250,39 @@ public class RootFragment extends Fragment { break; case 1: // Proper root - if (autoRootStatus) { - rootStatusContainer.setBackgroundColor(green500); - rootStatusIcon.setImageResource(statusAuto); - rootStatusIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP); - rootStatus.setTextColor(green500); - rootStatus.setText(R.string.root_auto_unmounted); - rootToggle.setEnabled(false); - safetyNetStatusIcon.setImageResource(statusOK); - safetyNetStatus.setText(R.string.root_auto_unmounted_info); + if (autoRootStatus) { + rootStatusContainer.setBackgroundColor(green500); + rootStatusIcon.setImageResource(statusAuto); + rootStatusIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP); + rootStatus.setTextColor(green500); + rootStatus.setText(R.string.root_auto_unmounted); + rootToggle.setEnabled(false); + safetyNetStatusIcon.setImageResource(statusOK); + safetyNetStatus.setText(R.string.root_auto_unmounted_info); + break; + } else { + rootToggle.setEnabled(true); + if (Utils.rootEnabled()) { + // Mounted + rootStatusContainer.setBackgroundColor(accent); + rootStatusIcon.setImageResource(statusError); + rootStatus.setTextColor(accent); + rootStatus.setText(R.string.root_enabled); + rootToggle.setChecked(true); + safetyNetStatusIcon.setImageResource(statusError); + safetyNetStatus.setText(R.string.root_enabled_info); break; } else { - rootToggle.setEnabled(true); - if (Utils.rootEnabled()) { - // Mounted - rootStatusContainer.setBackgroundColor(accent); - rootStatusIcon.setImageResource(statusError); - rootStatus.setTextColor(accent); - rootStatus.setText(R.string.root_enabled); - rootToggle.setChecked(true); - safetyNetStatusIcon.setImageResource(statusError); - safetyNetStatus.setText(R.string.root_enabled_info); - break; - } else { - // Disabled - rootStatusContainer.setBackgroundColor(green500); - rootStatusIcon.setImageResource(statusOK); - rootStatus.setTextColor(green500); - rootStatus.setText(R.string.root_disabled); - rootToggle.setChecked(false); - safetyNetStatusIcon.setImageResource(statusOK); - safetyNetStatus.setText(R.string.root_disabled_info); - break; - } + // Disabled + rootStatusContainer.setBackgroundColor(green500); + rootStatusIcon.setImageResource(statusOK); + rootStatus.setTextColor(green500); + rootStatus.setText(R.string.root_disabled); + rootToggle.setChecked(false); + safetyNetStatusIcon.setImageResource(statusOK); + safetyNetStatus.setText(R.string.root_disabled_info); + break; + } } case 2: // Improper root diff --git a/app/src/main/java/com/topjohnwu/magisk/WelcomeActivity.java b/app/src/main/java/com/topjohnwu/magisk/WelcomeActivity.java index 309847076..e2da03e0a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/WelcomeActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/WelcomeActivity.java @@ -62,6 +62,10 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView } } } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Intent serviceIntent = new Intent(this, QuickSettingTileService.class); + startService(serviceIntent); + } if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0); diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 5ef1ed198..2fba7801d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -1,10 +1,8 @@ package com.topjohnwu.magisk.utils; import android.Manifest; -import android.accessibilityservice.AccessibilityServiceInfo; import android.app.Activity; import android.app.ActivityManager; -import android.app.AppOpsManager; import android.app.DownloadManager; import android.app.ProgressDialog; import android.content.BroadcastReceiver; @@ -17,18 +15,20 @@ import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Environment; +import android.preference.PreferenceManager; import android.provider.DocumentsContract; +import android.provider.Settings; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AlertDialog; +import android.text.TextUtils; 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; +import com.topjohnwu.magisk.MonitorService; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.ReposFragment; import com.topjohnwu.magisk.module.Module; @@ -90,6 +90,11 @@ public class Utils { return Boolean.parseBoolean(ret.get(0)); } + public static boolean autoRootEnabled(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context).getBoolean("autoRootEnable", false); + + } + public static boolean createFile(String path) { String command = "touch " + path + " 2>/dev/null; if [ -f " + path + " ]; then echo true; else echo false; fi"; if (!Shell.rootAccess()) { @@ -116,6 +121,17 @@ public class Utils { } } + public static void toggleAutoRoot(Boolean b, Context context) { + PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean("autoRootEnable", b).apply(); + Intent myServiceIntent = new Intent(context, MonitorService.class); + if (b) { + context.startService(myServiceIntent); + } else { + context.stopService(myServiceIntent); + } + + } + public static List getModList(String path) { List ret; ret = Shell.sh("find " + path + " -type d -maxdepth 1 ! -name \"*.core\" ! -name \"*lost+found\" ! -name \"*magisk\""); @@ -174,25 +190,41 @@ public class Utils { return value; } + // To check if service is enabled + public static boolean hasServicePermission(Context mContext) { + int accessibilityEnabled = 0; + final String service = mContext.getPackageName() + "/" + MonitorService.class.getCanonicalName(); + try { + accessibilityEnabled = Settings.Secure.getInt( + mContext.getApplicationContext().getContentResolver(), + android.provider.Settings.Secure.ACCESSIBILITY_ENABLED); + } catch (Settings.SettingNotFoundException e) { + Log.e(TAG, "Error finding setting, default accessibility to not found: " + + e.getMessage()); + } + TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':'); + if (accessibilityEnabled == 1) { + String settingValue = Settings.Secure.getString( + mContext.getApplicationContext().getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); + if (settingValue != null) { + mStringColonSplitter.setString(settingValue); + while (mStringColonSplitter.hasNext()) { + String accessibilityService = mStringColonSplitter.next(); - public static boolean hasStatsPermission(Context context, String id) { - - AccessibilityManager am = (AccessibilityManager) context - .getSystemService(Context.ACCESSIBILITY_SERVICE); - - List runningServices = am - .getEnabledAccessibilityServiceList(AccessibilityEvent.TYPES_ALL_MASK); - for (AccessibilityServiceInfo service : runningServices) { - if (id.equals(service.getId())) { - return true; + if (accessibilityService.equalsIgnoreCase(service)) { + return true; + } + } } + } else { + Log.v(TAG, "***ACCESSIBILITY IS DISABLED***"); } return false; } - public abstract static class DownloadReceiver extends BroadcastReceiver { public Context mContext; long downloadID; @@ -479,7 +511,7 @@ public class Utils { if (serviceClass.getName().equals(service.service.getClassName())) { return true; } - } + } return false; }