Skip to content

Commit

Permalink
Open management UI trough a notification
Browse files Browse the repository at this point in the history
  • Loading branch information
RikkaW committed Jan 18, 2021
1 parent c830d43 commit 564ca2a
Show file tree
Hide file tree
Showing 21 changed files with 455 additions and 51 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ In conclusion, we can get a super user interface similar to standard Android API
## Guide for users

* Install the zip from Magisk manager
* Show Management UI: enter `*#*#784784#*#*` in the default dialer app
* Open Management UI:
- Trough a notification, this notification will show when you are in "Developer options"
- Enter `*#*#784784#*#*` in the default dialer app
* Play with apps that support Sui

## Guide for application developers
Expand Down
4 changes: 4 additions & 0 deletions module/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
public static void main(java.lang.String[], java.nio.ByteBuffer[]);
}

-keep class rikka.sui.settings.SettingsProcess {
public static void main(java.lang.String[], java.nio.ByteBuffer[]);
}

-keepnames class * implements android.os.Parcelable

-keepclassmembers class * implements android.os.Parcelable {
Expand Down
3 changes: 2 additions & 1 deletion module/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ add_library(${MODULE_NAME} SHARED
bridge_service.cpp
android.cpp
plt.c
manager_process.cpp)
manager_process.cpp
settings_process.cpp)
target_link_libraries(${MODULE_NAME} log riru::riru nativehelper::nativehelper_header_only)
set_target_properties(${MODULE_NAME} PROPERTIES LINK_FLAGS_RELEASE -s)

Expand Down
2 changes: 2 additions & 0 deletions module/src/main/cpp/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
#define ROOT_PATH "/data/adb/sui"
#define FALLBACK_DEX_DIR "/data/system/sui"
#define MANAGER_APPLICATION_ID "com.android.systemui"
#define SETTINGS_APPLICATION_ID "com.android.settings"

#define DEX_NAME "sui.dex"
#define DEX_PATH ROOT_PATH "/" DEX_NAME
#define RES_PATH ROOT_PATH "/res"
#define SYSTEM_PROCESS_CLASSNAME "rikka/sui/systemserver/SystemProcess"
#define MANAGER_PROCESS_CLASSNAME "rikka/sui/manager/ManagerProcess"
#define SETTINGS_PROCESS_CLASSNAME "rikka/sui/settings/SettingsProcess"
30 changes: 17 additions & 13 deletions module/src/main/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,21 @@
#include "system_server.h"
#include "config.h"
#include "manager_process.h"
#include "settings_process.h"

static DexFile *dexFile = nullptr;
static std::vector<File *> *files = nullptr;
static std::vector<File *> *resources_files = nullptr;

static void PrepareFiles() {
if (dexFile && dexFile->getBytes()) return;
dexFile = new DexFile(DEX_PATH);

files = new std::vector<File *>();
files->emplace_back(new File(RES_PATH "/layout/confirmation_dialog.xml"));
files->emplace_back(new File(RES_PATH "/layout/management_dialog.xml"));
files->emplace_back(new File(RES_PATH "/layout/management_app_item.xml"));
files->emplace_back(new File(RES_PATH "/drawable/ic_su_24.xml"));
files->emplace_back(new File(RES_PATH "/drawable/ic_close_24.xml"));
resources_files = new std::vector<File *>();
resources_files->emplace_back(new File(RES_PATH "/layout/confirmation_dialog.xml"));
resources_files->emplace_back(new File(RES_PATH "/layout/management_dialog.xml"));
resources_files->emplace_back(new File(RES_PATH "/layout/management_app_item.xml"));
resources_files->emplace_back(new File(RES_PATH "/drawable/ic_su_24.xml"));
resources_files->emplace_back(new File(RES_PATH "/drawable/ic_close_24.xml"));
}

static void DestroyFiles(JNIEnv *env) {
Expand All @@ -33,12 +34,12 @@ static void DestroyFiles(JNIEnv *env) {
delete dexFile;
dexFile = nullptr;
}
if (files) {
for (auto *file : *files) {
if (resources_files) {
for (auto *file : *resources_files) {
delete file;
}
delete files;
files = nullptr;
delete resources_files;
resources_files = nullptr;
}
}

Expand Down Expand Up @@ -84,8 +85,11 @@ static void appProcessPost(
JNIEnv *env, const char *from, const char *package_name, const char *app_data_dir, jint uid) {

if (strcmp(saved_package_name, MANAGER_APPLICATION_ID) == 0) {
LOGV("%s: uid=%d, package=%s, dir=%s", from, uid, package_name, app_data_dir);
Manager::main(env, app_data_dir, dexFile, files);
LOGV("%s: manager process, uid=%d, package=%s, dir=%s", from, uid, package_name, app_data_dir);
Manager::main(env, app_data_dir, dexFile, resources_files);
} else if (strcmp(saved_package_name, SETTINGS_APPLICATION_ID) == 0) {
LOGV("%s: settings process, uid=%d, package=%s, dir=%s", from, uid, package_name, app_data_dir);
Settings::main(env, app_data_dir, dexFile, resources_files);
} else {
DestroyFiles(env);
}
Expand Down
99 changes: 99 additions & 0 deletions module/src/main/cpp/settings_process.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include <cstdio>
#include <cstring>
#include <chrono>
#include <fcntl.h>
#include <unistd.h>
#include <sys/vfs.h>
#include <sys/stat.h>
#include <dirent.h>
#include <jni.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <mntent.h>
#include <sys/mount.h>
#include <sys/sendfile.h>
#include <dlfcn.h>
#include <cinttypes>
#include <vector>

#include "android.h"
#include "logging.h"
#include "riru.h"
#include "misc.h"
#include "dex_file.h"
#include "bridge_service.h"
#include "binder_hook.h"
#include "config.h"

namespace Settings {

static jclass mainClass = nullptr;

static bool installDex(JNIEnv *env, const char *appDataDir, DexFile *dexFile, std::vector<File *> *files) {
if (android::GetApiLevel() >= 26) {
dexFile->createInMemoryDexClassLoader(env);
} else {
char dexDir[PATH_MAX], oatDir[PATH_MAX];
snprintf(dexDir, PATH_MAX, "%s/sui", appDataDir);
snprintf(oatDir, PATH_MAX, "%s/sui/oat", appDataDir);
dexFile->createDexClassLoader(env, dexDir, DEX_NAME, oatDir);
}

mainClass = dexFile->findClass(env, SETTINGS_PROCESS_CLASSNAME);
if (!mainClass) {
LOGE("unable to find main class");
return false;
}
mainClass = (jclass) env->NewGlobalRef(mainClass);

auto mainMethod = env->GetStaticMethodID(mainClass, "main", "([Ljava/lang/String;[Ljava/nio/ByteBuffer;)V");
if (!mainMethod) {
LOGE("unable to find main method");
env->ExceptionDescribe();
env->ExceptionClear();
return false;
}

auto args = env->NewObjectArray(1, env->FindClass("java/lang/String"), nullptr);
char buf[64];
sprintf(buf, "--version-code=%d", RIRU_MODULE_VERSION);
env->SetObjectArrayElement(args, 0, env->NewStringUTF(buf));

auto buffers = env->NewObjectArray(files->size(), env->FindClass("java/nio/ByteBuffer"), nullptr);
for (auto i = 0; i < files->size(); ++i) {
auto file = files->at(i);
env->SetObjectArrayElement(buffers, i, env->NewDirectByteBuffer(file->getBytes(), file->getSize()));
}

env->CallStaticVoidMethod(mainClass, mainMethod, args, buffers);
if (env->ExceptionCheck()) {
LOGE("unable to call main method");
env->ExceptionDescribe();
env->ExceptionClear();
return false;
}

return true;
}

void main(JNIEnv *env, const char *appDataDir, DexFile *dexFile, std::vector<File *> *files) {
LOGD("dex size=%" PRIdPTR, dexFile->getSize());

if (!dexFile->getBytes()) {
LOGE("no dex");
return;
}

LOGV("main: manager");

LOGV("install dex");

if (!installDex(env, appDataDir, dexFile, files)) {
LOGE("can't install dex");
return;
}

LOGV("install dex finished");
}
}
8 changes: 8 additions & 0 deletions module/src/main/cpp/settings_process.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include <jni.h>
#include "dex_file.h"

namespace Settings {
void main(JNIEnv *env, const char *appDataDir, DexFile *dexFile, std::vector<File *> *files);
}
6 changes: 3 additions & 3 deletions module/src/main/java/rikka/sui/ktx/TextView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package rikka.sui.ktx

import android.view.View
import android.widget.TextView
import rikka.sui.manager.res.Res.string
import rikka.sui.manager.res.Strings
import rikka.sui.resource.Res
import rikka.sui.resource.Strings

private const val tag_countdown = 1599296841

Expand All @@ -17,7 +17,7 @@ fun TextView.applyCountdown(countdownSecond: Int, message: CharSequence? = null,
if (message != null) text = message
} else {
isEnabled = false
if (message != null && format != 0) text = String.format(Strings.get(string.brackets_format), message, countdown.toString())
if (message != null && format != 0) text = String.format(Strings.get(Res.string.brackets_format), message, countdown.toString())
postDelayed(this, 1000)
}
}
Expand Down
3 changes: 2 additions & 1 deletion module/src/main/java/rikka/sui/manager/ManagerProcess.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
import rikka.sui.ktx.HandlerKt;
import rikka.sui.manager.dialog.ConfirmationDialog;
import rikka.sui.manager.dialog.ManagementDialog;
import rikka.sui.manager.res.Xml;
import rikka.sui.resource.Xml;
import rikka.sui.server.ServerConstants;
import rikka.sui.util.BridgeServiceClient;

import static rikka.sui.manager.ManagerConstants.LOGGER;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
import rikka.sui.ktx.ResourcesKt;
import rikka.sui.ktx.TextViewKt;
import rikka.sui.ktx.WindowKt;
import rikka.sui.manager.BridgeServiceClient;
import rikka.sui.manager.res.Res;
import rikka.sui.manager.res.Strings;
import rikka.sui.manager.res.Utils;
import rikka.sui.manager.res.Xml;
import rikka.sui.util.BridgeServiceClient;
import rikka.sui.resource.Res;
import rikka.sui.resource.Strings;
import rikka.sui.resource.Utils;
import rikka.sui.resource.Xml;
import rikka.sui.util.UserHandleCompat;

import static rikka.shizuku.ShizukuApiConstants.REQUEST_PERMISSION_REPLY_ALLOWED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@
import rikka.sui.ktx.HandlerKt;
import rikka.sui.ktx.ResourcesKt;
import rikka.sui.ktx.WindowKt;
import rikka.sui.manager.BridgeServiceClient;
import rikka.sui.util.BridgeServiceClient;
import rikka.sui.manager.WorkerHandler;
import rikka.sui.manager.res.Res;
import rikka.sui.manager.res.Strings;
import rikka.sui.manager.res.Xml;
import rikka.sui.resource.Res;
import rikka.sui.resource.Strings;
import rikka.sui.resource.Xml;
import rikka.sui.model.AppInfo;
import rikka.sui.server.config.Config;
import rikka.sui.util.UserHandleCompat;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package rikka.sui.manager.res;
package rikka.sui.resource;

public final class Res {

Expand Down Expand Up @@ -30,6 +30,8 @@ public final static class string {
public static final int permission_denied = 10;
public static final int permission_hidden = 11;
public static final int permission_ask = 12;
public static final int COUNT = 13;
public static final int notification_channel_group_name = 13;
public static final int notification_show_management_text = 14;
public static final int COUNT = 15;
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
package rikka.sui.manager.res;
package rikka.sui.resource;

import java.util.HashMap;
import java.util.Locale;

import static rikka.sui.manager.res.Res.string.COUNT;
import static rikka.sui.manager.res.Res.string.brackets_format;
import static rikka.sui.manager.res.Res.string.close;
import static rikka.sui.manager.res.Res.string.grant_dialog_button_allow_always;
import static rikka.sui.manager.res.Res.string.grant_dialog_button_allow_one_time;
import static rikka.sui.manager.res.Res.string.grant_dialog_button_deny;
import static rikka.sui.manager.res.Res.string.grant_dialog_button_deny_and_dont_ask_again;
import static rikka.sui.manager.res.Res.string.management_title;
import static rikka.sui.manager.res.Res.string.permission_allowed;
import static rikka.sui.manager.res.Res.string.permission_ask;
import static rikka.sui.manager.res.Res.string.permission_denied;
import static rikka.sui.manager.res.Res.string.permission_description;
import static rikka.sui.manager.res.Res.string.permission_hidden;
import static rikka.sui.manager.res.Res.string.permission_warning_template;
import static rikka.sui.resource.Res.string.COUNT;
import static rikka.sui.resource.Res.string.brackets_format;
import static rikka.sui.resource.Res.string.close;
import static rikka.sui.resource.Res.string.grant_dialog_button_allow_always;
import static rikka.sui.resource.Res.string.grant_dialog_button_allow_one_time;
import static rikka.sui.resource.Res.string.grant_dialog_button_deny;
import static rikka.sui.resource.Res.string.grant_dialog_button_deny_and_dont_ask_again;
import static rikka.sui.resource.Res.string.management_title;
import static rikka.sui.resource.Res.string.notification_channel_group_name;
import static rikka.sui.resource.Res.string.notification_show_management_text;
import static rikka.sui.resource.Res.string.permission_allowed;
import static rikka.sui.resource.Res.string.permission_ask;
import static rikka.sui.resource.Res.string.permission_denied;
import static rikka.sui.resource.Res.string.permission_description;
import static rikka.sui.resource.Res.string.permission_hidden;
import static rikka.sui.resource.Res.string.permission_warning_template;

public class Strings {

Expand All @@ -41,6 +43,8 @@ public class Strings {
array[permission_denied] = "拒绝";
array[permission_hidden] = "隐藏";
array[permission_ask] = "询问";
array[notification_channel_group_name] = "显示管理界面";
array[notification_show_management_text] = "点按以显示超级用户管理界面";
Strings.STRINGS.put("zh-CN", array);

array = new String[COUNT];
Expand All @@ -57,6 +61,8 @@ public class Strings {
array[permission_denied] = "拒絕";
array[permission_hidden] = "隱藏";
array[permission_ask] = "詢問";
array[notification_channel_group_name] = "顯示管理介面";
array[notification_show_management_text] = "輕觸以顯示超級使用者管理介面";
Strings.STRINGS.put("zh", array);

array = new String[COUNT];
Expand All @@ -73,6 +79,8 @@ public class Strings {
array[permission_denied] = "Denied";
array[permission_hidden] = "Hidden";
array[permission_ask] = "Ask";
array[notification_channel_group_name] = "Show management";
array[notification_show_management_text] = "Tap to show superuser management";
Strings.STRINGS.put("en", array);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/


package rikka.sui.manager.res;
package rikka.sui.resource;

import android.text.Html;
import android.text.TextPaint;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package rikka.sui.manager.res;
package rikka.sui.resource;

import android.content.Context;
import android.content.pm.ApplicationInfo;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package rikka.sui.manager.res;
package rikka.sui.resource;

import android.annotation.SuppressLint;
import android.util.Log;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package rikka.sui.settings;

import rikka.sui.util.Logger;

public class SettingsConstants {

public static final Logger LOGGER = new Logger("SuiSettings");
}
Loading

0 comments on commit 564ca2a

Please sign in to comment.