Add LSPatch manager

This commit is contained in:
Nullptr 2021-09-06 14:14:55 +08:00 committed by LoveSy
parent 605383e8b9
commit 7876d84f65
33 changed files with 502 additions and 71 deletions

View File

@ -1,6 +1,7 @@
package org.lsposed.lspatch.loader; package org.lsposed.lspatch.loader;
import static android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE; import static android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE;
import static org.lsposed.lspd.service.ConfigFileManager.loadModule;
import android.app.ActivityThread; import android.app.ActivityThread;
import android.app.Application; import android.app.Application;
@ -15,10 +16,7 @@ import android.os.Environment;
import android.os.IBinder; import android.os.IBinder;
import android.os.Parcel; import android.os.Parcel;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.SharedMemory;
import android.system.ErrnoException;
import android.system.Os; import android.system.Os;
import android.system.OsConstants;
import android.util.Log; import android.util.Log;
import org.lsposed.lspatch.loader.util.FileUtils; import org.lsposed.lspatch.loader.util.FileUtils;
@ -27,19 +25,15 @@ import org.lsposed.lspatch.share.Constants;
import org.lsposed.lspd.config.ApplicationServiceClient; import org.lsposed.lspd.config.ApplicationServiceClient;
import org.lsposed.lspd.core.Main; import org.lsposed.lspd.core.Main;
import org.lsposed.lspd.models.Module; import org.lsposed.lspd.models.Module;
import org.lsposed.lspd.models.PreLoadedApk;
import org.lsposed.lspd.nativebridge.SigBypass; import org.lsposed.lspd.nativebridge.SigBypass;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.channels.Channels;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermissions; import java.nio.file.attribute.PosixFilePermissions;
@ -176,7 +170,8 @@ public class LSPApplication extends ApplicationServiceClient {
public static void loadModules(Context context) { public static void loadModules(Context context) {
if (useManager) { if (useManager) {
try { try {
LSPApplication.modules.addAll(managerResolver.getModules()); modules.addAll(managerResolver.getModules());
modules.forEach(m -> Log.i(TAG, "Load module " + m.packageName + " from manager"));
} catch (NullPointerException | RemoteException e) { } catch (NullPointerException | RemoteException e) {
Log.e(TAG, "Failed to get modules from manager", e); Log.e(TAG, "Failed to get modules from manager", e);
} }
@ -202,7 +197,8 @@ public class LSPApplication extends ApplicationServiceClient {
var module = new Module(); var module = new Module();
module.apkPath = cacheApkPath; module.apkPath = cacheApkPath;
module.packageName = packageName; module.packageName = packageName;
module.file = loadModule(context, cacheApkPath); module.file = loadModule(cacheApkPath);
if (module.file != null) module.file.hostApk = context.getApplicationInfo().sourceDir;
modules.add(module); modules.add(module);
} }
} catch (Throwable ignored) { } catch (Throwable ignored) {
@ -210,61 +206,6 @@ public class LSPApplication extends ApplicationServiceClient {
} }
} }
private static void readDexes(ZipFile apkFile, List<SharedMemory> preLoadedDexes) {
int secondary = 2;
for (var dexFile = apkFile.getEntry("classes.dex"); dexFile != null;
dexFile = apkFile.getEntry("classes" + secondary + ".dex"), secondary++) {
try (var in = apkFile.getInputStream(dexFile)) {
var memory = SharedMemory.create(null, in.available());
var byteBuffer = memory.mapReadWrite();
Channels.newChannel(in).read(byteBuffer);
SharedMemory.unmap(byteBuffer);
memory.setProtect(OsConstants.PROT_READ);
preLoadedDexes.add(memory);
} catch (IOException | ErrnoException e) {
Log.w(TAG, "Can not load " + dexFile + " in " + apkFile, e);
}
}
}
private static void readName(ZipFile apkFile, String initName, List<String> names) {
var initEntry = apkFile.getEntry(initName);
if (initEntry == null) return;
try (var in = apkFile.getInputStream(initEntry)) {
var reader = new BufferedReader(new InputStreamReader(in));
String name;
while ((name = reader.readLine()) != null) {
name = name.trim();
if (name.isEmpty() || name.startsWith("#")) continue;
names.add(name);
}
} catch (IOException e) {
Log.e(TAG, "Can not open " + initEntry, e);
}
}
private static PreLoadedApk loadModule(Context context, String path) {
var file = new PreLoadedApk();
var preLoadedDexes = new ArrayList<SharedMemory>();
var moduleClassNames = new ArrayList<String>(1);
var moduleLibraryNames = new ArrayList<String>(1);
try (var apkFile = new ZipFile(path)) {
readDexes(apkFile, preLoadedDexes);
readName(apkFile, "assets/xposed_init", moduleClassNames);
readName(apkFile, "assets/native_init", moduleLibraryNames);
} catch (IOException e) {
Log.e(TAG, "Can not open " + path, e);
return null;
}
if (preLoadedDexes.isEmpty()) return null;
if (moduleClassNames.isEmpty()) return null;
file.hostApk = context.getApplicationInfo().sourceDir;
file.preLoadedDexes = preLoadedDexes;
file.moduleClassNames = moduleClassNames;
file.moduleLibraryNames = moduleLibraryNames;
return file;
}
public LSPApplication() { public LSPApplication() {
super(); super();
} }

View File

@ -1,6 +1,7 @@
package org.lsposed.lspatch.loader; package org.lsposed.lspatch.loader;
import android.content.ContentResolver; import static org.lsposed.lspatch.share.Constants.MANAGER_PACKAGE_NAME;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@ -11,19 +12,19 @@ import org.lsposed.lspd.models.Module;
import java.util.List; import java.util.List;
public class ManagerResolver extends ContentResolver { public class ManagerResolver {
private static final String MANAGER_PACKAGE_NAME = "org.lsposed.lspatch"; private static final Uri PROVIDER = Uri.parse("content://" + MANAGER_PACKAGE_NAME + ".provider");
private static final Uri BINDER_URI = Uri.parse("content://" + MANAGER_PACKAGE_NAME + "/binder");
private final IManagerService service; private final IManagerService service;
public ManagerResolver(Context context) throws RemoteException { public ManagerResolver(Context context) throws RemoteException {
super(context);
try { try {
Bundle back = call(BINDER_URI, "getBinder", null, null); Bundle back = context.getContentResolver().call(PROVIDER, "getBinder", null, null);
service = IManagerService.Stub.asInterface(back.getBinder("binder")); service = IManagerService.Stub.asInterface(back.getBinder("binder"));
if (service == null) throw new RemoteException("Binder is null");
} catch (Throwable t) { } catch (Throwable t) {
var e = new RemoteException("Failed to get manager binder"); var e = new RemoteException("Failed to get manager binder");
e.setStackTrace(new StackTraceElement[0]);
e.addSuppressed(t); e.addSuppressed(t);
throw e; throw e;
} }

View File

@ -7,6 +7,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.1.0-alpha11' classpath 'com.android.tools.build:gradle:7.1.0-alpha11'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30'
} }
} }

2
core

@ -1 +1 @@
Subproject commit f955755ac40134f1b0a858f4e7df3b4a4eec78a8 Subproject commit 6b4c519cf1b0d1ada03c9f39e27c3a0971b47f9e

1
manager/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

46
manager/build.gradle Normal file
View File

@ -0,0 +1,46 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 31
defaultConfig {
applicationId "org.lsposed.lspatch"
minSdk 27
targetSdk 31
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation project(":imanager")
implementation project(path: ':lspcore')
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
}

21
manager/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.lsposed.lspatch">
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.LSPatch">
<activity
android:name=".ui.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name=".ModuleProvider"
android:authorities="org.lsposed.lspatch.provider"
android:enabled="true"
android:exported="true" />
</application>
</manifest>

View File

@ -0,0 +1,16 @@
package org.lsposed.lspatch
import android.app.Application
import android.content.Context
class LSPApplication : Application() {
companion object {
const val TAG = "LSPatch Manager"
lateinit var appContext: Context
}
override fun onCreate() {
super.onCreate()
appContext = applicationContext
}
}

View File

@ -0,0 +1,10 @@
package org.lsposed.lspatch
import org.lsposed.lspatch.manager.IManagerService
import org.lsposed.lspd.models.Module
class ManagerServiceImpl : IManagerService.Stub() {
override fun getModules(): List<Module> {
return ModuleProvider.allModules
}
}

View File

@ -0,0 +1,73 @@
package org.lsposed.lspatch
import android.content.ContentProvider
import android.content.ContentValues
import android.content.pm.PackageManager
import android.database.Cursor
import android.net.Uri
import android.os.Binder
import android.os.Bundle
import android.util.Log
import org.lsposed.lspatch.LSPApplication.Companion.TAG
import org.lsposed.lspd.models.Module
import org.lsposed.lspd.service.ConfigFileManager.loadModule
class ModuleProvider : ContentProvider() {
companion object {
lateinit var allModules: List<Module>
}
override fun onCreate(): Boolean {
return false
}
override fun call(method: String, arg: String?, extras: Bundle?): Bundle {
val app = context!!.packageManager.getNameForUid(Binder.getCallingUid())
Log.d(TAG, "$app calls binder")
when (method) {
"getBinder" -> {
loadAllModules()
return Bundle().apply {
putBinder("binder", ManagerServiceImpl())
}
}
else -> throw IllegalArgumentException("Invalid method name")
}
}
private fun loadAllModules() {
val list = mutableListOf<Module>()
for (pkg in context!!.packageManager.getInstalledPackages(PackageManager.GET_META_DATA)) {
val app = pkg.applicationInfo ?: continue
if (app.metaData != null && app.metaData.containsKey("xposedminversion")) {
Module().apply {
apkPath = app.publicSourceDir
packageName = app.packageName
file = loadModule(apkPath)
}.also { list.add(it) }
Log.d(TAG, "send module ${app.packageName}")
}
}
allModules = list
}
override fun query(p0: Uri, p1: Array<out String>?, p2: String?, p3: Array<out String>?, p4: String?): Cursor? {
return null
}
override fun getType(p0: Uri): String? {
return null
}
override fun insert(p0: Uri, p1: ContentValues?): Uri? {
return null
}
override fun delete(p0: Uri, p1: String?, p2: Array<out String>?): Int {
return 0
}
override fun update(p0: Uri, p1: ContentValues?, p2: String?, p3: Array<out String>?): Int {
return 0
}
}

View File

@ -0,0 +1,15 @@
package org.lsposed.lspatch.ui
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import org.lsposed.lspatch.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}

View File

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stub!"
android:textSize="50sp" />
</LinearLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.LSPatch" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

View File

@ -0,0 +1,3 @@
<resources>
<string name="app_name">LSPatch</string>
</resources>

View File

@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.LSPatch" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@ -16,3 +16,4 @@ include ':share'
include ':appstub' include ':appstub'
include ':apkzlib' include ':apkzlib'
include ':imanager' include ':imanager'
include ':manager'

View File

@ -1,6 +1,7 @@
package org.lsposed.lspatch.share; package org.lsposed.lspatch.share;
public class Constants { public class Constants {
final static public String MANAGER_PACKAGE_NAME = "org.lsposed.lspatch";
final static public String CONFIG_NAME_SIGBYPASSLV = "lspatch_sigbypasslv"; final static public String CONFIG_NAME_SIGBYPASSLV = "lspatch_sigbypasslv";
final static public int SIGBYPASS_LV_DISABLE = 0; final static public int SIGBYPASS_LV_DISABLE = 0;
final static public int SIGBYPASS_LV_PM = 1; final static public int SIGBYPASS_LV_PM = 1;