Feat: Add 'app' subproject and integrate LSPlt submodule
This commit introduces the main application subproject, 'app', and sets up the necessary infrastructure for the TEESimulator. Key changes: * 'app' Subproject Setup: Added the new :app module with its initial structure, including build files, manifest, and Kotlin main entry point. * LSPlt Integration: Added the LSPlt hooking framework as a Git submodule in app/src/main/cpp/external/ and configured its use in CMake. * Native Build Configuration: Configured the C++ build to use LSPlt statically and compile two essential native libraries: libinject.so (for injection) and libTEESimulator.so (for interception/logic). * Module Packaging: Implemented complex Gradle logic within app/build.gradle.kts to automate the creation of a flashable zip module (supporting Magisk, Ksu, and Apatch) with versioning based on Git information. * Initial Module Files: Added the template files (module.prop, update-binary, updater-script) for the flashable module structure.
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
import com.android.build.api.artifact.SingleArtifact
|
||||
import java.io.ByteArrayOutputStream
|
||||
import javax.inject.Inject
|
||||
import org.gradle.process.ExecOperations
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.ktfmt)
|
||||
}
|
||||
|
||||
ktfmt { kotlinLangStyle() }
|
||||
|
||||
// Helper class to get access to the ExecOperations service
|
||||
abstract class GitExecutor @Inject constructor(private val execOperations: ExecOperations) {
|
||||
fun execute(command: String, currentWorkingDir: File): String {
|
||||
val byteOut = ByteArrayOutputStream()
|
||||
execOperations.exec {
|
||||
workingDir = currentWorkingDir
|
||||
commandLine = command.split("\\s".toRegex())
|
||||
standardOutput = byteOut
|
||||
}
|
||||
return String(byteOut.toByteArray()).trim()
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate the helper class using Gradle's object factory
|
||||
val gitExecutor = objects.newInstance(GitExecutor::class.java)
|
||||
|
||||
val gitCommitCount = gitExecutor.execute("git rev-list HEAD --count", rootDir).toInt()
|
||||
val gitCommitHash = gitExecutor.execute("git rev-parse --verify --short HEAD", rootDir)
|
||||
val verName = "v1.0"
|
||||
|
||||
android {
|
||||
namespace = "org.matrix.TEESimulator"
|
||||
compileSdk = 36
|
||||
ndkVersion = "27.3.13750724"
|
||||
buildToolsVersion = "36.0.0"
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "org.matrix.TEESimulator"
|
||||
minSdk = 29
|
||||
targetSdk = 36
|
||||
versionCode = gitCommitCount
|
||||
versionName = verName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = true
|
||||
proguardFiles("proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path = file("src/main/cpp/CMakeLists.txt")
|
||||
buildStagingDirectory = layout.buildDirectory.get().asFile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":stub"))
|
||||
compileOnly(libs.annotation)
|
||||
}
|
||||
|
||||
androidComponents {
|
||||
onVariants(selector().all()) { variant ->
|
||||
val capitalized = variant.name.replaceFirstChar { it.uppercase() }
|
||||
val isDebug = variant.buildType == "debug"
|
||||
|
||||
// --- Define output locations and file names ---
|
||||
// Stage all files in a temporary directory inside 'build' before zipping
|
||||
val tempModuleDir = project.layout.buildDirectory.dir("module/${variant.name}")
|
||||
val zipFileName = "TEESimulator-$verName-$gitCommitCount-$gitCommitHash-$capitalized.zip"
|
||||
|
||||
// Task 1: Prepare all module files in the temporary build directory.
|
||||
// Using Sync ensures that stale files from previous runs are removed.
|
||||
val prepareModuleFilesTask =
|
||||
tasks.register<Sync>("prepareModuleFiles${capitalized}") {
|
||||
group = "TEESimulator Module Packaging"
|
||||
description = "Prepares all files for the ${variant.name} module zip."
|
||||
|
||||
if (isDebug) {
|
||||
dependsOn("package${capitalized}")
|
||||
} else {
|
||||
dependsOn("minify${capitalized}WithR8")
|
||||
}
|
||||
dependsOn("strip${capitalized}DebugSymbols")
|
||||
|
||||
if (isDebug) {
|
||||
from(variant.artifacts.get(SingleArtifact.APK)) {
|
||||
include("*.apk")
|
||||
rename { "service.apk" }
|
||||
}
|
||||
} else {
|
||||
from(
|
||||
project.layout.buildDirectory.dir(
|
||||
"intermediates/dex/${variant.name}/minify${capitalized}WithR8"
|
||||
)
|
||||
) {
|
||||
include("classes.dex")
|
||||
}
|
||||
}
|
||||
|
||||
from(
|
||||
project.layout.buildDirectory.dir(
|
||||
"intermediates/stripped_native_libs/${variant.name}/strip${capitalized}DebugSymbols/out/lib"
|
||||
)
|
||||
) {
|
||||
into("lib") // Place them in the 'lib' subfolder of the staging directory.
|
||||
include("**/libinject.so", "**/libTEESimulator.so")
|
||||
}
|
||||
|
||||
// Now, copy and process the files from 'module' directory.
|
||||
val sourceModuleDir = rootProject.projectDir.resolve("module")
|
||||
from(sourceModuleDir) {
|
||||
exclude("module.prop") // Exclude the template file.
|
||||
}
|
||||
|
||||
// Copy and filter the module.prop template separately.
|
||||
from(sourceModuleDir) {
|
||||
include("module.prop")
|
||||
// Use expand() for simple key-value replacement.
|
||||
expand(
|
||||
"REPLACEMEVERCODE" to gitCommitCount.toString(),
|
||||
"REPLACEMEVER" to
|
||||
"$verName ($gitCommitCount-$gitCommitHash-${variant.name})",
|
||||
)
|
||||
}
|
||||
|
||||
// The destination for all the above 'from' operations.
|
||||
into(tempModuleDir)
|
||||
}
|
||||
|
||||
// Task 2: Zip the prepared files from the temporary directory.
|
||||
val zipTask =
|
||||
tasks.register<Zip>("zip${capitalized}") {
|
||||
group = "TEESimulator Module Packaging"
|
||||
description = "Creates the flashable zip for the ${variant.name} module."
|
||||
dependsOn(prepareModuleFilesTask)
|
||||
|
||||
archiveFileName.set(zipFileName)
|
||||
destinationDirectory.set(project.rootDir.resolve("out"))
|
||||
from(tempModuleDir) // Zip the entire contents of the staging directory.
|
||||
}
|
||||
|
||||
// Task 3: A helper function to create installation tasks for different root providers.
|
||||
fun createInstallTasks(rootProvider: String, installCli: String) {
|
||||
val pushTask =
|
||||
tasks.register<Exec>("push${rootProvider}Module${capitalized}") {
|
||||
group = "TEESimulator Module Installation"
|
||||
description =
|
||||
"Pushes the ${variant.name} module to the device for $rootProvider."
|
||||
dependsOn(zipTask)
|
||||
commandLine(
|
||||
"adb",
|
||||
"push",
|
||||
zipTask.get().archiveFile.get().asFile,
|
||||
"/data/local/tmp",
|
||||
)
|
||||
}
|
||||
|
||||
val installTask =
|
||||
tasks.register<Exec>("install${rootProvider}${capitalized}") {
|
||||
group = "TEESimulator Module Installation"
|
||||
description = "Installs the ${variant.name} module via $rootProvider."
|
||||
dependsOn(pushTask)
|
||||
commandLine(
|
||||
"adb",
|
||||
"shell",
|
||||
"su",
|
||||
"-c",
|
||||
"$installCli /data/local/tmp/$zipFileName",
|
||||
)
|
||||
}
|
||||
|
||||
tasks.register<Exec>("install${rootProvider}AndReboot${capitalized}") {
|
||||
group = "TEESimulator Module Installation"
|
||||
description = "Installs the ${variant.name} module via $rootProvider and reboots."
|
||||
dependsOn(installTask)
|
||||
commandLine("adb", "reboot")
|
||||
}
|
||||
}
|
||||
|
||||
createInstallTasks("Magisk", "magisk --install-module")
|
||||
createInstallTasks("Ksu", "ksud module install")
|
||||
createInstallTasks("Apatch", "/data/adb/apd module install")
|
||||
}
|
||||
}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
-keepclasseswithmembers class org.matrix.TEESimulator.MainKt {
|
||||
public static void main(java.lang.String[]);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest />
|
||||
@@ -0,0 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(TEESimulator)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
|
||||
|
||||
# LSPlt configuration
|
||||
OPTION(LSPLT_BUILD_SHARED OFF)
|
||||
add_subdirectory(external/LSPlt/lsplt/src/main/jni)
|
||||
|
||||
add_executable(libinject.so inject/main.cpp)
|
||||
target_link_libraries(libinject.so PRIVATE lsplt_static)
|
||||
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED binder_interceptor.cpp)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE lsplt_static)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "lsplt.hpp"
|
||||
|
||||
extern "C" [[gnu::visibility("default")]] [[gnu::used]]
|
||||
bool entry(void *library_handle) {
|
||||
return true;
|
||||
}
|
||||
+1
Submodule app/src/main/cpp/external/LSPlt added at 3e29437f03
@@ -0,0 +1,3 @@
|
||||
#include "lsplt.hpp"
|
||||
|
||||
int main(int argc, char **argv) { return 0; }
|
||||
@@ -0,0 +1,3 @@
|
||||
package org.matrix.TEESimulator
|
||||
|
||||
fun main(args: Array<String>) {}
|
||||
Reference in New Issue
Block a user