Add multiuser support

This commit is contained in:
topjohnwu 2017-05-27 02:41:24 +08:00
parent 738f943a68
commit 2a7d996881
7 changed files with 84 additions and 74 deletions

View File

@ -3,7 +3,6 @@ package com.topjohnwu.magisk;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
@ -18,7 +17,6 @@ import android.widget.TextView;
import com.topjohnwu.magisk.components.AboutCardRow; import com.topjohnwu.magisk.components.AboutCardRow;
import com.topjohnwu.magisk.components.Activity; import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.components.AlertDialogBuilder; import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.utils.Logger;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;

View File

@ -30,6 +30,10 @@ public class MagiskManager extends Application {
public static final String UNINSTALLER = "magisk_uninstaller.sh"; public static final String UNINSTALLER = "magisk_uninstaller.sh";
public static final String INTENT_SECTION = "section"; public static final String INTENT_SECTION = "section";
public static final String BUSYBOX_VERSION = "1.26.2"; public static final String BUSYBOX_VERSION = "1.26.2";
public static final String ROOT_ACCESS_PROP = "persist.magisk.root";
public static final String MULTIUSER_MODE_PROP = "persist.magisk.multiuser";
public static final String MAGISKHIDE_PROP = "persist.magisk.hide";
public static final String DISABLE_INDICATION_PROP = "ro.magisk.disable";
// Events // Events
public final CallbackEvent<Void> blockDetectionDone = new CallbackEvent<>(); public final CallbackEvent<Void> blockDetectionDone = new CallbackEvent<>();
@ -53,7 +57,6 @@ public class MagiskManager extends Application {
public boolean isSuClient = false; public boolean isSuClient = false;
public String suVersion = null; public String suVersion = null;
public boolean disabled; public boolean disabled;
public boolean magiskHideStarted;
// Data // Data
public ValueSortedMap<String, Repo> repoMap; public ValueSortedMap<String, Repo> repoMap;
@ -72,6 +75,7 @@ public class MagiskManager extends Application {
public int suRequestTimeout; public int suRequestTimeout;
public int suLogTimeout = 14; public int suLogTimeout = 14;
public int suAccessState; public int suAccessState;
public int multiuserMode;
public int suResponseType; public int suResponseType;
public int suNotificationType; public int suNotificationType;
@ -130,6 +134,7 @@ public class MagiskManager extends Application {
.putString("su_auto_response", String.valueOf(suResponseType)) .putString("su_auto_response", String.valueOf(suResponseType))
.putString("su_notification", String.valueOf(suNotificationType)) .putString("su_notification", String.valueOf(suNotificationType))
.putString("su_access", String.valueOf(suAccessState)) .putString("su_access", String.valueOf(suAccessState))
.putString("multiuser_mode", String.valueOf(multiuserMode))
.putString("busybox_version", BUSYBOX_VERSION) .putString("busybox_version", BUSYBOX_VERSION)
.apply(); .apply();
// Add busybox to PATH // Add busybox to PATH
@ -149,12 +154,17 @@ public class MagiskManager extends Application {
isSuClient = suVersion.toUpperCase().contains("MAGISK"); isSuClient = suVersion.toUpperCase().contains("MAGISK");
} }
if (isSuClient) { if (isSuClient) {
ret = Shell.sh("getprop persist.sys.root_access"); ret = Shell.sh("getprop " + ROOT_ACCESS_PROP);
if (Utils.isValidShellResponse(ret)) { if (Utils.isValidShellResponse(ret)) {
suAccessState = Integer.parseInt(ret.get(0)); suAccessState = Integer.parseInt(ret.get(0));
} else { } else {
Shell.su(true, "setprop persist.sys.root_access 3"); suAccessState = 0;
suAccessState = 3; }
ret = Shell.sh("getprop " + MULTIUSER_MODE_PROP);
if (Utils.isValidShellResponse(ret)) {
multiuserMode = Integer.parseInt(ret.get(0));
} else {
multiuserMode = 0;
} }
} }
} }
@ -177,21 +187,17 @@ public class MagiskManager extends Application {
magiskVersionCode = Integer.parseInt(ret.get(0)); magiskVersionCode = Integer.parseInt(ret.get(0));
} catch (NumberFormatException ignored) {} } catch (NumberFormatException ignored) {}
} }
ret = Shell.sh("getprop ro.magisk.disable"); ret = Shell.sh("getprop " + DISABLE_INDICATION_PROP);
try { try {
disabled = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0; disabled = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
disabled = false; disabled = false;
} }
ret = Shell.sh("getprop persist.magisk.hide"); ret = Shell.sh("getprop " + MAGISKHIDE_PROP);
try { try {
magiskHideStarted = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0; magiskHide = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
magiskHideStarted = false; magiskHide = false;
}
if (magiskHideStarted) {
magiskHide = true;
} }
} }

View File

@ -60,11 +60,8 @@ public class SettingsActivity extends Activity {
private SharedPreferences prefs; private SharedPreferences prefs;
private PreferenceScreen prefScreen; private PreferenceScreen prefScreen;
private ListPreference suAccess, autoRes, suNotification, requestTimeout; private ListPreference suAccess, autoRes, suNotification, requestTimeout, multiuserMode;
private MagiskManager magiskManager;
private MagiskManager getApplication() {
return Utils.getMagiskManager(getActivity());
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -72,6 +69,7 @@ public class SettingsActivity extends Activity {
addPreferencesFromResource(R.xml.app_settings); addPreferencesFromResource(R.xml.app_settings);
prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
prefScreen = getPreferenceScreen(); prefScreen = getPreferenceScreen();
magiskManager = Utils.getMagiskManager(getActivity());
PreferenceCategory magiskCategory = (PreferenceCategory) findPreference("magisk"); PreferenceCategory magiskCategory = (PreferenceCategory) findPreference("magisk");
PreferenceCategory suCategory = (PreferenceCategory) findPreference("superuser"); PreferenceCategory suCategory = (PreferenceCategory) findPreference("superuser");
@ -81,6 +79,7 @@ public class SettingsActivity extends Activity {
autoRes = (ListPreference) findPreference("su_auto_response"); autoRes = (ListPreference) findPreference("su_auto_response");
requestTimeout = (ListPreference) findPreference("su_request_timeout"); requestTimeout = (ListPreference) findPreference("su_request_timeout");
suNotification = (ListPreference) findPreference("su_notification"); suNotification = (ListPreference) findPreference("su_notification");
multiuserMode = (ListPreference) findPreference("multiuser_mode");
setSummary(); setSummary();
@ -97,10 +96,10 @@ public class SettingsActivity extends Activity {
prefScreen.removePreference(magiskCategory); prefScreen.removePreference(magiskCategory);
prefScreen.removePreference(suCategory); prefScreen.removePreference(suCategory);
} else { } else {
if (!getApplication().isSuClient) { if (!magiskManager.isSuClient) {
prefScreen.removePreference(suCategory); prefScreen.removePreference(suCategory);
} }
if (getApplication().magiskVersionCode < 130) { if (magiskManager.magiskVersionCode < 130) {
prefScreen.removePreference(magiskCategory); prefScreen.removePreference(magiskCategory);
} }
} }
@ -126,9 +125,9 @@ public class SettingsActivity extends Activity {
switch (key) { switch (key) {
case "dark_theme": case "dark_theme":
enabled = prefs.getBoolean("dark_theme", false); enabled = prefs.getBoolean("dark_theme", false);
if (getApplication().isDarkTheme != enabled) { if (magiskManager.isDarkTheme != enabled) {
getApplication().isDarkTheme = enabled; magiskManager.isDarkTheme = enabled;
getApplication().reloadMainActivity.trigger(); magiskManager.reloadMainActivity.trigger();
getActivity().recreate(); getActivity().recreate();
} }
break; break;
@ -148,29 +147,10 @@ public class SettingsActivity extends Activity {
}.exec(); }.exec();
Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show(); Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show();
break; break;
case "busybox":
enabled = prefs.getBoolean("busybox", false);
new SerialTask<Void, Void, Void>() {
private boolean enable = enabled;
@Override
protected Void doInBackground(Void... voids) {
if (enable) {
Shell.su(
"setprop persist.magisk.busybox 1",
"sh /sbin/magic_mask.sh mount_busybox");
} else {
Shell.su(
"setprop persist.magisk.busybox 0",
"umount /system/xbin");
}
return null;
}
}.exec();
break;
case "magiskhide": case "magiskhide":
enabled = prefs.getBoolean("magiskhide", false); enabled = prefs.getBoolean("magiskhide", false);
if (enabled) { if (enabled) {
if (!getApplication().isSuClient) { if (!magiskManager.isSuClient) {
new AlertDialogBuilder(getActivity()) new AlertDialogBuilder(getActivity())
.setTitle(R.string.no_magisksu_title) .setTitle(R.string.no_magisksu_title)
.setMessage(R.string.no_magisksu_msg) .setMessage(R.string.no_magisksu_msg)
@ -202,17 +182,32 @@ public class SettingsActivity extends Activity {
}.exec(); }.exec();
break; break;
case "su_access": case "su_access":
getApplication().suAccessState = Utils.getPrefsInt(prefs, "su_access", 0); magiskManager.suAccessState = Utils.getPrefsInt(prefs, "su_access", 0);
Shell.su("setprop persist.sys.root_access " + getApplication().suAccessState); new SerialTask<Void, Void, Void>(getActivity()) {
@Override
protected Void doInBackground(Void... params) {
Shell.su("setprop " + MagiskManager.ROOT_ACCESS_PROP + " " + magiskManager.suAccessState);
return null;
}
}.exec();
break; break;
case "multiuser_mode":
magiskManager.multiuserMode = Utils.getPrefsInt(prefs, "multiuser_mode", 0);
new SerialTask<Void, Void, Void>(getActivity()) {
@Override
protected Void doInBackground(Void... params) {
Shell.su("setprop " + MagiskManager.MULTIUSER_MODE_PROP + " " + magiskManager.multiuserMode);
return null;
}
}.exec();
case "su_request_timeout": case "su_request_timeout":
getApplication().suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10); magiskManager.suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
break; break;
case "su_auto_response": case "su_auto_response":
getApplication().suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0); magiskManager.suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
break; break;
case "su_notification": case "su_notification":
getApplication().suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1); magiskManager.suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
break; break;
case "developer_logging": case "developer_logging":
MagiskManager.devLogging = prefs.getBoolean("developer_logging", false); MagiskManager.devLogging = prefs.getBoolean("developer_logging", false);
@ -226,13 +221,15 @@ public class SettingsActivity extends Activity {
private void setSummary() { private void setSummary() {
suAccess.setSummary(getResources() suAccess.setSummary(getResources()
.getStringArray(R.array.su_access)[getApplication().suAccessState]); .getStringArray(R.array.su_access)[magiskManager.suAccessState]);
autoRes.setSummary(getResources() autoRes.setSummary(getResources()
.getStringArray(R.array.auto_response)[getApplication().suResponseType]); .getStringArray(R.array.auto_response)[magiskManager.suResponseType]);
suNotification.setSummary(getResources() suNotification.setSummary(getResources()
.getStringArray(R.array.su_notification)[getApplication().suNotificationType]); .getStringArray(R.array.su_notification)[magiskManager.suNotificationType]);
requestTimeout.setSummary( requestTimeout.setSummary(
getString(R.string.request_timeout_summary, prefs.getString("su_request_timeout", "10"))); getString(R.string.request_timeout_summary, prefs.getString("su_request_timeout", "10")));
multiuserMode.setSummary(getResources()
.getStringArray(R.array.multiuser_summary)[magiskManager.multiuserMode]);
} }
} }

View File

@ -2,12 +2,6 @@ package com.topjohnwu.magisk.services;
import android.app.IntentService; import android.app.IntentService;
import android.content.Intent; import android.content.Intent;
import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
public class BootupIntentService extends IntentService { public class BootupIntentService extends IntentService {
@ -17,14 +11,10 @@ public class BootupIntentService extends IntentService {
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleIntent(Intent intent) {
MagiskManager magiskManager = Utils.getMagiskManager(this); /* Currently no bootup task to do
magiskManager.initSuAccess(); MagiskManager magiskManager = Utils.getMagiskManager(this);
magiskManager.updateMagiskInfo(); magiskManager.initSuAccess();
if (magiskManager.prefs.getBoolean("magiskhide", false) && magiskManager.updateMagiskInfo();
!magiskManager.disabled && !magiskManager.magiskHideStarted && magiskManager.magiskVersionCode >= 130) { */
magiskManager.toast(R.string.start_magiskhide, Toast.LENGTH_LONG);
Shell.su(true, MagiskManager.MAGISK_HIDE_PATH + "enable",
"setprop persist.magisk.hide 1");
}
} }
} }

View File

@ -49,4 +49,16 @@
<item>@string/toast</item> <item>@string/toast</item>
</string-array> </string-array>
<string-array name="multiuser_mode">
<item>@string/settings_owner_only</item>
<item>@string/settings_owner_manage</item>
<item>@string/settings_user_independent</item>
</string-array>
<string-array name="multiuser_summary">
<item>@string/owner_only_summary</item>
<item>@string/owner_manage_summary</item>
<item>@string/user_indepenent_summary</item>
</string-array>
</resources> </resources>

View File

@ -201,4 +201,12 @@
<string name="target_uid">Target UID:\u0020</string> <string name="target_uid">Target UID:\u0020</string>
<string name="command">Command:\u0020</string> <string name="command">Command:\u0020</string>
<string name="multiuser_mode">Multiuser Mode</string>
<string name="settings_owner_only">Device Owner Only</string>
<string name="settings_owner_manage">Device Owner Managed</string>
<string name="settings_user_independent">User Independent</string>
<string name="owner_only_summary">Only owner has root access</string>
<string name="owner_manage_summary">Only owner can manage root access and receive request prompts</string>
<string name="user_indepenent_summary">Each user has its own separate root rules</string>
</resources> </resources>

View File

@ -31,13 +31,6 @@
android:title="@string/settings_core_only_title" android:title="@string/settings_core_only_title"
android:summary="@string/settings_core_only_summary" /> android:summary="@string/settings_core_only_summary" />
<!-- No more busybox -->
<!--<SwitchPreference-->
<!--android:key="busybox"-->
<!--android:defaultValue="false"-->
<!--android:title="@string/settings_busybox_title"-->
<!--android:summary="@string/settings_busybox_summary" />-->
<SwitchPreference <SwitchPreference
android:key="magiskhide" android:key="magiskhide"
android:defaultValue="false" android:defaultValue="false"
@ -62,6 +55,12 @@
android:entries="@array/su_access" android:entries="@array/su_access"
android:entryValues="@array/value_array" /> android:entryValues="@array/value_array" />
<ListPreference
android:key="multiuser_mode"
android:title="@string/multiuser_mode"
android:entries="@array/multiuser_mode"
android:entryValues="@array/value_array" />
<ListPreference <ListPreference
android:key="su_auto_response" android:key="su_auto_response"
android:title="@string/auto_response" android:title="@string/auto_response"