mirror of
https://github.com/ReVanced/revanced-library.git
synced 2026-01-11 13:56:17 +00:00
feat: Add local Android installer (#25)
This commit is contained in:
3
.github/workflows/build_pull_request.yml
vendored
3
.github/workflows/build_pull_request.yml
vendored
@@ -19,6 +19,9 @@ jobs:
|
|||||||
- name: Cache Gradle
|
- name: Cache Gradle
|
||||||
uses: burrunan/gradle-cache-action@v1
|
uses: burrunan/gradle-cache-action@v1
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
run: echo "JAVA_HOME=$JAVA_HOME_17_X64" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -23,6 +23,9 @@ jobs:
|
|||||||
- name: Cache Gradle
|
- name: Cache Gradle
|
||||||
uses: burrunan/gradle-cache-action@v1
|
uses: burrunan/gradle-cache-action@v1
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
run: echo "JAVA_HOME=$JAVA_HOME_17_X64" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
123
.gitignore
vendored
123
.gitignore
vendored
@@ -1,118 +1,11 @@
|
|||||||
### Java template
|
|
||||||
# Compiled class file
|
|
||||||
*.class
|
|
||||||
|
|
||||||
# Log file
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# BlueJ files
|
|
||||||
*.ctxt
|
|
||||||
|
|
||||||
# Mobile Tools for Java (J2ME)
|
|
||||||
.mtj.tmp/
|
|
||||||
|
|
||||||
# Package Files #
|
|
||||||
*.jar
|
|
||||||
*.war
|
|
||||||
*.nar
|
|
||||||
*.ear
|
|
||||||
*.zip
|
|
||||||
*.tar.gz
|
|
||||||
*.rar
|
|
||||||
|
|
||||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
|
||||||
hs_err_pid*
|
|
||||||
|
|
||||||
### JetBrains template
|
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
|
||||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
|
||||||
|
|
||||||
# User-specific stuff
|
|
||||||
.idea/**/workspace.xml
|
|
||||||
.idea/**/tasks.xml
|
|
||||||
.idea/**/usage.statistics.xml
|
|
||||||
.idea/**/dictionaries
|
|
||||||
.idea/**/shelf
|
|
||||||
|
|
||||||
# Generated files
|
|
||||||
.idea/**/contentModel.xml
|
|
||||||
|
|
||||||
# Sensitive or high-churn files
|
|
||||||
.idea/**/dataSources/
|
|
||||||
.idea/**/dataSources.ids
|
|
||||||
.idea/**/dataSources.local.xml
|
|
||||||
.idea/**/sqlDataSources.xml
|
|
||||||
.idea/**/dynamic.xml
|
|
||||||
.idea/**/uiDesigner.xml
|
|
||||||
.idea/**/dbnavigator.xml
|
|
||||||
|
|
||||||
# Gradle
|
|
||||||
.idea/**/gradle.xml
|
|
||||||
.idea/**/libraries
|
|
||||||
|
|
||||||
# Gradle and Maven with auto-import
|
|
||||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
|
||||||
# since they will be recreated, and may cause churn. Uncomment if using
|
|
||||||
# auto-import.
|
|
||||||
.idea/artifacts
|
|
||||||
.idea/compiler.xml
|
|
||||||
.idea/jarRepositories.xml
|
|
||||||
.idea/modules.xml
|
|
||||||
.idea/*.iml
|
|
||||||
.idea/modules
|
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
|
||||||
|
|
||||||
# CMake
|
|
||||||
cmake-build-*/
|
|
||||||
|
|
||||||
# Mongo Explorer plugin
|
|
||||||
.idea/**/mongoSettings.xml
|
|
||||||
|
|
||||||
# File-based project format
|
|
||||||
*.iws
|
|
||||||
|
|
||||||
# IntelliJ
|
|
||||||
out/
|
|
||||||
.idea
|
|
||||||
|
|
||||||
# mpeltonen/sbt-idea plugin
|
|
||||||
.idea_modules/
|
|
||||||
|
|
||||||
# JIRA plugin
|
|
||||||
atlassian-ide-plugin.xml
|
|
||||||
|
|
||||||
# Cursive Clojure plugin
|
|
||||||
.idea/replstate.xml
|
|
||||||
|
|
||||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
||||||
com_crashlytics_export_strings.xml
|
|
||||||
crashlytics.properties
|
|
||||||
crashlytics-build.properties
|
|
||||||
fabric.properties
|
|
||||||
|
|
||||||
# Editor-based Rest Client
|
|
||||||
.idea/httpRequests
|
|
||||||
|
|
||||||
# Android studio 3.1+ serialized cache file
|
|
||||||
.idea/caches/build_file_checksums.ser
|
|
||||||
|
|
||||||
### Gradle template
|
|
||||||
.gradle
|
.gradle
|
||||||
**/build/
|
.idea
|
||||||
!src/**/build/
|
.DS_Store
|
||||||
|
build
|
||||||
# Ignore Gradle GUI config
|
captures
|
||||||
gradle-app.setting
|
.externalNativeBuild
|
||||||
|
.cxx
|
||||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
local.properties
|
||||||
!gradle-wrapper.jar
|
xcuserdata
|
||||||
|
|
||||||
# Cache of project
|
|
||||||
.gradletasknamecache
|
|
||||||
|
|
||||||
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
|
||||||
# gradle/wrapper/gradle-wrapper.properties
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules/
|
node_modules/
|
||||||
337
api/android/revanced-library.api
Normal file
337
api/android/revanced-library.api
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
public final class app/revanced/library/ApkSigner {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/ApkSigner;
|
||||||
|
public final fun newApkSigner (Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)Lapp/revanced/library/ApkSigner$Signer;
|
||||||
|
public final fun newApkSigner (Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)Lapp/revanced/library/ApkSigner$Signer;
|
||||||
|
public final fun newApkSigner (Ljava/lang/String;Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$Signer;
|
||||||
|
public final fun newApkSigner (Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$Signer;
|
||||||
|
public final fun newKeyStore (Ljava/io/OutputStream;Ljava/lang/String;Ljava/util/Set;)V
|
||||||
|
public final fun newKeyStore (Ljava/util/Set;)Ljava/security/KeyStore;
|
||||||
|
public final fun newPrivateKeyCertificatePair (Ljava/lang/String;Ljava/util/Date;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
public final fun readKeyCertificatePair (Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
public final fun readKeyStore (Ljava/io/InputStream;Ljava/lang/String;)Ljava/security/KeyStore;
|
||||||
|
public final fun readPrivateKeyCertificatePair (Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkSigner$KeyStoreEntry {
|
||||||
|
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)V
|
||||||
|
public final fun getAlias ()Ljava/lang/String;
|
||||||
|
public final fun getPassword ()Ljava/lang/String;
|
||||||
|
public final fun getPrivateKeyCertificatePair ()Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkSigner$PrivateKeyCertificatePair {
|
||||||
|
public fun <init> (Ljava/security/PrivateKey;Ljava/security/cert/X509Certificate;)V
|
||||||
|
public final fun getCertificate ()Ljava/security/cert/X509Certificate;
|
||||||
|
public final fun getPrivateKey ()Ljava/security/PrivateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkSigner$Signer {
|
||||||
|
public final fun signApk (Lcom/android/tools/build/apkzlib/zip/ZFile;)V
|
||||||
|
public final fun signApk (Ljava/io/File;)V
|
||||||
|
public final fun signApk (Ljava/io/File;Ljava/io/File;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkUtils {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/ApkUtils;
|
||||||
|
public final fun applyTo (Lapp/revanced/patcher/PatcherResult;Ljava/io/File;)V
|
||||||
|
public final fun newPrivateKeyCertificatePair (Lapp/revanced/library/ApkUtils$PrivateKeyCertificatePairDetails;Lapp/revanced/library/ApkUtils$KeyStoreDetails;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
public final fun readPrivateKeyCertificatePairFromKeyStore (Lapp/revanced/library/ApkUtils$KeyStoreDetails;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
public final fun sign (Ljava/io/File;Lapp/revanced/library/ApkUtils$SigningOptions;)V
|
||||||
|
public final fun sign (Ljava/io/File;Ljava/io/File;Lapp/revanced/library/ApkUtils$SigningOptions;)V
|
||||||
|
public final fun sign (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)V
|
||||||
|
public final fun signApk (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkUtils$KeyStoreDetails;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkUtils$KeyStoreDetails {
|
||||||
|
public fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getAlias ()Ljava/lang/String;
|
||||||
|
public final fun getKeyStore ()Ljava/io/File;
|
||||||
|
public final fun getKeyStorePassword ()Ljava/lang/String;
|
||||||
|
public final fun getPassword ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkUtils$PrivateKeyCertificatePairDetails {
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun <init> (Ljava/lang/String;Ljava/util/Date;)V
|
||||||
|
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Date;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getCommonName ()Ljava/lang/String;
|
||||||
|
public final fun getValidUntil ()Ljava/util/Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkUtils$SigningOptions {
|
||||||
|
public fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getAlias ()Ljava/lang/String;
|
||||||
|
public final fun getKeyStore ()Ljava/io/File;
|
||||||
|
public final fun getKeyStorePassword ()Ljava/lang/String;
|
||||||
|
public final fun getPassword ()Ljava/lang/String;
|
||||||
|
public final fun getSigner ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/Options {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/Options;
|
||||||
|
public final fun deserialize (Ljava/lang/String;)[Lapp/revanced/library/Options$Patch;
|
||||||
|
public final fun serialize (Ljava/util/Set;Z)Ljava/lang/String;
|
||||||
|
public static synthetic fun serialize$default (Lapp/revanced/library/Options;Ljava/util/Set;ZILjava/lang/Object;)Ljava/lang/String;
|
||||||
|
public final fun setOptions (Ljava/util/Set;Ljava/io/File;)V
|
||||||
|
public final fun setOptions (Ljava/util/Set;Ljava/lang/String;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/Options$Patch {
|
||||||
|
public final fun getOptions ()Ljava/util/List;
|
||||||
|
public final fun getPatchName ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/Options$Patch$Option {
|
||||||
|
public final fun getKey ()Ljava/lang/String;
|
||||||
|
public final fun getValue ()Ljava/lang/Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/PatchUtils;
|
||||||
|
public final fun getMostCommonCompatibleVersions (Ljava/util/Set;Ljava/util/Set;Z)Ljava/util/Map;
|
||||||
|
public static synthetic fun getMostCommonCompatibleVersions$default (Lapp/revanced/library/PatchUtils;Ljava/util/Set;Ljava/util/Set;ZILjava/lang/Object;)Ljava/util/Map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/PatchUtils$Json;
|
||||||
|
public final fun deserialize (Ljava/io/InputStream;Ljava/lang/Class;)Ljava/util/Set;
|
||||||
|
public final fun serialize (Ljava/util/Set;Lkotlin/jvm/functions/Function1;ZLjava/io/OutputStream;)V
|
||||||
|
public static synthetic fun serialize$default (Lapp/revanced/library/PatchUtils$Json;Ljava/util/Set;Lkotlin/jvm/functions/Function1;ZLjava/io/OutputStream;ILjava/lang/Object;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json$FullJsonPatch : app/revanced/library/PatchUtils$Json$JsonPatch {
|
||||||
|
public static final field Companion Lapp/revanced/library/PatchUtils$Json$FullJsonPatch$Companion;
|
||||||
|
public final fun getCompatiblePackages ()Ljava/util/Set;
|
||||||
|
public final fun getDependencies ()Ljava/util/Set;
|
||||||
|
public final fun getDescription ()Ljava/lang/String;
|
||||||
|
public final fun getName ()Ljava/lang/String;
|
||||||
|
public final fun getOptions ()Ljava/util/Map;
|
||||||
|
public final fun getRequiresIntegrations ()Z
|
||||||
|
public final fun getUse ()Z
|
||||||
|
public final fun setRequiresIntegrations (Z)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json$FullJsonPatch$Companion {
|
||||||
|
public final fun fromPatch (Lapp/revanced/patcher/patch/Patch;)Lapp/revanced/library/PatchUtils$Json$FullJsonPatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json$FullJsonPatch$FullJsonPatchOption {
|
||||||
|
public static final field Companion Lapp/revanced/library/PatchUtils$Json$FullJsonPatch$FullJsonPatchOption$Companion;
|
||||||
|
public final fun getDefault ()Ljava/lang/Object;
|
||||||
|
public final fun getDescription ()Ljava/lang/String;
|
||||||
|
public final fun getKey ()Ljava/lang/String;
|
||||||
|
public final fun getRequired ()Z
|
||||||
|
public final fun getTitle ()Ljava/lang/String;
|
||||||
|
public final fun getValueType ()Ljava/lang/String;
|
||||||
|
public final fun getValues ()Ljava/util/Map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json$FullJsonPatch$FullJsonPatchOption$Companion {
|
||||||
|
public final fun fromPatchOption (Lapp/revanced/patcher/patch/options/PatchOption;)Lapp/revanced/library/PatchUtils$Json$FullJsonPatch$FullJsonPatchOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class app/revanced/library/PatchUtils$Json$JsonPatch {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/Utils {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/Utils;
|
||||||
|
public final fun isAndroidEnvironment ()Z
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class app/revanced/library/adb/AdbManager {
|
||||||
|
public static final field Companion Lapp/revanced/library/adb/AdbManager$Companion;
|
||||||
|
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
protected abstract fun getInstaller ()Lapp/revanced/library/installation/installer/Installer;
|
||||||
|
public fun install (Lapp/revanced/library/adb/AdbManager$Apk;)Lkotlin/jvm/functions/Function1;
|
||||||
|
public fun uninstall (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$Apk {
|
||||||
|
public fun <init> (Ljava/io/File;Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/io/File;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getFile ()Ljava/io/File;
|
||||||
|
public final fun getPackageName ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$Companion {
|
||||||
|
public final fun getAdbManager (Ljava/lang/String;Z)Lapp/revanced/library/adb/AdbManager;
|
||||||
|
public static synthetic fun getAdbManager$default (Lapp/revanced/library/adb/AdbManager$Companion;Ljava/lang/String;ZILjava/lang/Object;)Lapp/revanced/library/adb/AdbManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$DeviceNotFoundException : java/lang/Exception {
|
||||||
|
public fun <init> ()V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$FailedToFindInstalledPackageException : java/lang/Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$PackageNameRequiredException : java/lang/Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$RootAdbManager : app/revanced/library/adb/AdbManager {
|
||||||
|
public static final field Utils Lapp/revanced/library/adb/AdbManager$RootAdbManager$Utils;
|
||||||
|
public synthetic fun getInstaller ()Lapp/revanced/library/installation/installer/Installer;
|
||||||
|
public fun install (Lapp/revanced/library/adb/AdbManager$Apk;)Lkotlin/jvm/functions/Function1;
|
||||||
|
public fun uninstall (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$RootAdbManager$Utils {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$UserAdbManager : app/revanced/library/adb/AdbManager {
|
||||||
|
public synthetic fun getInstaller ()Lapp/revanced/library/installation/installer/Installer;
|
||||||
|
public fun install (Lapp/revanced/library/adb/AdbManager$Apk;)Lkotlin/jvm/functions/Function1;
|
||||||
|
public fun uninstall (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/command/AdbShellCommandRunner : app/revanced/library/installation/command/ShellCommandRunner {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class app/revanced/library/installation/command/ILocalShellCommandRunnerRootService : android/os/IInterface {
|
||||||
|
public static final field DESCRIPTOR Ljava/lang/String;
|
||||||
|
public abstract fun getFileSystemService ()Landroid/os/IBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class app/revanced/library/installation/command/ILocalShellCommandRunnerRootService$Default : app/revanced/library/installation/command/ILocalShellCommandRunnerRootService {
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun asBinder ()Landroid/os/IBinder;
|
||||||
|
public fun getFileSystemService ()Landroid/os/IBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class app/revanced/library/installation/command/ILocalShellCommandRunnerRootService$Stub : android/os/Binder, app/revanced/library/installation/command/ILocalShellCommandRunnerRootService {
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun asBinder ()Landroid/os/IBinder;
|
||||||
|
public static fun asInterface (Landroid/os/IBinder;)Lapp/revanced/library/installation/command/ILocalShellCommandRunnerRootService;
|
||||||
|
public fun onTransact (ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/command/LocalShellCommandRunner : app/revanced/library/installation/command/ShellCommandRunner, android/content/ServiceConnection, java/io/Closeable {
|
||||||
|
public fun close ()V
|
||||||
|
public fun onServiceConnected (Landroid/content/ComponentName;Landroid/os/IBinder;)V
|
||||||
|
public fun onServiceDisconnected (Landroid/content/ComponentName;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class app/revanced/library/installation/command/RunResult {
|
||||||
|
public abstract fun getError ()Ljava/lang/String;
|
||||||
|
public abstract fun getExitCode ()I
|
||||||
|
public abstract fun getOutput ()Ljava/lang/String;
|
||||||
|
public abstract fun waitFor ()V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/command/RunResult$DefaultImpls {
|
||||||
|
public static fun waitFor (Lapp/revanced/library/installation/command/RunResult;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class app/revanced/library/installation/command/ShellCommandRunner {
|
||||||
|
protected final fun getLogger ()Ljava/util/logging/Logger;
|
||||||
|
protected abstract fun runCommand (Ljava/lang/String;)Lapp/revanced/library/installation/command/RunResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/AdbInstaller : app/revanced/library/installation/installer/Installer {
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun <init> (Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public fun getInstallation (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
public fun install (Lapp/revanced/library/installation/installer/Installer$Apk;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
public fun uninstall (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class app/revanced/library/installation/installer/AdbInstallerResult {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/AdbInstallerResult$Failure : app/revanced/library/installation/installer/AdbInstallerResult {
|
||||||
|
public final fun getException ()Ljava/lang/Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/AdbInstallerResult$Success : app/revanced/library/installation/installer/AdbInstallerResult {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/installation/installer/AdbInstallerResult$Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/AdbRootInstaller : app/revanced/library/installation/installer/RootInstaller {
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun <init> (Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public class app/revanced/library/installation/installer/Installation {
|
||||||
|
public final fun getApkFilePath ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class app/revanced/library/installation/installer/Installer {
|
||||||
|
public abstract fun getInstallation (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
protected final fun getLogger ()Ljava/util/logging/Logger;
|
||||||
|
public abstract fun install (Lapp/revanced/library/installation/installer/Installer$Apk;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
public abstract fun uninstall (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/Installer$Apk {
|
||||||
|
public fun <init> (Ljava/io/File;Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/io/File;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getFile ()Ljava/io/File;
|
||||||
|
public final fun getPackageName ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/LocalInstaller : app/revanced/library/installation/installer/Installer, java/io/Closeable {
|
||||||
|
public static final field Companion Lapp/revanced/library/installation/installer/LocalInstaller$Companion;
|
||||||
|
public fun <init> (Landroid/content/Context;Lkotlin/jvm/functions/Function1;)V
|
||||||
|
public fun close ()V
|
||||||
|
public fun getInstallation (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
public fun install (Lapp/revanced/library/installation/installer/Installer$Apk;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
public fun uninstall (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/LocalInstaller$Companion {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/LocalInstallerResult {
|
||||||
|
public final fun getExtra ()Ljava/lang/String;
|
||||||
|
public final fun getPackageName ()Ljava/lang/String;
|
||||||
|
public final fun getPmStatus ()I
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/LocalInstallerService : android/app/Service {
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun onBind (Landroid/content/Intent;)Landroid/os/IBinder;
|
||||||
|
public fun onStartCommand (Landroid/content/Intent;II)I
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/LocalRootInstaller : app/revanced/library/installation/installer/RootInstaller, java/io/Closeable {
|
||||||
|
public fun <init> (Landroid/content/Context;Lkotlin/jvm/functions/Function1;)V
|
||||||
|
public synthetic fun <init> (Landroid/content/Context;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public fun close ()V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/RootInstallation : app/revanced/library/installation/installer/Installation {
|
||||||
|
public final fun getInstalledApkFilePath ()Ljava/lang/String;
|
||||||
|
public final fun getMounted ()Z
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class app/revanced/library/installation/installer/RootInstaller : app/revanced/library/installation/installer/Installer {
|
||||||
|
public fun getInstallation (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
protected final fun getShellCommandRunner ()Lapp/revanced/library/installation/command/ShellCommandRunner;
|
||||||
|
public fun install (Lapp/revanced/library/installation/installer/Installer$Apk;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
protected final fun invoke (Ljava/lang/String;)Lapp/revanced/library/installation/command/RunResult;
|
||||||
|
protected final fun move (Ljava/io/File;Ljava/lang/String;)V
|
||||||
|
public fun uninstall (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
protected final fun write (Ljava/lang/String;Ljava/lang/String;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/RootInstallerResult : java/lang/Enum {
|
||||||
|
public static final field FAILURE Lapp/revanced/library/installation/installer/RootInstallerResult;
|
||||||
|
public static final field SUCCESS Lapp/revanced/library/installation/installer/RootInstallerResult;
|
||||||
|
public static fun getEntries ()Lkotlin/enums/EnumEntries;
|
||||||
|
public static fun valueOf (Ljava/lang/String;)Lapp/revanced/library/installation/installer/RootInstallerResult;
|
||||||
|
public static fun values ()[Lapp/revanced/library/installation/installer/RootInstallerResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/logging/Logger {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/logging/Logger;
|
||||||
|
public final fun addHandler (Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V
|
||||||
|
public final fun removeAllHandlers ()V
|
||||||
|
public final fun setDefault ()V
|
||||||
|
public final fun setFormat (Ljava/lang/String;)V
|
||||||
|
public static synthetic fun setFormat$default (Lapp/revanced/library/logging/Logger;Ljava/lang/String;ILjava/lang/Object;)V
|
||||||
|
}
|
||||||
|
|
||||||
283
api/jvm/revanced-library.api
Normal file
283
api/jvm/revanced-library.api
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
public final class app/revanced/library/ApkSigner {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/ApkSigner;
|
||||||
|
public final fun newApkSigner (Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)Lapp/revanced/library/ApkSigner$Signer;
|
||||||
|
public final fun newApkSigner (Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)Lapp/revanced/library/ApkSigner$Signer;
|
||||||
|
public final fun newApkSigner (Ljava/lang/String;Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$Signer;
|
||||||
|
public final fun newApkSigner (Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$Signer;
|
||||||
|
public final fun newKeyStore (Ljava/io/OutputStream;Ljava/lang/String;Ljava/util/Set;)V
|
||||||
|
public final fun newKeyStore (Ljava/util/Set;)Ljava/security/KeyStore;
|
||||||
|
public final fun newPrivateKeyCertificatePair (Ljava/lang/String;Ljava/util/Date;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
public final fun readKeyCertificatePair (Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
public final fun readKeyStore (Ljava/io/InputStream;Ljava/lang/String;)Ljava/security/KeyStore;
|
||||||
|
public final fun readPrivateKeyCertificatePair (Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkSigner$KeyStoreEntry {
|
||||||
|
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)V
|
||||||
|
public final fun getAlias ()Ljava/lang/String;
|
||||||
|
public final fun getPassword ()Ljava/lang/String;
|
||||||
|
public final fun getPrivateKeyCertificatePair ()Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkSigner$PrivateKeyCertificatePair {
|
||||||
|
public fun <init> (Ljava/security/PrivateKey;Ljava/security/cert/X509Certificate;)V
|
||||||
|
public final fun getCertificate ()Ljava/security/cert/X509Certificate;
|
||||||
|
public final fun getPrivateKey ()Ljava/security/PrivateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkSigner$Signer {
|
||||||
|
public final fun signApk (Lcom/android/tools/build/apkzlib/zip/ZFile;)V
|
||||||
|
public final fun signApk (Ljava/io/File;)V
|
||||||
|
public final fun signApk (Ljava/io/File;Ljava/io/File;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkUtils {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/ApkUtils;
|
||||||
|
public final fun applyTo (Lapp/revanced/patcher/PatcherResult;Ljava/io/File;)V
|
||||||
|
public final fun newPrivateKeyCertificatePair (Lapp/revanced/library/ApkUtils$PrivateKeyCertificatePairDetails;Lapp/revanced/library/ApkUtils$KeyStoreDetails;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
public final fun readPrivateKeyCertificatePairFromKeyStore (Lapp/revanced/library/ApkUtils$KeyStoreDetails;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||||
|
public final fun sign (Ljava/io/File;Lapp/revanced/library/ApkUtils$SigningOptions;)V
|
||||||
|
public final fun sign (Ljava/io/File;Ljava/io/File;Lapp/revanced/library/ApkUtils$SigningOptions;)V
|
||||||
|
public final fun sign (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)V
|
||||||
|
public final fun signApk (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkUtils$KeyStoreDetails;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkUtils$KeyStoreDetails {
|
||||||
|
public fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getAlias ()Ljava/lang/String;
|
||||||
|
public final fun getKeyStore ()Ljava/io/File;
|
||||||
|
public final fun getKeyStorePassword ()Ljava/lang/String;
|
||||||
|
public final fun getPassword ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkUtils$PrivateKeyCertificatePairDetails {
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun <init> (Ljava/lang/String;Ljava/util/Date;)V
|
||||||
|
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Date;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getCommonName ()Ljava/lang/String;
|
||||||
|
public final fun getValidUntil ()Ljava/util/Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/ApkUtils$SigningOptions {
|
||||||
|
public fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getAlias ()Ljava/lang/String;
|
||||||
|
public final fun getKeyStore ()Ljava/io/File;
|
||||||
|
public final fun getKeyStorePassword ()Ljava/lang/String;
|
||||||
|
public final fun getPassword ()Ljava/lang/String;
|
||||||
|
public final fun getSigner ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/Options {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/Options;
|
||||||
|
public final fun deserialize (Ljava/lang/String;)[Lapp/revanced/library/Options$Patch;
|
||||||
|
public final fun serialize (Ljava/util/Set;Z)Ljava/lang/String;
|
||||||
|
public static synthetic fun serialize$default (Lapp/revanced/library/Options;Ljava/util/Set;ZILjava/lang/Object;)Ljava/lang/String;
|
||||||
|
public final fun setOptions (Ljava/util/Set;Ljava/io/File;)V
|
||||||
|
public final fun setOptions (Ljava/util/Set;Ljava/lang/String;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/Options$Patch {
|
||||||
|
public final fun getOptions ()Ljava/util/List;
|
||||||
|
public final fun getPatchName ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/Options$Patch$Option {
|
||||||
|
public final fun getKey ()Ljava/lang/String;
|
||||||
|
public final fun getValue ()Ljava/lang/Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/PatchUtils;
|
||||||
|
public final fun getMostCommonCompatibleVersions (Ljava/util/Set;Ljava/util/Set;Z)Ljava/util/Map;
|
||||||
|
public static synthetic fun getMostCommonCompatibleVersions$default (Lapp/revanced/library/PatchUtils;Ljava/util/Set;Ljava/util/Set;ZILjava/lang/Object;)Ljava/util/Map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/PatchUtils$Json;
|
||||||
|
public final fun deserialize (Ljava/io/InputStream;Ljava/lang/Class;)Ljava/util/Set;
|
||||||
|
public final fun serialize (Ljava/util/Set;Lkotlin/jvm/functions/Function1;ZLjava/io/OutputStream;)V
|
||||||
|
public static synthetic fun serialize$default (Lapp/revanced/library/PatchUtils$Json;Ljava/util/Set;Lkotlin/jvm/functions/Function1;ZLjava/io/OutputStream;ILjava/lang/Object;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json$FullJsonPatch : app/revanced/library/PatchUtils$Json$JsonPatch {
|
||||||
|
public static final field Companion Lapp/revanced/library/PatchUtils$Json$FullJsonPatch$Companion;
|
||||||
|
public final fun getCompatiblePackages ()Ljava/util/Set;
|
||||||
|
public final fun getDependencies ()Ljava/util/Set;
|
||||||
|
public final fun getDescription ()Ljava/lang/String;
|
||||||
|
public final fun getName ()Ljava/lang/String;
|
||||||
|
public final fun getOptions ()Ljava/util/Map;
|
||||||
|
public final fun getRequiresIntegrations ()Z
|
||||||
|
public final fun getUse ()Z
|
||||||
|
public final fun setRequiresIntegrations (Z)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json$FullJsonPatch$Companion {
|
||||||
|
public final fun fromPatch (Lapp/revanced/patcher/patch/Patch;)Lapp/revanced/library/PatchUtils$Json$FullJsonPatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json$FullJsonPatch$FullJsonPatchOption {
|
||||||
|
public static final field Companion Lapp/revanced/library/PatchUtils$Json$FullJsonPatch$FullJsonPatchOption$Companion;
|
||||||
|
public final fun getDefault ()Ljava/lang/Object;
|
||||||
|
public final fun getDescription ()Ljava/lang/String;
|
||||||
|
public final fun getKey ()Ljava/lang/String;
|
||||||
|
public final fun getRequired ()Z
|
||||||
|
public final fun getTitle ()Ljava/lang/String;
|
||||||
|
public final fun getValueType ()Ljava/lang/String;
|
||||||
|
public final fun getValues ()Ljava/util/Map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/PatchUtils$Json$FullJsonPatch$FullJsonPatchOption$Companion {
|
||||||
|
public final fun fromPatchOption (Lapp/revanced/patcher/patch/options/PatchOption;)Lapp/revanced/library/PatchUtils$Json$FullJsonPatch$FullJsonPatchOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class app/revanced/library/PatchUtils$Json$JsonPatch {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/Utils {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/Utils;
|
||||||
|
public final fun isAndroidEnvironment ()Z
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class app/revanced/library/adb/AdbManager {
|
||||||
|
public static final field Companion Lapp/revanced/library/adb/AdbManager$Companion;
|
||||||
|
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
protected abstract fun getInstaller ()Lapp/revanced/library/installation/installer/Installer;
|
||||||
|
public fun install (Lapp/revanced/library/adb/AdbManager$Apk;)Lkotlin/jvm/functions/Function1;
|
||||||
|
public fun uninstall (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$Apk {
|
||||||
|
public fun <init> (Ljava/io/File;Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/io/File;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getFile ()Ljava/io/File;
|
||||||
|
public final fun getPackageName ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$Companion {
|
||||||
|
public final fun getAdbManager (Ljava/lang/String;Z)Lapp/revanced/library/adb/AdbManager;
|
||||||
|
public static synthetic fun getAdbManager$default (Lapp/revanced/library/adb/AdbManager$Companion;Ljava/lang/String;ZILjava/lang/Object;)Lapp/revanced/library/adb/AdbManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$DeviceNotFoundException : java/lang/Exception {
|
||||||
|
public fun <init> ()V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$FailedToFindInstalledPackageException : java/lang/Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$PackageNameRequiredException : java/lang/Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$RootAdbManager : app/revanced/library/adb/AdbManager {
|
||||||
|
public static final field Utils Lapp/revanced/library/adb/AdbManager$RootAdbManager$Utils;
|
||||||
|
public synthetic fun getInstaller ()Lapp/revanced/library/installation/installer/Installer;
|
||||||
|
public fun install (Lapp/revanced/library/adb/AdbManager$Apk;)Lkotlin/jvm/functions/Function1;
|
||||||
|
public fun uninstall (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$RootAdbManager$Utils {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/adb/AdbManager$UserAdbManager : app/revanced/library/adb/AdbManager {
|
||||||
|
public synthetic fun getInstaller ()Lapp/revanced/library/installation/installer/Installer;
|
||||||
|
public fun install (Lapp/revanced/library/adb/AdbManager$Apk;)Lkotlin/jvm/functions/Function1;
|
||||||
|
public fun uninstall (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/command/AdbShellCommandRunner : app/revanced/library/installation/command/ShellCommandRunner {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class app/revanced/library/installation/command/RunResult {
|
||||||
|
public abstract fun getError ()Ljava/lang/String;
|
||||||
|
public abstract fun getExitCode ()I
|
||||||
|
public abstract fun getOutput ()Ljava/lang/String;
|
||||||
|
public abstract fun waitFor ()V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/command/RunResult$DefaultImpls {
|
||||||
|
public static fun waitFor (Lapp/revanced/library/installation/command/RunResult;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class app/revanced/library/installation/command/ShellCommandRunner {
|
||||||
|
protected final fun getLogger ()Ljava/util/logging/Logger;
|
||||||
|
protected abstract fun runCommand (Ljava/lang/String;)Lapp/revanced/library/installation/command/RunResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/AdbInstaller : app/revanced/library/installation/installer/Installer {
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun <init> (Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public fun getInstallation (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
public fun install (Lapp/revanced/library/installation/installer/Installer$Apk;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
public fun uninstall (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class app/revanced/library/installation/installer/AdbInstallerResult {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/AdbInstallerResult$Failure : app/revanced/library/installation/installer/AdbInstallerResult {
|
||||||
|
public final fun getException ()Ljava/lang/Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/AdbInstallerResult$Success : app/revanced/library/installation/installer/AdbInstallerResult {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/installation/installer/AdbInstallerResult$Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/AdbRootInstaller : app/revanced/library/installation/installer/RootInstaller {
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun <init> (Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public class app/revanced/library/installation/installer/Installation {
|
||||||
|
public final fun getApkFilePath ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class app/revanced/library/installation/installer/Installer {
|
||||||
|
public abstract fun getInstallation (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
protected final fun getLogger ()Ljava/util/logging/Logger;
|
||||||
|
public abstract fun install (Lapp/revanced/library/installation/installer/Installer$Apk;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
public abstract fun uninstall (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/Installer$Apk {
|
||||||
|
public fun <init> (Ljava/io/File;Ljava/lang/String;)V
|
||||||
|
public synthetic fun <init> (Ljava/io/File;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
public final fun getFile ()Ljava/io/File;
|
||||||
|
public final fun getPackageName ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/RootInstallation : app/revanced/library/installation/installer/Installation {
|
||||||
|
public final fun getInstalledApkFilePath ()Ljava/lang/String;
|
||||||
|
public final fun getMounted ()Z
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class app/revanced/library/installation/installer/RootInstaller : app/revanced/library/installation/installer/Installer {
|
||||||
|
public fun getInstallation (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
protected final fun getShellCommandRunner ()Lapp/revanced/library/installation/command/ShellCommandRunner;
|
||||||
|
public fun install (Lapp/revanced/library/installation/installer/Installer$Apk;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
protected final fun invoke (Ljava/lang/String;)Lapp/revanced/library/installation/command/RunResult;
|
||||||
|
protected final fun move (Ljava/io/File;Ljava/lang/String;)V
|
||||||
|
public fun uninstall (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
protected final fun write (Ljava/lang/String;Ljava/lang/String;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/installation/installer/RootInstallerResult : java/lang/Enum {
|
||||||
|
public static final field FAILURE Lapp/revanced/library/installation/installer/RootInstallerResult;
|
||||||
|
public static final field SUCCESS Lapp/revanced/library/installation/installer/RootInstallerResult;
|
||||||
|
public static fun getEntries ()Lkotlin/enums/EnumEntries;
|
||||||
|
public static fun valueOf (Ljava/lang/String;)Lapp/revanced/library/installation/installer/RootInstallerResult;
|
||||||
|
public static fun values ()[Lapp/revanced/library/installation/installer/RootInstallerResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/library/logging/Logger {
|
||||||
|
public static final field INSTANCE Lapp/revanced/library/logging/Logger;
|
||||||
|
public final fun addHandler (Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V
|
||||||
|
public final fun removeAllHandlers ()V
|
||||||
|
public final fun setDefault ()V
|
||||||
|
public final fun setFormat (Ljava/lang/String;)V
|
||||||
|
public static synthetic fun setFormat$default (Lapp/revanced/library/logging/Logger;Ljava/lang/String;ILjava/lang/Object;)V
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.kotlin)
|
alias(libs.plugins.kotlin.multiplatform)
|
||||||
|
alias(libs.plugins.android.library)
|
||||||
alias(libs.plugins.binary.compatibility.validator)
|
alias(libs.plugins.binary.compatibility.validator)
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
signing
|
signing
|
||||||
@@ -9,53 +8,87 @@ plugins {
|
|||||||
|
|
||||||
group = "app.revanced"
|
group = "app.revanced"
|
||||||
|
|
||||||
|
// Because access to the project is necessary to authenticate with GitHub,
|
||||||
|
// the following block must be placed in the root build.gradle.kts file
|
||||||
|
// instead of the settings.gradle.kts file inside the dependencyResolutionManagement block.
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
google()
|
google()
|
||||||
maven {
|
maven {
|
||||||
// A repository must be speficied for some reason. "registry" is a dummy.
|
// A repository must be specified for some reason. "registry" is a dummy.
|
||||||
url = uri("https://maven.pkg.github.com/revanced/registry")
|
url = uri("https://maven.pkg.github.com/revanced/registry")
|
||||||
credentials {
|
credentials {
|
||||||
username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
|
username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
|
||||||
password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN")
|
password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
maven { url = uri("https://jitpack.io") }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
kotlin {
|
||||||
implementation(libs.revanced.patcher)
|
jvm {
|
||||||
implementation(libs.kotlin.reflect)
|
compilations.all {
|
||||||
implementation(libs.jadb) // Fork with Shell v2 support.
|
kotlinOptions {
|
||||||
implementation(libs.jackson.module.kotlin)
|
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||||
implementation(libs.apkzlib)
|
}
|
||||||
implementation(libs.apksig)
|
}
|
||||||
implementation(libs.bcpkix.jdk15on)
|
}
|
||||||
implementation(libs.guava)
|
|
||||||
|
|
||||||
testImplementation(libs.revanced.patcher)
|
androidTarget {
|
||||||
testImplementation(libs.kotlin.test)
|
compilations.all {
|
||||||
}
|
kotlinOptions {
|
||||||
|
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tasks {
|
publishLibraryVariants("release")
|
||||||
test {
|
}
|
||||||
useJUnitPlatform()
|
|
||||||
testLogging {
|
sourceSets {
|
||||||
events("PASSED", "SKIPPED", "FAILED")
|
androidMain.dependencies {
|
||||||
|
implementation(libs.libsu.nio)
|
||||||
|
implementation(libs.libsu.service)
|
||||||
|
implementation(libs.core.ktx)
|
||||||
|
}
|
||||||
|
|
||||||
|
commonMain.dependencies {
|
||||||
|
implementation(libs.revanced.patcher)
|
||||||
|
implementation(libs.kotlin.reflect)
|
||||||
|
implementation(libs.jadb) // Fork with Shell v2 support.
|
||||||
|
implementation(libs.bcpkix.jdk15on)
|
||||||
|
implementation(libs.jackson.module.kotlin)
|
||||||
|
implementation(libs.apkzlib)
|
||||||
|
implementation(libs.apksig)
|
||||||
|
implementation(libs.guava)
|
||||||
|
}
|
||||||
|
|
||||||
|
commonTest.dependencies {
|
||||||
|
implementation(libs.revanced.patcher)
|
||||||
|
implementation(libs.kotlin.test.junit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
android {
|
||||||
compilerOptions {
|
namespace = "app.revanced.library"
|
||||||
jvmTarget.set(JvmTarget.JVM_11)
|
compileSdk = 34
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 26
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
aidl = true
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
|
||||||
withSourcesJar()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
@@ -72,8 +105,6 @@ publishing {
|
|||||||
|
|
||||||
publications {
|
publications {
|
||||||
create<MavenPublication>("revanced-library-publication") {
|
create<MavenPublication>("revanced-library-publication") {
|
||||||
from(components["java"])
|
|
||||||
|
|
||||||
version = project.version.toString()
|
version = project.version.toString()
|
||||||
|
|
||||||
pom {
|
pom {
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
org.gradle.parallel = true
|
|
||||||
org.gradle.caching = true
|
|
||||||
kotlin.code.style = official
|
|
||||||
version = 2.3.0
|
version = 2.3.0
|
||||||
|
|
||||||
|
#Gradle
|
||||||
|
org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M"
|
||||||
|
org.gradle.caching=true
|
||||||
|
org.gradle.configuration-cache=true
|
||||||
|
org.gradle.parallel = true
|
||||||
|
|
||||||
|
#Kotlin
|
||||||
|
kotlin.code.style=official
|
||||||
|
|
||||||
|
#Android
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.nonTransitiveRClass=true
|
||||||
|
|||||||
@@ -4,22 +4,29 @@ jadb = "1.2.1"
|
|||||||
kotlin = "1.9.22"
|
kotlin = "1.9.22"
|
||||||
revanced-patcher = "19.3.1"
|
revanced-patcher = "19.3.1"
|
||||||
binary-compatibility-validator = "0.14.0"
|
binary-compatibility-validator = "0.14.0"
|
||||||
apkzlib = "8.3.0"
|
android = "8.3.0"
|
||||||
bcpkix-jdk15on = "1.70"
|
bcpkix-jdk15on = "1.70"
|
||||||
guava = "33.0.0-jre"
|
guava = "33.0.0-jre"
|
||||||
apksig = "8.3.0"
|
libsu = "5.2.2"
|
||||||
|
core-ktx = "1.12.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson-module-kotlin" }
|
jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson-module-kotlin" }
|
||||||
jadb = { module = "app.revanced:jadb", version.ref = "jadb" }
|
jadb = { module = "app.revanced:jadb", version.ref = "jadb" }
|
||||||
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
|
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
|
||||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
|
||||||
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
|
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
|
||||||
apkzlib = { module = "com.android.tools.build:apkzlib", version.ref = "apkzlib" }
|
apkzlib = { module = "com.android.tools.build:apkzlib", version.ref = "android" }
|
||||||
|
apksig = { module = "com.android.tools.build:apksig", version.ref = "android" }
|
||||||
bcpkix-jdk15on = { module = "org.bouncycastle:bcpkix-jdk15on", version.ref = "bcpkix-jdk15on" }
|
bcpkix-jdk15on = { module = "org.bouncycastle:bcpkix-jdk15on", version.ref = "bcpkix-jdk15on" }
|
||||||
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
||||||
apksig = { module = "com.android.tools.build:apksig", version.ref = "apksig" }
|
libsu-core = { module = "com.github.topjohnwu.libsu:core", version.ref = "libsu" }
|
||||||
|
libsu-nio = { module = "com.github.topjohnwu.libsu:nio", version.ref = "libsu" }
|
||||||
|
libsu-service = { module = "com.github.topjohnwu.libsu:service", version.ref = "libsu" }
|
||||||
|
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
|
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
|
||||||
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
android-library = { id = "com.android.library", version.ref = "android" }
|
||||||
|
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
281
gradlew
vendored
281
gradlew
vendored
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright © 2015-2021 the original authors.
|
# Copyright 2015 the original author or authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -17,98 +17,67 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
##
|
||||||
# Gradle start up script for POSIX generated by Gradle.
|
## Gradle start up script for UN*X
|
||||||
#
|
##
|
||||||
# Important for running:
|
|
||||||
#
|
|
||||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
|
||||||
# noncompliant, but you have some other compliant shell such as ksh or
|
|
||||||
# bash, then to run this script, type that shell name before the whole
|
|
||||||
# command line, like:
|
|
||||||
#
|
|
||||||
# ksh Gradle
|
|
||||||
#
|
|
||||||
# Busybox and similar reduced shells will NOT work, because this script
|
|
||||||
# requires all of these POSIX shell features:
|
|
||||||
# * functions;
|
|
||||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
|
||||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
|
||||||
# * compound commands having a testable exit status, especially «case»;
|
|
||||||
# * various built-in commands including «command», «set», and «ulimit».
|
|
||||||
#
|
|
||||||
# Important for patching:
|
|
||||||
#
|
|
||||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
|
||||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
|
||||||
#
|
|
||||||
# The "traditional" practice of packing multiple parameters into a
|
|
||||||
# space-separated string is a well documented source of bugs and security
|
|
||||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
|
||||||
# options in "$@", and eventually passing that to Java.
|
|
||||||
#
|
|
||||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
|
||||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
|
||||||
# see the in-line comments for details.
|
|
||||||
#
|
|
||||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
|
||||||
# Darwin, MinGW, and NonStop.
|
|
||||||
#
|
|
||||||
# (3) This script is generated from the Groovy template
|
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
|
||||||
# within the Gradle project.
|
|
||||||
#
|
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
|
||||||
#
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
app_path=$0
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
# Need this for daisy-chained symlinks.
|
while [ -h "$PRG" ] ; do
|
||||||
while
|
ls=`ls -ld "$PRG"`
|
||||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
[ -h "$app_path" ]
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
do
|
PRG="$link"
|
||||||
ls=$( ls -ld "$app_path" )
|
else
|
||||||
link=${ls#*' -> '}
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
case $link in #(
|
fi
|
||||||
/*) app_path=$link ;; #(
|
|
||||||
*) app_path=$APP_HOME$link ;;
|
|
||||||
esac
|
|
||||||
done
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
# This is normally unused
|
APP_NAME="Gradle"
|
||||||
# shellcheck disable=SC2034
|
APP_BASE_NAME=`basename "$0"`
|
||||||
APP_BASE_NAME=${0##*/}
|
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD="maximum"
|
||||||
|
|
||||||
warn () {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
} >&2
|
}
|
||||||
|
|
||||||
die () {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
} >&2
|
}
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
# OS specific support (must be 'true' or 'false').
|
||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
nonstop=false
|
nonstop=false
|
||||||
case "$( uname )" in #(
|
case "`uname`" in
|
||||||
CYGWIN* ) cygwin=true ;; #(
|
CYGWIN* )
|
||||||
Darwin* ) darwin=true ;; #(
|
cygwin=true
|
||||||
MSYS* | MINGW* ) msys=true ;; #(
|
;;
|
||||||
NONSTOP* ) nonstop=true ;;
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
@@ -118,9 +87,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
else
|
else
|
||||||
JAVACMD=$JAVA_HOME/bin/java
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
@@ -129,120 +98,88 @@ Please set the JAVA_HOME variable in your environment to match the
|
|||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD="java"
|
||||||
if ! command -v java >/dev/null 2>&1
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
then
|
|
||||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
case $MAX_FD in #(
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
max*)
|
if [ $? -eq 0 ] ; then
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
# shellcheck disable=SC3045
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
fi
|
||||||
warn "Could not query maximum file descriptor limit"
|
ulimit -n $MAX_FD
|
||||||
esac
|
if [ $? -ne 0 ] ; then
|
||||||
case $MAX_FD in #(
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
'' | soft) :;; #(
|
fi
|
||||||
*)
|
else
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
# shellcheck disable=SC3045
|
fi
|
||||||
ulimit -n "$MAX_FD" ||
|
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
|
||||||
esac
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Collect all arguments for the java command, stacking in reverse order:
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
# * args from the command line
|
if $darwin; then
|
||||||
# * the main class name
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
# * -classpath
|
fi
|
||||||
# * -D...appname settings
|
|
||||||
# * --module-path (only if needed)
|
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
|
||||||
|
|
||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if "$cygwin" || "$msys" ; then
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
for arg do
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
if
|
SEP=""
|
||||||
case $arg in #(
|
for dir in $ROOTDIRSRAW ; do
|
||||||
-*) false ;; # don't mess with options #(
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
SEP="|"
|
||||||
[ -e "$t" ] ;; #(
|
|
||||||
*) false ;;
|
|
||||||
esac
|
|
||||||
then
|
|
||||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
|
||||||
fi
|
|
||||||
# Roll the args list around exactly as many times as the number of
|
|
||||||
# args, so each arg winds up back in the position where it started, but
|
|
||||||
# possibly modified.
|
|
||||||
#
|
|
||||||
# NB: a `for` loop captures its iteration list before it begins, so
|
|
||||||
# changing the positional parameters here affects neither the number of
|
|
||||||
# iterations, nor the values presented in `arg`.
|
|
||||||
shift # remove old arg
|
|
||||||
set -- "$@" "$arg" # push replacement arg
|
|
||||||
done
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
0) set -- ;;
|
||||||
|
1) set -- "$args0" ;;
|
||||||
|
2) set -- "$args0" "$args1" ;;
|
||||||
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
|
||||||
# double quotes to make sure that they get re-expanded; and
|
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
|
||||||
|
|
||||||
set -- \
|
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
|
||||||
-classpath "$CLASSPATH" \
|
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
|
||||||
"$@"
|
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
|
||||||
if ! command -v xargs >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
die "xargs is not available"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
|
||||||
#
|
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
|
||||||
#
|
|
||||||
# In Bash we could simply go:
|
|
||||||
#
|
|
||||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
|
||||||
# set -- "${ARGS[@]}" "$@"
|
|
||||||
#
|
|
||||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
|
||||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
|
||||||
# character that might be a shell metacharacter, then use eval to reverse
|
|
||||||
# that process (while maintaining the separation between arguments), and wrap
|
|
||||||
# the whole thing up as a single "set" statement.
|
|
||||||
#
|
|
||||||
# This will of course break if any of these variables contains a newline or
|
|
||||||
# an unmatched quote.
|
|
||||||
#
|
|
||||||
|
|
||||||
eval "set -- $(
|
|
||||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
|
||||||
xargs -n1 |
|
|
||||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
|
||||||
tr '\n' ' '
|
|
||||||
)" '"$@"'
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
15
gradlew.bat
vendored
15
gradlew.bat
vendored
@@ -14,7 +14,7 @@
|
|||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@@ -25,8 +25,7 @@
|
|||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
@rem This is normally unused
|
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@@ -41,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@@ -76,15 +75,13 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
set EXIT_CODE=%ERRORLEVEL%
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
exit /b 1
|
||||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
|
||||||
exit /b %EXIT_CODE%
|
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
|
// TODO: Figure out why this causes problems.
|
||||||
rootProject.name = "revanced-library"
|
rootProject.name = "revanced-library"
|
||||||
|
|
||||||
buildCache {
|
buildCache {
|
||||||
local {
|
local {
|
||||||
isEnabled = !System.getenv().containsKey("CI")
|
isEnabled = "CI" !in System.getenv()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package app.revanced.library.installation.command;
|
||||||
|
|
||||||
|
interface ILocalShellCommandRunnerRootService {
|
||||||
|
IBinder getFileSystemService();
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package app.revanced.library.installation.command
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.ServiceConnection
|
||||||
|
import android.os.IBinder
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
|
import com.topjohnwu.superuser.internal.BuilderImpl
|
||||||
|
import com.topjohnwu.superuser.ipc.RootService
|
||||||
|
import com.topjohnwu.superuser.nio.FileSystemManager
|
||||||
|
import java.io.Closeable
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [LocalShellCommandRunner] for running commands locally on the device.
|
||||||
|
*
|
||||||
|
* @param context The [Context] to use for binding to the [RootService].
|
||||||
|
* @param onReady A callback to be invoked when [LocalShellCommandRunner] is ready to be used.
|
||||||
|
* @throws IllegalStateException If the main shell was already created
|
||||||
|
*
|
||||||
|
* @see ShellCommandRunner
|
||||||
|
*/
|
||||||
|
class LocalShellCommandRunner internal constructor(
|
||||||
|
private val context: Context,
|
||||||
|
private val onReady: () -> Unit,
|
||||||
|
) : ShellCommandRunner(), ServiceConnection, Closeable {
|
||||||
|
private var fileSystemManager: FileSystemManager? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
logger.info("Binding to RootService")
|
||||||
|
val intent = Intent(context, LocalShellCommandRunnerRootService::class.java)
|
||||||
|
RootService.bind(intent, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun runCommand(command: String) = shell.newJob().add(command).exec().let {
|
||||||
|
object : RunResult {
|
||||||
|
override val exitCode = it.code
|
||||||
|
override val output by lazy { it.out.joinToString("\n") }
|
||||||
|
override val error by lazy { it.err.joinToString("\n") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasRootPermission() = shell.isRoot
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given [content] to the given [targetFilePath].
|
||||||
|
*
|
||||||
|
* @param content The [InputStream] to write.
|
||||||
|
* @param targetFilePath The path to write to.
|
||||||
|
* @throws NotReadyException If the [LocalShellCommandRunner] is not ready yet.
|
||||||
|
*/
|
||||||
|
override fun write(content: InputStream, targetFilePath: String) {
|
||||||
|
fileSystemManager?.let {
|
||||||
|
it.getFile(targetFilePath).newOutputStream().use { outputStream ->
|
||||||
|
content.copyTo(outputStream)
|
||||||
|
}
|
||||||
|
} ?: throw NotReadyException("FileSystemManager service is not ready yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun move(file: File, targetFilePath: String) {
|
||||||
|
invoke("mv ${file.absolutePath} $targetFilePath")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||||
|
val ipc = ILocalShellCommandRunnerRootService.Stub.asInterface(service)
|
||||||
|
fileSystemManager = FileSystemManager.getRemote(ipc.fileSystemService)
|
||||||
|
|
||||||
|
logger.info("LocalShellCommandRunner service is ready")
|
||||||
|
|
||||||
|
onReady()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceDisconnected(name: ComponentName?) {
|
||||||
|
fileSystemManager = null
|
||||||
|
|
||||||
|
logger.info("LocalShellCommandRunner service is disconnected")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() = RootService.unbind(this)
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private val shell = BuilderImpl.create().setFlags(Shell.FLAG_MOUNT_MASTER).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NotReadyException internal constructor(message: String) : Exception(message)
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package app.revanced.library.installation.command
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import com.topjohnwu.superuser.ipc.RootService
|
||||||
|
import com.topjohnwu.superuser.nio.FileSystemManager
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [RootService] for the [LocalShellCommandRunner].
|
||||||
|
*/
|
||||||
|
internal class LocalShellCommandRunnerRootService : RootService() {
|
||||||
|
override fun onBind(intent: Intent) = object : ILocalShellCommandRunnerRootService.Stub() {
|
||||||
|
override fun getFileSystemService() =
|
||||||
|
FileSystemManager.getService()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.content.pm.PackageInstaller
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import app.revanced.library.installation.installer.Installer.Apk
|
||||||
|
import java.io.Closeable
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [LocalInstaller] for installing and uninstalling [Apk] files locally.
|
||||||
|
*
|
||||||
|
* @param context The [Context] to use for installing and uninstalling.
|
||||||
|
* @param onResult The callback to be invoked when the [Apk] is installed or uninstalled.
|
||||||
|
*
|
||||||
|
* @see Installer
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
class LocalInstaller(
|
||||||
|
private val context: Context,
|
||||||
|
onResult: (result: LocalInstallerResult) -> Unit,
|
||||||
|
) : Installer<Unit, Installation>(), Closeable {
|
||||||
|
private val broadcastReceiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
val pmStatus = intent.getIntExtra(LocalInstallerService.EXTRA_STATUS, -999)
|
||||||
|
val extra = intent.getStringExtra(LocalInstallerService.EXTRA_STATUS_MESSAGE)!!
|
||||||
|
val packageName = intent.getStringExtra(LocalInstallerService.EXTRA_PACKAGE_NAME)!!
|
||||||
|
|
||||||
|
onResult.invoke(LocalInstallerResult(pmStatus, extra, packageName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val intentSender
|
||||||
|
get() = PendingIntent.getService(
|
||||||
|
context,
|
||||||
|
0,
|
||||||
|
Intent(context, LocalInstallerService::class.java),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT,
|
||||||
|
).intentSender
|
||||||
|
|
||||||
|
init {
|
||||||
|
ContextCompat.registerReceiver(
|
||||||
|
context,
|
||||||
|
broadcastReceiver,
|
||||||
|
IntentFilter().apply {
|
||||||
|
addAction(LocalInstallerService.ACTION)
|
||||||
|
},
|
||||||
|
ContextCompat.RECEIVER_NOT_EXPORTED,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun install(apk: Apk) {
|
||||||
|
logger.info("Installing ${apk.file.name}")
|
||||||
|
|
||||||
|
val packageInstaller = context.packageManager.packageInstaller
|
||||||
|
|
||||||
|
packageInstaller.openSession(packageInstaller.createSession(sessionParams)).use { session ->
|
||||||
|
session.writeApk(apk.file)
|
||||||
|
session.commit(intentSender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
override suspend fun uninstall(packageName: String) {
|
||||||
|
logger.info("Uninstalling $packageName")
|
||||||
|
|
||||||
|
val packageInstaller = context.packageManager.packageInstaller
|
||||||
|
|
||||||
|
packageInstaller.uninstall(packageName, intentSender)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getInstallation(packageName: String) = try {
|
||||||
|
val packageInfo = context.packageManager.getPackageInfo(packageName, 0)
|
||||||
|
|
||||||
|
Installation(packageInfo.applicationInfo.sourceDir)
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() = context.unregisterReceiver(broadcastReceiver)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val sessionParams = PackageInstaller.SessionParams(
|
||||||
|
PackageInstaller.SessionParams.MODE_FULL_INSTALL,
|
||||||
|
).apply {
|
||||||
|
setInstallReason(PackageManager.INSTALL_REASON_USER)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PackageInstaller.Session.writeApk(apk: File) {
|
||||||
|
apk.inputStream().use { inputStream ->
|
||||||
|
openWrite(apk.name, 0, apk.length()).use { outputStream ->
|
||||||
|
inputStream.copyTo(outputStream, 1024 * 1024)
|
||||||
|
fsync(outputStream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import app.revanced.library.installation.installer.Installer.Apk
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of installing or uninstalling an [Apk] locally using [LocalInstaller].
|
||||||
|
*
|
||||||
|
* @param pmStatus The status code returned by the package manager.
|
||||||
|
* @param extra The extra information returned by the package manager.
|
||||||
|
* @param packageName The package name of the installed app.
|
||||||
|
*
|
||||||
|
* @see LocalInstaller
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
class LocalInstallerResult internal constructor(val pmStatus: Int, val extra: String, val packageName: String)
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import android.app.Service
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageInstaller
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.IBinder
|
||||||
|
|
||||||
|
class LocalInstallerService : Service() {
|
||||||
|
override fun onStartCommand(
|
||||||
|
intent: Intent, flags: Int, startId: Int
|
||||||
|
): Int {
|
||||||
|
val extraStatus = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, 0)
|
||||||
|
val extraStatusMessage = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)
|
||||||
|
val extraPackageName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)
|
||||||
|
|
||||||
|
when (extraStatus) {
|
||||||
|
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
|
||||||
|
startActivity(
|
||||||
|
if (Build.VERSION.SDK_INT >= 33) {
|
||||||
|
intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
intent.getParcelableExtra(Intent.EXTRA_INTENT)
|
||||||
|
}?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
sendBroadcast(
|
||||||
|
Intent().apply {
|
||||||
|
action = ACTION
|
||||||
|
`package` = packageName
|
||||||
|
|
||||||
|
putExtra(EXTRA_STATUS, extraStatus)
|
||||||
|
putExtra(EXTRA_STATUS_MESSAGE, extraStatusMessage)
|
||||||
|
putExtra(EXTRA_PACKAGE_NAME, extraPackageName)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stopSelf()
|
||||||
|
|
||||||
|
return START_NOT_STICKY
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent?): IBinder? = null
|
||||||
|
|
||||||
|
internal companion object {
|
||||||
|
internal const val ACTION = "PACKAGE_INSTALLER_ACTION"
|
||||||
|
|
||||||
|
internal const val EXTRA_STATUS = "EXTRA_STATUS"
|
||||||
|
internal const val EXTRA_STATUS_MESSAGE = "EXTRA_STATUS_MESSAGE"
|
||||||
|
internal const val EXTRA_PACKAGE_NAME = "EXTRA_PACKAGE_NAME"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import app.revanced.library.installation.command.LocalShellCommandRunner
|
||||||
|
import app.revanced.library.installation.installer.Installer.Apk
|
||||||
|
import app.revanced.library.installation.installer.RootInstaller.NoRootPermissionException
|
||||||
|
import com.topjohnwu.superuser.ipc.RootService
|
||||||
|
import java.io.Closeable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [LocalRootInstaller] for installing and uninstalling [Apk] files locally with using root permissions by mounting.
|
||||||
|
*
|
||||||
|
* @param context The [Context] to use for binding to the [RootService].
|
||||||
|
* @param onReady A callback to be invoked when [LocalRootInstaller] is ready to be used.
|
||||||
|
*
|
||||||
|
* @throws NoRootPermissionException If the device does not have root permission.
|
||||||
|
*
|
||||||
|
* @see Installer
|
||||||
|
* @see LocalShellCommandRunner
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
class LocalRootInstaller(
|
||||||
|
context: Context,
|
||||||
|
onReady: LocalRootInstaller.() -> Unit = {},
|
||||||
|
) : RootInstaller(
|
||||||
|
{ installer ->
|
||||||
|
LocalShellCommandRunner(context) {
|
||||||
|
(installer as LocalRootInstaller).onReady()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Closeable {
|
||||||
|
override fun close() = (shellCommandRunner as LocalShellCommandRunner).close()
|
||||||
|
}
|
||||||
43
src/commonMain/kotlin/app/revanced/library/Commands.kt
Normal file
43
src/commonMain/kotlin/app/revanced/library/Commands.kt
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
@file:Suppress("DeprecatedCallableAddReplaceWith")
|
||||||
|
|
||||||
|
package app.revanced.library
|
||||||
|
|
||||||
|
import app.revanced.library.installation.command.AdbShellCommandRunner
|
||||||
|
import se.vidstige.jadb.JadbDevice
|
||||||
|
import se.vidstige.jadb.ShellProcessBuilder
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
@Deprecated("Do not use this anymore. Instead use AdbCommandRunner.")
|
||||||
|
internal fun JadbDevice.buildCommand(
|
||||||
|
command: String,
|
||||||
|
su: Boolean = true,
|
||||||
|
): ShellProcessBuilder {
|
||||||
|
if (su) return shellProcessBuilder("su -c \'$command\'")
|
||||||
|
|
||||||
|
val args = command.split(" ") as ArrayList<String>
|
||||||
|
val cmd = args.removeFirst()
|
||||||
|
|
||||||
|
return shellProcessBuilder(cmd, *args.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
@Deprecated("Use AdbShellCommandRunner instead.")
|
||||||
|
internal fun JadbDevice.run(
|
||||||
|
command: String,
|
||||||
|
su: Boolean = true,
|
||||||
|
) = buildCommand(command, su).start()
|
||||||
|
|
||||||
|
@Deprecated("Use AdbShellCommandRunner instead.")
|
||||||
|
internal fun JadbDevice.hasSu() = AdbShellCommandRunner(this).hasRootPermission()
|
||||||
|
|
||||||
|
@Deprecated("Use AdbShellCommandRunner instead.")
|
||||||
|
internal fun JadbDevice.push(
|
||||||
|
file: File,
|
||||||
|
targetFilePath: String,
|
||||||
|
) = AdbShellCommandRunner(this).move(file, targetFilePath)
|
||||||
|
|
||||||
|
@Deprecated("Use AdbShellCommandRunner instead.")
|
||||||
|
internal fun JadbDevice.createFile(
|
||||||
|
targetFile: String,
|
||||||
|
content: String,
|
||||||
|
) = AdbShellCommandRunner(this).write(content.byteInputStream(), targetFile)
|
||||||
18
src/commonMain/kotlin/app/revanced/library/Utils.kt
Normal file
18
src/commonMain/kotlin/app/revanced/library/Utils.kt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package app.revanced.library
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utils for the library.
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
object Utils {
|
||||||
|
/**
|
||||||
|
* True if the environment is Android.
|
||||||
|
*/
|
||||||
|
val isAndroidEnvironment =
|
||||||
|
try {
|
||||||
|
Class.forName("android.app.Application")
|
||||||
|
true
|
||||||
|
} catch (e: ClassNotFoundException) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
144
src/commonMain/kotlin/app/revanced/library/adb/AdbManager.kt
Normal file
144
src/commonMain/kotlin/app/revanced/library/adb/AdbManager.kt
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
|
package app.revanced.library.adb
|
||||||
|
|
||||||
|
import app.revanced.library.adb.AdbManager.Apk
|
||||||
|
import app.revanced.library.installation.installer.AdbInstaller
|
||||||
|
import app.revanced.library.installation.installer.AdbRootInstaller
|
||||||
|
import app.revanced.library.installation.installer.Constants.PLACEHOLDER
|
||||||
|
import app.revanced.library.installation.installer.Installer
|
||||||
|
import app.revanced.library.run
|
||||||
|
import se.vidstige.jadb.JadbDevice
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [AdbManager] to install and uninstall [Apk] files.
|
||||||
|
*
|
||||||
|
* @param deviceSerial The serial of the device. If null, the first connected device will be used.
|
||||||
|
*/
|
||||||
|
@Deprecated("Use an implementation of Installer instead.")
|
||||||
|
@Suppress("unused")
|
||||||
|
sealed class AdbManager private constructor(
|
||||||
|
@Suppress("UNUSED_PARAMETER") deviceSerial: String?,
|
||||||
|
) {
|
||||||
|
protected abstract val installer: Installer<*, *>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs the [Apk] file.
|
||||||
|
*
|
||||||
|
* @param apk The [Apk] file.
|
||||||
|
*/
|
||||||
|
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||||
|
@Deprecated("Use Installer.install instead.")
|
||||||
|
open fun install(apk: Apk) = suspend {
|
||||||
|
installer.install(Installer.Apk(apk.file, apk.packageName))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstalls the package.
|
||||||
|
*
|
||||||
|
* @param packageName The package name.
|
||||||
|
*/
|
||||||
|
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||||
|
@Deprecated("Use Installer.uninstall instead.")
|
||||||
|
open fun uninstall(packageName: String) = suspend {
|
||||||
|
installer.uninstall(packageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use Installer instead.")
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Gets an [AdbManager] for the supplied device serial.
|
||||||
|
*
|
||||||
|
* @param deviceSerial The device serial. If null, the first connected device will be used.
|
||||||
|
* @param root Whether to use root or not.
|
||||||
|
* @return The [AdbManager].
|
||||||
|
* @throws DeviceNotFoundException If the device can not be found.
|
||||||
|
*/
|
||||||
|
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||||
|
@Deprecated("This is deprecated.")
|
||||||
|
fun getAdbManager(
|
||||||
|
deviceSerial: String? = null,
|
||||||
|
root: Boolean = false,
|
||||||
|
): AdbManager = if (root) RootAdbManager(deviceSerial) else UserAdbManager(deviceSerial)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adb manager for rooted devices.
|
||||||
|
*
|
||||||
|
* @param deviceSerial The device serial. If null, the first connected device will be used.
|
||||||
|
*/
|
||||||
|
@Deprecated("Use AdbRootInstaller instead.", ReplaceWith("AdbRootInstaller(deviceSerial)"))
|
||||||
|
class RootAdbManager internal constructor(deviceSerial: String?) : AdbManager(deviceSerial) {
|
||||||
|
override val installer = AdbRootInstaller(deviceSerial)
|
||||||
|
|
||||||
|
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||||
|
@Deprecated("Use AdbRootInstaller.install instead.")
|
||||||
|
override fun install(apk: Apk) = suspend {
|
||||||
|
installer.install(Installer.Apk(apk.file, apk.packageName))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||||
|
@Deprecated("Use AdbRootInstaller.uninstall instead.")
|
||||||
|
override fun uninstall(packageName: String) = suspend {
|
||||||
|
installer.uninstall(packageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("This is deprecated.")
|
||||||
|
companion object Utils {
|
||||||
|
private fun JadbDevice.run(
|
||||||
|
command: String,
|
||||||
|
with: String,
|
||||||
|
) = run(command.applyReplacement(with))
|
||||||
|
|
||||||
|
private fun String.applyReplacement(with: String) = replace(PLACEHOLDER, with)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adb manager for non-rooted devices.
|
||||||
|
*
|
||||||
|
* @param deviceSerial The device serial. If null, the first connected device will be used.
|
||||||
|
*/
|
||||||
|
@Deprecated("Use AdbInstaller instead.")
|
||||||
|
class UserAdbManager internal constructor(deviceSerial: String?) : AdbManager(deviceSerial) {
|
||||||
|
override val installer = AdbInstaller(deviceSerial)
|
||||||
|
|
||||||
|
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||||
|
@Deprecated("Use AdbInstaller.install instead.")
|
||||||
|
override fun install(apk: Apk) = suspend {
|
||||||
|
installer.install(Installer.Apk(apk.file, apk.packageName))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||||
|
@Deprecated("Use AdbInstaller.uninstall instead.")
|
||||||
|
override fun uninstall(packageName: String) = suspend {
|
||||||
|
installer.uninstall(packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apk file for [AdbManager].
|
||||||
|
*
|
||||||
|
* @param file The [Apk] file.
|
||||||
|
* @param packageName The package name of the [Apk] file.
|
||||||
|
*/
|
||||||
|
@Deprecated("Use Installer.Apk instead.")
|
||||||
|
class Apk(val file: File, val packageName: String? = null)
|
||||||
|
|
||||||
|
@Deprecated("Use AdbCommandRunner.DeviceNotFoundException instead.")
|
||||||
|
class DeviceNotFoundException internal constructor(deviceSerial: String? = null) :
|
||||||
|
Exception(
|
||||||
|
deviceSerial?.let {
|
||||||
|
"The device with the ADB device serial \"$deviceSerial\" can not be found"
|
||||||
|
} ?: "No ADB device found",
|
||||||
|
)
|
||||||
|
|
||||||
|
@Deprecated("Use RootInstaller.FailedToFindInstalledPackageException instead.")
|
||||||
|
class FailedToFindInstalledPackageException internal constructor(packageName: String) :
|
||||||
|
Exception("Failed to find installed package \"$packageName\" because no activity was found")
|
||||||
|
|
||||||
|
@Deprecated("Use RootInstaller.PackageNameRequiredException instead.")
|
||||||
|
class PackageNameRequiredException internal constructor() :
|
||||||
|
Exception("Package name is required")
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package app.revanced.library.installation.command
|
||||||
|
|
||||||
|
import app.revanced.library.installation.installer.Utils
|
||||||
|
import se.vidstige.jadb.JadbDevice
|
||||||
|
import se.vidstige.jadb.RemoteFile
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [AdbShellCommandRunner] for running commands on a device remotely using ADB.
|
||||||
|
*
|
||||||
|
* @see ShellCommandRunner
|
||||||
|
*/
|
||||||
|
class AdbShellCommandRunner : ShellCommandRunner {
|
||||||
|
private val device: JadbDevice
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a [AdbShellCommandRunner] for the given device.
|
||||||
|
*
|
||||||
|
* @param device The device.
|
||||||
|
*/
|
||||||
|
internal constructor(device: JadbDevice) {
|
||||||
|
this.device = device
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a [AdbShellCommandRunner] for the device with the given serial.
|
||||||
|
*
|
||||||
|
* @param deviceSerial deviceSerial The device serial. If null, the first connected device will be used.
|
||||||
|
*/
|
||||||
|
internal constructor(deviceSerial: String?) {
|
||||||
|
device = Utils.getDevice(deviceSerial, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun runCommand(command: String) = device.shellProcessBuilder(command).start().let { process ->
|
||||||
|
object : RunResult {
|
||||||
|
override val exitCode by lazy { process.waitFor() }
|
||||||
|
override val output by lazy { process.inputStream.bufferedReader().readText() }
|
||||||
|
override val error by lazy { process.errorStream.bufferedReader().readText() }
|
||||||
|
|
||||||
|
override fun waitFor() {
|
||||||
|
process.waitFor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasRootPermission(): Boolean = invoke("whoami").exitCode == 0
|
||||||
|
|
||||||
|
override fun write(content: InputStream, targetFilePath: String) =
|
||||||
|
device.push(content, System.currentTimeMillis(), 644, RemoteFile(targetFilePath))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the given [file] from the local to the target file path on the device.
|
||||||
|
*
|
||||||
|
* @param file The file to move.
|
||||||
|
* @param targetFilePath The target file path.
|
||||||
|
*/
|
||||||
|
override fun move(file: File, targetFilePath: String) = device.push(file, RemoteFile(targetFilePath))
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package app.revanced.library.installation.command
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of a command execution.
|
||||||
|
*/
|
||||||
|
interface RunResult {
|
||||||
|
/**
|
||||||
|
* The exit code of the command.
|
||||||
|
*/
|
||||||
|
val exitCode: Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The output of the command.
|
||||||
|
*/
|
||||||
|
val output: String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The error of the command.
|
||||||
|
*/
|
||||||
|
val error: String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for the command to finish.
|
||||||
|
*/
|
||||||
|
fun waitFor() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package app.revanced.library.installation.command
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.logging.Logger
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ShellCommandRunner] for running commands on a device.
|
||||||
|
*/
|
||||||
|
abstract class ShellCommandRunner internal constructor() {
|
||||||
|
protected val logger: Logger = Logger.getLogger(this::class.java.name)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given [content] to the file at the given [targetFilePath] path.
|
||||||
|
*
|
||||||
|
* @param content The content of the file.
|
||||||
|
* @param targetFilePath The target file path.
|
||||||
|
*/
|
||||||
|
internal abstract fun write(
|
||||||
|
content: InputStream,
|
||||||
|
targetFilePath: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the given [file] to the given [targetFilePath] path.
|
||||||
|
*
|
||||||
|
* @param file The file to move.
|
||||||
|
* @param targetFilePath The target file path.
|
||||||
|
*/
|
||||||
|
internal abstract fun move(
|
||||||
|
file: File,
|
||||||
|
targetFilePath: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the given [command] on the device as root.
|
||||||
|
*
|
||||||
|
* @param command The command to run.
|
||||||
|
* @return The [RunResult].
|
||||||
|
*/
|
||||||
|
protected abstract fun runCommand(command: String): RunResult
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the device has root permission.
|
||||||
|
*
|
||||||
|
* @return True if the device has root permission, false otherwise.
|
||||||
|
*/
|
||||||
|
internal abstract fun hasRootPermission(): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs a command on the device as root.
|
||||||
|
*
|
||||||
|
* @param command The command to run.
|
||||||
|
* @return The [RunResult].
|
||||||
|
*/
|
||||||
|
internal operator fun invoke(
|
||||||
|
command: String,
|
||||||
|
) = runCommand("su -c \'$command\'")
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import app.revanced.library.installation.command.AdbShellCommandRunner
|
||||||
|
import app.revanced.library.installation.installer.Constants.INSTALLED_APK_PATH
|
||||||
|
import app.revanced.library.installation.installer.Installer.Apk
|
||||||
|
import se.vidstige.jadb.JadbException
|
||||||
|
import se.vidstige.jadb.managers.Package
|
||||||
|
import se.vidstige.jadb.managers.PackageManager
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [AdbInstaller] for installing and uninstalling [Apk] files using ADB.
|
||||||
|
*
|
||||||
|
* @param deviceSerial The device serial. If null, the first connected device will be used.
|
||||||
|
*
|
||||||
|
* @see Installer
|
||||||
|
*/
|
||||||
|
class AdbInstaller(
|
||||||
|
deviceSerial: String? = null,
|
||||||
|
) : Installer<AdbInstallerResult, Installation>() {
|
||||||
|
private val device = Utils.getDevice(deviceSerial, logger)
|
||||||
|
private val adbShellCommandRunner = AdbShellCommandRunner(device)
|
||||||
|
private val packageManager = PackageManager(device)
|
||||||
|
|
||||||
|
init {
|
||||||
|
logger.fine("Connected to $deviceSerial")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun install(apk: Apk): AdbInstallerResult {
|
||||||
|
logger.info("Installing ${apk.file.name}")
|
||||||
|
|
||||||
|
return runPackageManager { install(apk.file) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun uninstall(packageName: String): AdbInstallerResult {
|
||||||
|
logger.info("Uninstalling $packageName")
|
||||||
|
|
||||||
|
return runPackageManager { uninstall(Package(packageName)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getInstallation(packageName: String): Installation? = packageManager.packages.find {
|
||||||
|
it.toString() == packageName
|
||||||
|
}?.let { Installation(adbShellCommandRunner(INSTALLED_APK_PATH).output) }
|
||||||
|
|
||||||
|
private fun runPackageManager(block: PackageManager.() -> Unit) = try {
|
||||||
|
packageManager.run(block)
|
||||||
|
|
||||||
|
AdbInstallerResult.Success
|
||||||
|
} catch (e: JadbException) {
|
||||||
|
AdbInstallerResult.Failure(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import app.revanced.library.installation.installer.Installer.Apk
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of installing or uninstalling an [Apk] via ADB using [AdbInstaller].
|
||||||
|
*
|
||||||
|
* @see AdbInstaller
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
interface AdbInstallerResult {
|
||||||
|
/**
|
||||||
|
* The result of installing an [Apk] successfully.
|
||||||
|
*/
|
||||||
|
object Success : AdbInstallerResult
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of installing an [Apk] unsuccessfully.
|
||||||
|
*
|
||||||
|
* @param exception The exception that caused the installation to fail.
|
||||||
|
*/
|
||||||
|
class Failure internal constructor(val exception: Exception) : AdbInstallerResult
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import app.revanced.library.installation.command.AdbShellCommandRunner
|
||||||
|
import app.revanced.library.installation.installer.Installer.Apk
|
||||||
|
import app.revanced.library.installation.installer.RootInstaller.NoRootPermissionException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [AdbRootInstaller] for installing and uninstalling [Apk] files with using ADB root permissions by mounting.
|
||||||
|
*
|
||||||
|
* @param deviceSerial The device serial. If null, the first connected device will be used.
|
||||||
|
*
|
||||||
|
* @throws NoRootPermissionException If the device does not have root permission.
|
||||||
|
*
|
||||||
|
* @see RootInstaller
|
||||||
|
* @see AdbShellCommandRunner
|
||||||
|
*/
|
||||||
|
class AdbRootInstaller(
|
||||||
|
deviceSerial: String? = null,
|
||||||
|
) : RootInstaller({ AdbShellCommandRunner(deviceSerial) }) {
|
||||||
|
init {
|
||||||
|
logger.fine("Connected to $deviceSerial")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
internal object Constants {
|
||||||
|
const val PLACEHOLDER = "PLACEHOLDER"
|
||||||
|
|
||||||
|
const val TMP_FILE_PATH = "/data/local/tmp/revanced.tmp"
|
||||||
|
const val MOUNT_PATH = "/data/adb/revanced/"
|
||||||
|
const val MOUNTED_APK_PATH = "$MOUNT_PATH$PLACEHOLDER.apk"
|
||||||
|
const val MOUNT_SCRIPT_PATH = "/data/adb/service.d/mount_revanced_$PLACEHOLDER.sh"
|
||||||
|
|
||||||
|
const val EXISTS = "[[ -f $PLACEHOLDER ]] || exit 1"
|
||||||
|
const val MOUNT_GREP = "grep $PLACEHOLDER /proc/mounts"
|
||||||
|
const val DELETE = "rm -rf $PLACEHOLDER"
|
||||||
|
const val CREATE_DIR = "mkdir -p"
|
||||||
|
const val RESTART = "am start -S $PLACEHOLDER"
|
||||||
|
const val KILL = "am force-stop $PLACEHOLDER"
|
||||||
|
const val INSTALLED_APK_PATH = "pm path $PLACEHOLDER"
|
||||||
|
const val CREATE_INSTALLATION_PATH = "$CREATE_DIR $MOUNT_PATH"
|
||||||
|
|
||||||
|
const val MOUNT_APK =
|
||||||
|
"base_path=\"$MOUNTED_APK_PATH\" && " +
|
||||||
|
"mv $TMP_FILE_PATH \$base_path && " +
|
||||||
|
"chmod 644 \$base_path && " +
|
||||||
|
"chown system:system \$base_path && " +
|
||||||
|
"chcon u:object_r:apk_data_file:s0 \$base_path"
|
||||||
|
|
||||||
|
const val UMOUNT =
|
||||||
|
"grep $PLACEHOLDER /proc/mounts | " +
|
||||||
|
"while read -r line; do echo \$line | " +
|
||||||
|
"cut -d ' ' -f 2 | " +
|
||||||
|
"sed 's/apk.*/apk/' | " +
|
||||||
|
"xargs -r umount -l; done"
|
||||||
|
|
||||||
|
const val INSTALL_MOUNT_SCRIPT = "mv $TMP_FILE_PATH $MOUNT_SCRIPT_PATH && chmod +x $MOUNT_SCRIPT_PATH"
|
||||||
|
|
||||||
|
val MOUNT_SCRIPT =
|
||||||
|
"""
|
||||||
|
#!/system/bin/sh
|
||||||
|
until [ "$( getprop sys.boot_completed )" = 1 ]; do sleep 3; done
|
||||||
|
until [ -d "/sdcard/Android" ]; do sleep 1; done
|
||||||
|
|
||||||
|
stock_path=$( pm path $PLACEHOLDER | grep base | sed 's/package://g' )
|
||||||
|
|
||||||
|
# Make sure the app is installed.
|
||||||
|
if [ -z "${'$'}stock_path" ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unmount any existing installations to prevent multiple unnecessary mounts.
|
||||||
|
$UMOUNT
|
||||||
|
|
||||||
|
base_path="$MOUNTED_APK_PATH"
|
||||||
|
|
||||||
|
chcon u:object_r:apk_data_file:s0 ${'$'}base_path
|
||||||
|
|
||||||
|
# Use Magisk mirror, if possible.
|
||||||
|
if command -v magisk &> /dev/null; then
|
||||||
|
MIRROR="${'$'}(magisk --path)/.magisk/mirror"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mount -o bind ${'$'}MIRROR${'$'}base_path ${'$'}stock_path
|
||||||
|
|
||||||
|
# Kill the app to force it to restart the mounted APK in case it's currently running.
|
||||||
|
$KILL
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the [PLACEHOLDER] with the given [replacement].
|
||||||
|
*
|
||||||
|
* @param replacement The replacement to use.
|
||||||
|
* @return The replaced string.
|
||||||
|
*/
|
||||||
|
operator fun String.invoke(replacement: String) = replace(PLACEHOLDER, replacement)
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [Installation] of an apk file.
|
||||||
|
*
|
||||||
|
* @param apkFilePath The apk file path.
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
open class Installation internal constructor(
|
||||||
|
val apkFilePath: String,
|
||||||
|
)
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import app.revanced.library.installation.installer.Installer.Apk
|
||||||
|
import java.io.File
|
||||||
|
import java.util.logging.Logger
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [Installer] for installing and uninstalling [Apk] files.
|
||||||
|
*
|
||||||
|
* @param TInstallerResult The type of the result of the installation.
|
||||||
|
* @param TInstallation The type of the installation.
|
||||||
|
*/
|
||||||
|
abstract class Installer<TInstallerResult, TInstallation : Installation> internal constructor() {
|
||||||
|
/**
|
||||||
|
* The [Logger].
|
||||||
|
*/
|
||||||
|
protected val logger: Logger = Logger.getLogger(this::class.java.name)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs the [Apk] file.
|
||||||
|
*
|
||||||
|
* @param apk The [Apk] file.
|
||||||
|
*
|
||||||
|
* @return The result of the installation.
|
||||||
|
*/
|
||||||
|
abstract suspend fun install(apk: Apk): TInstallerResult
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstalls the package.
|
||||||
|
*
|
||||||
|
* @param packageName The package name.
|
||||||
|
*
|
||||||
|
* @return The result of the uninstallation.
|
||||||
|
*/
|
||||||
|
abstract suspend fun uninstall(packageName: String): TInstallerResult
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current installation or null if not installed.
|
||||||
|
*
|
||||||
|
* @param packageName The package name.
|
||||||
|
*
|
||||||
|
* @return The installation.
|
||||||
|
*/
|
||||||
|
abstract suspend fun getInstallation(packageName: String): TInstallation?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apk file for [Installer].
|
||||||
|
*
|
||||||
|
* @param file The [Apk] file.
|
||||||
|
* @param packageName The package name of the [Apk] file.
|
||||||
|
*/
|
||||||
|
class Apk(val file: File, val packageName: String? = null)
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [RootInstallation] of the apk file that is mounted to [installedApkFilePath] with root permissions.
|
||||||
|
*
|
||||||
|
* @param installedApkFilePath The installed apk file path or null if the apk is not installed.
|
||||||
|
* @param apkFilePath The mounting apk file path.
|
||||||
|
* @param mounted Whether the apk is mounted to [installedApkFilePath].
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
class RootInstallation internal constructor(
|
||||||
|
val installedApkFilePath: String?,
|
||||||
|
apkFilePath: String,
|
||||||
|
val mounted: Boolean,
|
||||||
|
) : Installation(apkFilePath)
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import app.revanced.library.installation.command.ShellCommandRunner
|
||||||
|
import app.revanced.library.installation.installer.Constants.CREATE_INSTALLATION_PATH
|
||||||
|
import app.revanced.library.installation.installer.Constants.DELETE
|
||||||
|
import app.revanced.library.installation.installer.Constants.EXISTS
|
||||||
|
import app.revanced.library.installation.installer.Constants.INSTALLED_APK_PATH
|
||||||
|
import app.revanced.library.installation.installer.Constants.INSTALL_MOUNT_SCRIPT
|
||||||
|
import app.revanced.library.installation.installer.Constants.KILL
|
||||||
|
import app.revanced.library.installation.installer.Constants.MOUNTED_APK_PATH
|
||||||
|
import app.revanced.library.installation.installer.Constants.MOUNT_APK
|
||||||
|
import app.revanced.library.installation.installer.Constants.MOUNT_GREP
|
||||||
|
import app.revanced.library.installation.installer.Constants.MOUNT_SCRIPT
|
||||||
|
import app.revanced.library.installation.installer.Constants.MOUNT_SCRIPT_PATH
|
||||||
|
import app.revanced.library.installation.installer.Constants.RESTART
|
||||||
|
import app.revanced.library.installation.installer.Constants.TMP_FILE_PATH
|
||||||
|
import app.revanced.library.installation.installer.Constants.UMOUNT
|
||||||
|
import app.revanced.library.installation.installer.Constants.invoke
|
||||||
|
import app.revanced.library.installation.installer.Installer.Apk
|
||||||
|
import app.revanced.library.installation.installer.RootInstaller.NoRootPermissionException
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [RootInstaller] for installing and uninstalling [Apk] files using root permissions by mounting.
|
||||||
|
*
|
||||||
|
* @param shellCommandRunnerSupplier A supplier for the [ShellCommandRunner] to use.
|
||||||
|
*
|
||||||
|
* @throws NoRootPermissionException If the device does not have root permission.
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
abstract class RootInstaller internal constructor(
|
||||||
|
shellCommandRunnerSupplier: (RootInstaller) -> ShellCommandRunner,
|
||||||
|
) : Installer<RootInstallerResult, RootInstallation>() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command runner used to run commands on the device.
|
||||||
|
*/
|
||||||
|
@Suppress("LeakingThis")
|
||||||
|
protected val shellCommandRunner = shellCommandRunnerSupplier(this)
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (!shellCommandRunner.hasRootPermission()) throw NoRootPermissionException()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs the given [apk] by mounting.
|
||||||
|
*
|
||||||
|
* @param apk The [Apk] to install.
|
||||||
|
*
|
||||||
|
* @throws PackageNameRequiredException If the [Apk] does not have a package name.
|
||||||
|
*/
|
||||||
|
override suspend fun install(apk: Apk): RootInstallerResult {
|
||||||
|
logger.info("Installing ${apk.packageName} by mounting")
|
||||||
|
|
||||||
|
val packageName = apk.packageName?.also { it.assertInstalled() } ?: throw PackageNameRequiredException()
|
||||||
|
|
||||||
|
// Setup files.
|
||||||
|
apk.file.move(TMP_FILE_PATH)
|
||||||
|
CREATE_INSTALLATION_PATH().waitFor()
|
||||||
|
MOUNT_APK(packageName)().waitFor()
|
||||||
|
|
||||||
|
// Install and run.
|
||||||
|
TMP_FILE_PATH.write(MOUNT_SCRIPT(packageName))
|
||||||
|
INSTALL_MOUNT_SCRIPT(packageName)().waitFor()
|
||||||
|
MOUNT_SCRIPT_PATH(packageName)().waitFor()
|
||||||
|
RESTART(packageName)()
|
||||||
|
|
||||||
|
DELETE(TMP_FILE_PATH)()
|
||||||
|
|
||||||
|
return RootInstallerResult.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun uninstall(packageName: String): RootInstallerResult {
|
||||||
|
logger.info("Uninstalling $packageName by unmounting")
|
||||||
|
|
||||||
|
UMOUNT(packageName)()
|
||||||
|
|
||||||
|
DELETE(MOUNTED_APK_PATH)(packageName)()
|
||||||
|
DELETE(MOUNT_SCRIPT_PATH)(packageName)()
|
||||||
|
DELETE(TMP_FILE_PATH)() // Remove residual.
|
||||||
|
|
||||||
|
KILL(packageName)()
|
||||||
|
|
||||||
|
return RootInstallerResult.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getInstallation(packageName: String): RootInstallation? {
|
||||||
|
val patchedApkPath = MOUNTED_APK_PATH(packageName)
|
||||||
|
|
||||||
|
val patchedApkExists = EXISTS(patchedApkPath)().exitCode == 0
|
||||||
|
if (patchedApkExists) return null
|
||||||
|
|
||||||
|
return RootInstallation(
|
||||||
|
INSTALLED_APK_PATH(packageName)().output.ifEmpty { null },
|
||||||
|
patchedApkPath,
|
||||||
|
MOUNT_GREP(patchedApkPath)().exitCode == 0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs a command on the device.
|
||||||
|
*/
|
||||||
|
protected operator fun String.invoke() = shellCommandRunner(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the given file to the given [targetFilePath].
|
||||||
|
*
|
||||||
|
* @param targetFilePath The target file path.
|
||||||
|
*/
|
||||||
|
protected fun File.move(targetFilePath: String) = shellCommandRunner.move(this, targetFilePath)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given [content] to the file.
|
||||||
|
*
|
||||||
|
* @param content The content of the file.
|
||||||
|
*/
|
||||||
|
protected fun String.write(content: String) = shellCommandRunner.write(content.byteInputStream(), this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the package is installed.
|
||||||
|
*
|
||||||
|
* @throws FailedToFindInstalledPackageException If the package is not installed.
|
||||||
|
*/
|
||||||
|
private fun String.assertInstalled() {
|
||||||
|
if (INSTALLED_APK_PATH(this)().output.isNotEmpty()) {
|
||||||
|
throw FailedToFindInstalledPackageException(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class FailedToFindInstalledPackageException internal constructor(packageName: String) :
|
||||||
|
Exception("Failed to find installed package \"$packageName\" because no activity was found")
|
||||||
|
|
||||||
|
internal class PackageNameRequiredException internal constructor() : Exception("Package name is required")
|
||||||
|
internal class NoRootPermissionException internal constructor() : Exception("No root permission")
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import app.revanced.library.installation.installer.Installer.Apk
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of installing or uninstalling an [Apk] with root permissions using [RootInstaller].
|
||||||
|
*
|
||||||
|
* @see RootInstaller
|
||||||
|
*/
|
||||||
|
enum class RootInstallerResult {
|
||||||
|
/**
|
||||||
|
* The result of installing an [Apk] successfully.
|
||||||
|
*/
|
||||||
|
SUCCESS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of installing an [Apk] unsuccessfully.
|
||||||
|
*/
|
||||||
|
FAILURE,
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package app.revanced.library.installation.installer
|
||||||
|
|
||||||
|
import se.vidstige.jadb.JadbConnection
|
||||||
|
import java.util.logging.Logger
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility functions for [Installer].
|
||||||
|
*
|
||||||
|
* @see Installer
|
||||||
|
*/
|
||||||
|
internal object Utils {
|
||||||
|
/**
|
||||||
|
* Gets the device with the given serial.
|
||||||
|
*
|
||||||
|
* @param deviceSerial The device serial. If null, the first connected device will be used.
|
||||||
|
* @param logger The logger.
|
||||||
|
* @return The device.
|
||||||
|
* @throws DeviceNotFoundException If no device with the given serial is found.
|
||||||
|
*/
|
||||||
|
internal fun getDevice(
|
||||||
|
deviceSerial: String? = null,
|
||||||
|
logger: Logger,
|
||||||
|
) = with(JadbConnection().devices) {
|
||||||
|
if (isEmpty()) throw DeviceNotFoundException()
|
||||||
|
|
||||||
|
deviceSerial?.let {
|
||||||
|
firstOrNull { it.serial == deviceSerial } ?: throw DeviceNotFoundException(
|
||||||
|
deviceSerial,
|
||||||
|
)
|
||||||
|
} ?: first().also {
|
||||||
|
logger.warning("No device serial supplied. Using device with serial ${it.serial}")
|
||||||
|
}
|
||||||
|
}!!
|
||||||
|
|
||||||
|
class DeviceNotFoundException internal constructor(deviceSerial: String? = null) : Exception(
|
||||||
|
deviceSerial?.let {
|
||||||
|
"The device with the ADB device serial \"$deviceSerial\" can not be found"
|
||||||
|
} ?: "No ADB device found",
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -5,15 +5,17 @@ import java.util.logging.Level
|
|||||||
import java.util.logging.LogRecord
|
import java.util.logging.LogRecord
|
||||||
import java.util.logging.SimpleFormatter
|
import java.util.logging.SimpleFormatter
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate", "unused")
|
||||||
object Logger {
|
object Logger {
|
||||||
/**
|
/**
|
||||||
* Rules for allowed loggers.
|
* Rules for allowed loggers.
|
||||||
*/
|
*/
|
||||||
private val allowedLoggersRules =
|
private val allowedLoggersRules =
|
||||||
arrayOf<String.() -> Boolean>(
|
arrayOf<String.() -> Boolean>(
|
||||||
{ startsWith("app.revanced") }, // ReVanced loggers.
|
// ReVanced loggers.
|
||||||
{ this == "" }, // Logs warnings when compiling resources (Logger in class brut.util.OS).
|
{ startsWith("app.revanced") },
|
||||||
|
// Logs warnings when compiling resources (Logger in class brut.util.OS).
|
||||||
|
{ this == "" },
|
||||||
)
|
)
|
||||||
|
|
||||||
private val rootLogger = java.util.logging.Logger.getLogger("")
|
private val rootLogger = java.util.logging.Logger.getLogger("")
|
||||||
@@ -6,36 +6,29 @@ import app.revanced.patcher.patch.BytecodePatch
|
|||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
|
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
|
||||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||||
import org.junit.jupiter.api.MethodOrderer
|
import kotlin.test.Test
|
||||||
import org.junit.jupiter.api.Order
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.junit.jupiter.api.TestMethodOrder
|
|
||||||
|
|
||||||
@TestMethodOrder(MethodOrderer.OrderAnnotation::class)
|
class PatchOptionsTest {
|
||||||
internal object PatchOptionsTest {
|
|
||||||
private var patches = setOf(PatchOptionsTestPatch)
|
private var patches = setOf(PatchOptionsTestPatch)
|
||||||
|
|
||||||
@Test
|
private val serializedJson =
|
||||||
@Order(1)
|
"[{\"patchName\":\"PatchOptionsTestPatch\",\"options\":[{\"key\":\"key1\",\"value\":null},{\"key\":\"key2\"," +
|
||||||
fun serializeTest() {
|
"\"value\":true}]}]"
|
||||||
assert(SERIALIZED_JSON == Options.serialize(patches))
|
|
||||||
}
|
private val changedJson =
|
||||||
|
"[{\"patchName\":\"PatchOptionsTestPatch\",\"options\":[{\"key\":\"key1\",\"value\":\"test\"},{\"key\":\"key2" +
|
||||||
|
"\",\"value\":false}]}]"
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(2)
|
fun `serializes and deserializes`() {
|
||||||
fun loadOptionsTest() {
|
assert(serializedJson == Options.serialize(patches))
|
||||||
patches.setOptions(CHANGED_JSON)
|
|
||||||
|
patches.setOptions(changedJson)
|
||||||
|
|
||||||
assert(PatchOptionsTestPatch.option1 == "test")
|
assert(PatchOptionsTestPatch.option1 == "test")
|
||||||
assert(PatchOptionsTestPatch.option2 == false)
|
assert(PatchOptionsTestPatch.option2 == false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val SERIALIZED_JSON =
|
|
||||||
"[{\"patchName\":\"PatchOptionsTestPatch\",\"options\":[{\"key\":\"key1\",\"value\":null},{\"key\":\"key2\",\"value\":true}]}]"
|
|
||||||
|
|
||||||
private const val CHANGED_JSON =
|
|
||||||
"[{\"patchName\":\"PatchOptionsTestPatch\",\"options\":[{\"key\":\"key1\",\"value\":\"test\"},{\"key\":\"key2\",\"value\":false}]}]"
|
|
||||||
|
|
||||||
@Patch("PatchOptionsTestPatch")
|
@Patch("PatchOptionsTestPatch")
|
||||||
object PatchOptionsTestPatch : BytecodePatch(emptySet()) {
|
object PatchOptionsTestPatch : BytecodePatch(emptySet()) {
|
||||||
var option1 by stringPatchOption("key1", null, null, "title1", "description1")
|
var option1 by stringPatchOption("key1", null, null, "title1", "description1")
|
||||||
@@ -7,12 +7,12 @@ import app.revanced.patcher.patch.Patch
|
|||||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
|
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
|
||||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.intArrayPatchOption
|
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.intArrayPatchOption
|
||||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal object PatchUtilsTest {
|
internal class PatchUtilsTest {
|
||||||
private val patches =
|
private val patches =
|
||||||
arrayOf(
|
arrayOf(
|
||||||
newPatch("some.package", setOf("a")) { stringPatchOption("string", "value") },
|
newPatch("some.package", setOf("a")) { stringPatchOption("string", "value") },
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
package app.revanced.library.adb
|
|
||||||
|
|
||||||
import app.revanced.library.adb.AdbManager.Apk
|
|
||||||
import app.revanced.library.adb.Constants.CREATE_DIR
|
|
||||||
import app.revanced.library.adb.Constants.DELETE
|
|
||||||
import app.revanced.library.adb.Constants.GET_INSTALLED_PATH
|
|
||||||
import app.revanced.library.adb.Constants.INSTALLATION_PATH
|
|
||||||
import app.revanced.library.adb.Constants.INSTALL_MOUNT_SCRIPT
|
|
||||||
import app.revanced.library.adb.Constants.INSTALL_PATCHED_APK
|
|
||||||
import app.revanced.library.adb.Constants.KILL
|
|
||||||
import app.revanced.library.adb.Constants.MOUNT_SCRIPT
|
|
||||||
import app.revanced.library.adb.Constants.MOUNT_SCRIPT_PATH
|
|
||||||
import app.revanced.library.adb.Constants.PATCHED_APK_PATH
|
|
||||||
import app.revanced.library.adb.Constants.PLACEHOLDER
|
|
||||||
import app.revanced.library.adb.Constants.RESTART
|
|
||||||
import app.revanced.library.adb.Constants.TMP_PATH
|
|
||||||
import app.revanced.library.adb.Constants.UMOUNT
|
|
||||||
import se.vidstige.jadb.JadbConnection
|
|
||||||
import se.vidstige.jadb.JadbDevice
|
|
||||||
import se.vidstige.jadb.managers.Package
|
|
||||||
import se.vidstige.jadb.managers.PackageManager
|
|
||||||
import java.io.File
|
|
||||||
import java.util.logging.Logger
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adb manager. Used to install and uninstall [Apk] files.
|
|
||||||
*
|
|
||||||
* @param deviceSerial The serial of the device. If null, the first connected device will be used.
|
|
||||||
*/
|
|
||||||
sealed class AdbManager private constructor(deviceSerial: String?) {
|
|
||||||
protected val logger: Logger = Logger.getLogger(AdbManager::class.java.name)
|
|
||||||
|
|
||||||
protected val device =
|
|
||||||
with(JadbConnection().devices) {
|
|
||||||
if (isEmpty()) throw DeviceNotFoundException()
|
|
||||||
|
|
||||||
deviceSerial?.let {
|
|
||||||
firstOrNull { it.serial == deviceSerial } ?: throw DeviceNotFoundException(deviceSerial)
|
|
||||||
} ?: first().also {
|
|
||||||
logger.warning("No device serial supplied. Using device with serial ${it.serial}")
|
|
||||||
}
|
|
||||||
}!!
|
|
||||||
|
|
||||||
init {
|
|
||||||
logger.fine("Connected to ${device.serial}")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Installs the [Apk] file.
|
|
||||||
*
|
|
||||||
* @param apk The [Apk] file.
|
|
||||||
*/
|
|
||||||
open fun install(apk: Apk) {
|
|
||||||
logger.info("Finished installing ${apk.file.name}")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uninstalls the package.
|
|
||||||
*
|
|
||||||
* @param packageName The package name.
|
|
||||||
*/
|
|
||||||
open fun uninstall(packageName: String) {
|
|
||||||
logger.info("Finished uninstalling $packageName")
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Gets an [AdbManager] for the supplied device serial.
|
|
||||||
*
|
|
||||||
* @param deviceSerial The device serial. If null, the first connected device will be used.
|
|
||||||
* @param root Whether to use root or not.
|
|
||||||
* @return The [AdbManager].
|
|
||||||
* @throws DeviceNotFoundException If the device can not be found.
|
|
||||||
*/
|
|
||||||
fun getAdbManager(
|
|
||||||
deviceSerial: String? = null,
|
|
||||||
root: Boolean = false,
|
|
||||||
): AdbManager = if (root) RootAdbManager(deviceSerial) else UserAdbManager(deviceSerial)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adb manager for rooted devices.
|
|
||||||
*
|
|
||||||
* @param deviceSerial The device serial. If null, the first connected device will be used.
|
|
||||||
*/
|
|
||||||
class RootAdbManager internal constructor(deviceSerial: String?) : AdbManager(deviceSerial) {
|
|
||||||
init {
|
|
||||||
if (!device.hasSu()) throw IllegalArgumentException("Root required on ${device.serial}. Task failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun install(apk: Apk) {
|
|
||||||
logger.info("Installing by mounting")
|
|
||||||
|
|
||||||
val packageName = apk.packageName ?: throw PackageNameRequiredException()
|
|
||||||
|
|
||||||
device.run(GET_INSTALLED_PATH, packageName).inputStream.bufferedReader().readLine().let { line ->
|
|
||||||
if (line != null) return@let
|
|
||||||
throw throw FailedToFindInstalledPackageException(packageName)
|
|
||||||
}
|
|
||||||
|
|
||||||
device.push(apk.file, TMP_PATH)
|
|
||||||
|
|
||||||
device.run("$CREATE_DIR $INSTALLATION_PATH").waitFor()
|
|
||||||
device.run(INSTALL_PATCHED_APK, packageName).waitFor()
|
|
||||||
|
|
||||||
device.createFile(TMP_PATH, MOUNT_SCRIPT.applyReplacement(packageName))
|
|
||||||
|
|
||||||
device.run(INSTALL_MOUNT_SCRIPT, packageName).waitFor()
|
|
||||||
device.run(MOUNT_SCRIPT_PATH, packageName).waitFor()
|
|
||||||
device.run(RESTART, packageName)
|
|
||||||
device.run(DELETE, TMP_PATH)
|
|
||||||
|
|
||||||
super.install(apk)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun uninstall(packageName: String) {
|
|
||||||
logger.info("Uninstalling $packageName by unmounting")
|
|
||||||
|
|
||||||
device.run(UMOUNT, packageName)
|
|
||||||
device.run(DELETE.applyReplacement(PATCHED_APK_PATH), packageName)
|
|
||||||
device.run(DELETE, MOUNT_SCRIPT_PATH.applyReplacement(packageName))
|
|
||||||
device.run(DELETE, TMP_PATH)
|
|
||||||
device.run(KILL, packageName)
|
|
||||||
|
|
||||||
super.uninstall(packageName)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object Utils {
|
|
||||||
private fun JadbDevice.run(
|
|
||||||
command: String,
|
|
||||||
with: String,
|
|
||||||
) = run(command.applyReplacement(with))
|
|
||||||
|
|
||||||
private fun String.applyReplacement(with: String) = replace(PLACEHOLDER, with)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adb manager for non-rooted devices.
|
|
||||||
*
|
|
||||||
* @param deviceSerial The device serial. If null, the first connected device will be used.
|
|
||||||
*/
|
|
||||||
class UserAdbManager internal constructor(deviceSerial: String?) : AdbManager(deviceSerial) {
|
|
||||||
private val packageManager = PackageManager(device)
|
|
||||||
|
|
||||||
override fun install(apk: Apk) {
|
|
||||||
logger.info("Installing ${apk.file.name}")
|
|
||||||
|
|
||||||
PackageManager(device).install(apk.file)
|
|
||||||
|
|
||||||
super.install(apk)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun uninstall(packageName: String) {
|
|
||||||
logger.info("Uninstalling $packageName")
|
|
||||||
|
|
||||||
packageManager.uninstall(Package(packageName))
|
|
||||||
|
|
||||||
super.uninstall(packageName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apk file for [AdbManager].
|
|
||||||
*
|
|
||||||
* @param file The [Apk] file.
|
|
||||||
* @param packageName The package name of the [Apk] file.
|
|
||||||
*/
|
|
||||||
class Apk(val file: File, val packageName: String? = null)
|
|
||||||
|
|
||||||
class DeviceNotFoundException internal constructor(deviceSerial: String? = null) :
|
|
||||||
Exception(
|
|
||||||
deviceSerial?.let {
|
|
||||||
"The device with the ADB device serial \"$deviceSerial\" can not be found"
|
|
||||||
} ?: "No ADB device found",
|
|
||||||
)
|
|
||||||
|
|
||||||
class FailedToFindInstalledPackageException internal constructor(packageName: String) :
|
|
||||||
Exception("Failed to find installed package \"$packageName\" because no activity was found")
|
|
||||||
|
|
||||||
class PackageNameRequiredException internal constructor() :
|
|
||||||
Exception("Package name is required")
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package app.revanced.library.adb
|
|
||||||
|
|
||||||
import se.vidstige.jadb.JadbDevice
|
|
||||||
import se.vidstige.jadb.RemoteFile
|
|
||||||
import se.vidstige.jadb.ShellProcessBuilder
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
internal fun JadbDevice.buildCommand(
|
|
||||||
command: String,
|
|
||||||
su: Boolean = true,
|
|
||||||
): ShellProcessBuilder {
|
|
||||||
if (su) return shellProcessBuilder("su -c \'$command\'")
|
|
||||||
|
|
||||||
val args = command.split(" ") as ArrayList<String>
|
|
||||||
val cmd = args.removeFirst()
|
|
||||||
|
|
||||||
return shellProcessBuilder(cmd, *args.toTypedArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun JadbDevice.run(
|
|
||||||
command: String,
|
|
||||||
su: Boolean = true,
|
|
||||||
) = this.buildCommand(command, su).start()
|
|
||||||
|
|
||||||
internal fun JadbDevice.hasSu() = this.run("whoami", true).waitFor() == 0
|
|
||||||
|
|
||||||
internal fun JadbDevice.push(
|
|
||||||
file: File,
|
|
||||||
targetFilePath: String,
|
|
||||||
) = push(file, RemoteFile(targetFilePath))
|
|
||||||
|
|
||||||
internal fun JadbDevice.createFile(
|
|
||||||
targetFile: String,
|
|
||||||
content: String,
|
|
||||||
) = push(content.byteInputStream(), System.currentTimeMillis(), 644, RemoteFile(targetFile))
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package app.revanced.library.adb
|
|
||||||
|
|
||||||
internal object Constants {
|
|
||||||
internal const val PLACEHOLDER = "PLACEHOLDER"
|
|
||||||
|
|
||||||
internal const val TMP_PATH = "/data/local/tmp/revanced.tmp"
|
|
||||||
internal const val INSTALLATION_PATH = "/data/adb/revanced/"
|
|
||||||
internal const val PATCHED_APK_PATH = "$INSTALLATION_PATH$PLACEHOLDER.apk"
|
|
||||||
internal const val MOUNT_SCRIPT_PATH = "/data/adb/service.d/mount_revanced_$PLACEHOLDER.sh"
|
|
||||||
|
|
||||||
internal const val DELETE = "rm -rf $PLACEHOLDER"
|
|
||||||
internal const val CREATE_DIR = "mkdir -p"
|
|
||||||
internal const val RESTART = "am start -S $PLACEHOLDER"
|
|
||||||
internal const val KILL = "am force-stop $PLACEHOLDER"
|
|
||||||
internal const val GET_INSTALLED_PATH = "pm path $PLACEHOLDER"
|
|
||||||
|
|
||||||
internal const val INSTALL_PATCHED_APK =
|
|
||||||
"base_path=\"$PATCHED_APK_PATH\" && " +
|
|
||||||
"mv $TMP_PATH ${'$'}base_path && " +
|
|
||||||
"chmod 644 ${'$'}base_path && " +
|
|
||||||
"chown system:system ${'$'}base_path && " +
|
|
||||||
"chcon u:object_r:apk_data_file:s0 ${'$'}base_path"
|
|
||||||
|
|
||||||
internal const val UMOUNT =
|
|
||||||
"grep $PLACEHOLDER /proc/mounts | while read -r line; do echo ${'$'}line | cut -d ' ' -f 2 | sed 's/apk.*/apk/' | xargs -r umount -l; done"
|
|
||||||
|
|
||||||
internal const val INSTALL_MOUNT_SCRIPT = "mv $TMP_PATH $MOUNT_SCRIPT_PATH && chmod +x $MOUNT_SCRIPT_PATH"
|
|
||||||
|
|
||||||
internal val MOUNT_SCRIPT =
|
|
||||||
"""
|
|
||||||
#!/system/bin/sh
|
|
||||||
|
|
||||||
# Use Magisk mirror, if possible.
|
|
||||||
if command -v magisk &> /dev/null; then
|
|
||||||
MIRROR="${'$'}(magisk --path)/.magisk/mirror"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Wait for the system to boot.
|
|
||||||
until [ "$( getprop sys.boot_completed )" = 1 ]; do sleep 3; done
|
|
||||||
until [ -d "/sdcard/Android" ]; do sleep 1; done
|
|
||||||
|
|
||||||
# Unmount any existing mount as a safety measure.
|
|
||||||
$UMOUNT
|
|
||||||
|
|
||||||
base_path="$PATCHED_APK_PATH"
|
|
||||||
stock_path=$( pm path $PLACEHOLDER | grep base | sed 's/package://g' )
|
|
||||||
|
|
||||||
chcon u:object_r:apk_data_file:s0 ${'$'}base_path
|
|
||||||
mount -o bind ${'$'}MIRROR${'$'}base_path ${'$'}stock_path
|
|
||||||
|
|
||||||
# Kill the app to force it to restart the mounted APK in case it's currently running.
|
|
||||||
$KILL
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user