From d8cc154aebb2c3af615cc79d175f2f2fb8cbb809 Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 00:51:49 +0200 Subject: [PATCH 01/12] Test New Root Method --- .../core/downloader/VancedDownloadService.kt | 7 +- .../installer/RootSplitInstallerService.kt | 150 ++++++++++++++++-- .../com/vanced/manager/ui/MainActivity.kt | 2 - .../manager/ui/dialogs/DialogContainer.kt | 22 --- .../ui/fragments/ManagerChangelogFragment.kt | 2 +- .../com/vanced/manager/utils/InternetTools.kt | 2 +- .../com/vanced/manager/utils/PackageHelper.kt | 8 + 7 files changed, 152 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt index 537e29da..9369633f 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt @@ -61,6 +61,8 @@ class VancedDownloadService: Service() { when (type) { "arch" -> "$installUrl/apks/v$vancedVer/$variant/Arch/split_config.$arch.apk" "theme" -> "$installUrl/apks/v$vancedVer/$variant/Theme/$theme.apk" + "stock" -> "$installUrl/apks/v$vancedVer/$variant/Theme/stock.apk" + "dpi" -> "$installUrl/apks/v$vancedVer/$variant/Theme/dpi.apk" "lang" -> "$installUrl/apks/v$vancedVer/$variant/Language/split_config.${lang?.get(count)}.apk" else -> throw NotImplementedError("This type of APK is NOT valid. What the hell did you even do?") } @@ -80,7 +82,9 @@ class VancedDownloadService: Service() { override fun onDownloadComplete() { when (type) { "arch" -> downloadSplits("theme") - "theme" -> downloadSplits("lang") + "theme" -> downloadSplits("stock") + "stock" -> downloadSplits("dpi") + "dpi" -> downloadSplits("lang") "lang" -> { count++ if (count < lang?.count()!!) @@ -88,6 +92,7 @@ class VancedDownloadService: Service() { else prepareInstall(variant!!) } + } } diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index 0f91b214..cfc35208 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -2,6 +2,7 @@ package com.vanced.manager.core.installer import android.app.Service import android.content.Intent +import android.content.pm.PackageInfo import android.os.Build import android.os.IBinder import android.util.Log @@ -12,26 +13,56 @@ import com.topjohnwu.superuser.Shell import com.vanced.manager.ui.fragments.HomeFragment import com.vanced.manager.utils.AppUtils.sendFailure import com.vanced.manager.utils.FileInfo +import com.vanced.manager.utils.InternetTools.getJsonInt +import com.vanced.manager.utils.PackageHelper import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import java.io.File import java.text.SimpleDateFormat import java.util.* import java.util.regex.Pattern import kotlin.collections.ArrayList + class RootSplitInstallerService: Service() { + private var vancedVersionCode: Int = 0 + val yPkg = "com.google.android.youtube" + private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(this) } + suspend fun getVer() + { + vancedVersionCode = getJsonInt("vanced.json","versionCode", application) + } + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + + runBlocking { getVer() } + Shell.getShell { CoroutineScope(Dispatchers.IO).launch { val apkFilesPath = getExternalFilesDir("apks")?.path val fileInfoList = apkFilesPath?.let { it1 -> getFileInfoList(it1) } if (fileInfoList != null) { - installSplitApkFiles(fileInfoList) + var modApk: FileInfo? = null + for (fil in fileInfoList) + { + if(fil.name == "dark.apk" || fil.name == "black.apk") + { + modApk = fil + } + } + if (modApk != null) { + overwriteBase(modApk, fileInfoList,vancedVersionCode) + } + else + { + throw RuntimeException("Missing dark.apk or black.apk") + } + //installSplitApkFiles(fileInfoList) } } @@ -52,21 +83,24 @@ class RootSplitInstallerService: Service() { sessionId = Integer.parseInt(sessionIdMatcher.group(1)!!) } apkFiles.forEach { apkFile -> - Log.d("AppLog", "installing APK : ${apkFile.name} ${apkFile.fileSize} ") - val command = arrayOf("su", "-c", "pm", "install-write", "-S", "${apkFile.fileSize}", "$sessionId", apkFile.name) - val process: Process = Runtime.getRuntime().exec(command) - val inputPipe = apkFile.getInputStream() - try { - process.outputStream.use { outputStream -> inputPipe.copyTo(outputStream) } - } catch (e: Exception) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - process.destroyForcibly() - else - process.destroy() + if(apkFile.name != "black.apk" && apkFile.name != "dark.apk") + { + Log.d("AppLog", "installing APK : ${apkFile.name} ${apkFile.fileSize} ") + val command = arrayOf("su", "-c", "pm", "install-write", "-S", "${apkFile.fileSize}", "$sessionId", apkFile.name) + val process: Process = Runtime.getRuntime().exec(command) + val inputPipe = apkFile.getInputStream() + try { + process.outputStream.use { outputStream -> inputPipe.copyTo(outputStream) } + } catch (e: Exception) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + process.destroyForcibly() + else + process.destroy() - throw RuntimeException(e) + throw RuntimeException(e) + } + process.waitFor() } - process.waitFor() } Log.d("AppLog", "committing...") val installResult = Shell.su("pm install-commit $sessionId").exec() @@ -128,4 +162,92 @@ class RootSplitInstallerService: Service() { override fun onBind(intent: Intent?): IBinder? { return null } + + + + private fun overwriteBase(apkFile: FileInfo, baseApkFiles: ArrayList, versionCode: Int) + { + checkVersion(versionCode,baseApkFiles) + var path = getVPath() + apkFile.file?.absolutePath?.let { + moveAPK(it, path) + chConV(path) + } + + + } + + private fun checkVersion(versionCode: Int, baseApkFiles: ArrayList) { + val path = getVPath() + if(path.contains("/data/app/")) + { + when(compareVersion(getPkgVerCode(yPkg),versionCode)) + { + 1 -> fixHigherVer(baseApkFiles) + -1 -> fixLowerVer(baseApkFiles) + } + } + else + { + fixNoInstall(baseApkFiles) + } + } + + + + private fun getPkgVerCode(pkg: String): Int { + val pm = packageManager + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) + pm.getPackageInfo(pkg, 0).longVersionCode.and(0xFFFFFFFF).toInt() + else + pm.getPackageInfo(pkg, 0).versionCode + + } + + private fun getPkgInfo(pkg: String): PackageInfo + { + val m = packageManager + val p: PackageInfo = m.getPackageInfo(pkg, 0) + return p + } + + private fun compareVersion(pkgVerCode: Int, versionCode: Int): Int + { + return if(pkgVerCode > versionCode) + 1 + else if (pkgVerCode < versionCode) + -1 + else + 0 + } + + private fun fixHigherVer(apkFiles: ArrayList) { + + PackageHelper.uninstallApk(yPkg, applicationContext) + installSplitApkFiles(apkFiles) + } + + private fun fixLowerVer(apkFiles: ArrayList) { + installSplitApkFiles(apkFiles) + } + + private fun fixNoInstall(baseApkFiles: ArrayList) { + installSplitApkFiles(baseApkFiles) + } + + private fun chConV(path: String) { + Shell.su("chcon -R u:object_r:system_file:s0 $path").exec() + } + + private fun moveAPK(apkFile: String, path: String) { + Shell.su("cp $apkFile $path").exec() + Shell.su("chmod 644 $path").exec() + + } + + private fun getVPath(): String { + val p = getPkgInfo(yPkg) + return p.applicationInfo.sourceDir + } + } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 50663408..40161b1f 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -124,8 +124,6 @@ class MainActivity : AppCompatActivity() { } !prefs.getBoolean("statement", true) -> DialogContainer.statementFalse(this) variant == "root" -> { - if (showRootDialog) - DialogContainer.showRootDialog(this) if (PackageHelper.getPackageVersionName( "com.google.android.youtube", diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/DialogContainer.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/DialogContainer.kt index 01b0d370..00a0afb1 100644 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/DialogContainer.kt +++ b/app/src/main/java/com/vanced/manager/ui/dialogs/DialogContainer.kt @@ -73,28 +73,6 @@ object DialogContainer { } } - fun showRootDialog(activity: Activity) { - MaterialAlertDialogBuilder(activity).apply { - setTitle(activity.getString(R.string.hold_on)) - setMessage(activity.getString(R.string.disable_signature)) - setNeutralButton(activity.getString(R.string.button_dismiss)) { dialog, _ -> - dialog.dismiss() - } - setPositiveButton(activity.getString(R.string.guide)) { _, _ -> - openUrl( - "https://lmgtfy.com/?q=andnixsh+apk+verification+disable", - R.color.Twitter, - activity - ) - } - setCancelable(false) - create() - show() - } - PreferenceManager.getDefaultSharedPreferences(activity).edit() - .putBoolean("show_root_dialog", false).apply() - } - //Easter Egg fun statementFalse(context: Context) { MaterialAlertDialogBuilder(context).apply { diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/ManagerChangelogFragment.kt b/app/src/main/java/com/vanced/manager/ui/fragments/ManagerChangelogFragment.kt index 644c8d7c..083c4e7a 100644 --- a/app/src/main/java/com/vanced/manager/ui/fragments/ManagerChangelogFragment.kt +++ b/app/src/main/java/com/vanced/manager/ui/fragments/ManagerChangelogFragment.kt @@ -24,7 +24,7 @@ class ManagerChangelogFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) CoroutineScope(Dispatchers.Main).launch { - val changelog = InternetTools.getObjectFromJson("https://x1nto.github.io/VancedFiles/manager.json", "changelog") + val changelog = InternetTools.getObjectFromJson("https://ytvanced.github.io/VancedBackend/manager.json", "changelog") view.findViewById(R.id.manager_changelog).text = changelog } } diff --git a/app/src/main/java/com/vanced/manager/utils/InternetTools.kt b/app/src/main/java/com/vanced/manager/utils/InternetTools.kt index 81e2c76a..36b24d66 100644 --- a/app/src/main/java/com/vanced/manager/utils/InternetTools.kt +++ b/app/src/main/java/com/vanced/manager/utils/InternetTools.kt @@ -67,7 +67,7 @@ object InternetTools { suspend fun isUpdateAvailable(): Boolean { val result = try { - JsonHelper.getJson("https://x1nto.github.io/VancedFiles/manager.json").int("versionCode") ?: 0 + JsonHelper.getJson("https://ytvanced.github.io/VancedBackend/manager.json").int("versionCode") ?: 0 } catch (e: Exception) { 0 } diff --git a/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt b/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt index d6ec1f3c..dbf6f627 100644 --- a/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt +++ b/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt @@ -2,6 +2,7 @@ package com.vanced.manager.utils import android.app.Activity import android.app.PendingIntent +import android.content.Context import android.content.Intent import android.content.pm.PackageManager import com.vanced.manager.core.installer.AppUninstallerService @@ -30,4 +31,11 @@ object PackageHelper { val pendingIntent = PendingIntent.getService(activity.applicationContext, 0, callbackIntent, 0) activity.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender) } + + fun uninstallApk(pkg: String, applicationContext: Context) { + val callbackIntent = Intent(applicationContext, AppUninstallerService::class.java) + callbackIntent.putExtra("pkg", pkg) + val pendingIntent = PendingIntent.getService(applicationContext, 0, callbackIntent, 0) + applicationContext.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender) + } } \ No newline at end of file From 412ff6aebb2fcea94ee71d68ea694b0571da1ad5 Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 01:57:22 +0200 Subject: [PATCH 02/12] Test New Root Method And Step LogCode --- .../installer/RootSplitInstallerService.kt | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index cfc35208..38d84030 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -39,24 +39,31 @@ class RootSplitInstallerService: Service() { } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - + logDebug("RunBlockBefore"); runBlocking { getVer() } - + logDebug("RunBlockAfter"); Shell.getShell { CoroutineScope(Dispatchers.IO).launch { val apkFilesPath = getExternalFilesDir("apks")?.path val fileInfoList = apkFilesPath?.let { it1 -> getFileInfoList(it1) } + logDebug("GotFileInfoList") if (fileInfoList != null) { var modApk: FileInfo? = null + logDebug("FileInfoListIsNotEmpty") for (fil in fileInfoList) { + logDebug(fil.name) if(fil.name == "dark.apk" || fil.name == "black.apk") { + logDebug("found " + fil.name) modApk = fil } } + logDebug("Before modApk Check") if (modApk != null) { + logDebug("modApkCheck Passed") overwriteBase(modApk, fileInfoList,vancedVersionCode) + logDebug("Finished Patching") } else { @@ -71,6 +78,10 @@ class RootSplitInstallerService: Service() { return START_NOT_STICKY } + private fun logDebug(s: String) { + Log.d("ZLog", s) + } + @WorkerThread private fun installSplitApkFiles(apkFiles: ArrayList) { var sessionId: Int? @@ -167,11 +178,18 @@ class RootSplitInstallerService: Service() { private fun overwriteBase(apkFile: FileInfo, baseApkFiles: ArrayList, versionCode: Int) { + logDebug("check version") checkVersion(versionCode,baseApkFiles) + logDebug("Version Check Done, next getting apk path") var path = getVPath() - apkFile.file?.absolutePath?.let { - moveAPK(it, path) + logDebug("Path: $path") + apkFile.file?.let { + var apath = it.absolutePath + logDebug("Moving $apath to: $path") + moveAPK(apath, path) + logDebug("Move done setting chConv $path") chConV(path) + logDebug("Done with chConv $path") } @@ -179,16 +197,19 @@ class RootSplitInstallerService: Service() { private fun checkVersion(versionCode: Int, baseApkFiles: ArrayList) { val path = getVPath() + logDebug("checking if path is in /data/app") if(path.contains("/data/app/")) { + logDebug("Path is in /data/app: $path" ) when(compareVersion(getPkgVerCode(yPkg),versionCode)) { - 1 -> fixHigherVer(baseApkFiles) - -1 -> fixLowerVer(baseApkFiles) + 1 -> {fixHigherVer(baseApkFiles);logDebug("higher version uninstalling then installing base + patched");} + -1 -> {fixLowerVer(baseApkFiles);logDebug("Lower Version installing base + patched");} } } else { + logDebug("No install in /data/app/ now installing") fixNoInstall(baseApkFiles) } } From d0bdaef772893bec55a66a85e207cfdd452f9e58 Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 02:24:43 +0200 Subject: [PATCH 03/12] Version Bump and Target 29 --- app/build.gradle | 10 +++++----- app/src/main/java/com/vanced/manager/core/App.kt | 6 +++--- .../com/vanced/manager/ui/viewmodels/HomeViewModel.kt | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5ad08724..bf003d85 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,15 +7,15 @@ apply plugin: 'com.google.firebase.firebase-perf' apply plugin: 'com.google.firebase.crashlytics' android { - compileSdkVersion 30 - buildToolsVersion "30.0.1" + compileSdkVersion 29 + buildToolsVersion "29.0.3" defaultConfig { applicationId "com.vanced.manager" minSdkVersion 21 - targetSdkVersion 30 - versionCode 12 - versionName "1.2.0 (Niko)" + targetSdkVersion 29 + versionCode 13 + versionName "1.2.1 (Niko)" vectorDrawables.useSupportLibrary = true } diff --git a/app/src/main/java/com/vanced/manager/core/App.kt b/app/src/main/java/com/vanced/manager/core/App.kt index 38450be3..57c308c0 100644 --- a/app/src/main/java/com/vanced/manager/core/App.kt +++ b/app/src/main/java/com/vanced/manager/core/App.kt @@ -14,15 +14,15 @@ class App: Application() { super.onCreate() PRDownloader.initialize(this) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + //if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { Crowdin.init(this, CrowdinConfig.Builder() .withDistributionHash("36c51aed3180a4f43073d28j4s6") .withNetworkType(NetworkType.WIFI) .build() ) - } - + //} + } /* diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt index d8884e03..41f41cfc 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt @@ -65,7 +65,7 @@ open class HomeViewModel(application: Application): AndroidViewModel(application fun fetchData() { CoroutineScope(Dispatchers.IO).launch { fetching.set(true) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + //if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) Crowdin.forceUpdate(getApplication()) vancedVersion.set(getJsonString("vanced.json", "version", getApplication())) microgVersion.set(getJsonString("microg.json", "version", getApplication())) From 042a6a72a155b1c3d796b04fa3a912bebe3f5719 Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 02:48:48 +0200 Subject: [PATCH 04/12] remove dupe and more detailed throw --- .../manager/core/downloader/VancedDownloadService.kt | 7 ++++--- .../manager/core/installer/RootSplitInstallerService.kt | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt index 9369633f..3b5d2d92 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt @@ -57,12 +57,13 @@ class VancedDownloadService: Service() { Build.SUPPORTED_ABIS.contains("arm64-v8a") -> "arm64_v8a" else -> "armeabi_v7a" } + val themePath = "$installUrl/apks/v$vancedVer/$variant/Theme/" val url = when (type) { "arch" -> "$installUrl/apks/v$vancedVer/$variant/Arch/split_config.$arch.apk" - "theme" -> "$installUrl/apks/v$vancedVer/$variant/Theme/$theme.apk" - "stock" -> "$installUrl/apks/v$vancedVer/$variant/Theme/stock.apk" - "dpi" -> "$installUrl/apks/v$vancedVer/$variant/Theme/dpi.apk" + "theme" -> "$themePath$theme.apk" + "stock" -> "$themePath/stock.apk" + "dpi" -> "$themePath/dpi.apk" "lang" -> "$installUrl/apks/v$vancedVer/$variant/Language/split_config.${lang?.get(count)}.apk" else -> throw NotImplementedError("This type of APK is NOT valid. What the hell did you even do?") } diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index 38d84030..25272a80 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -67,7 +67,7 @@ class RootSplitInstallerService: Service() { } else { - throw RuntimeException("Missing dark.apk or black.apk") + throw IllegalArgumentException("modApk Is Null Cause Missing (dark.apk/black.apk) In apks Folder") } //installSplitApkFiles(fileInfoList) } From f2cb0e43071a55b41a3568e4737cb99eeb0cd465 Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 06:37:34 +0200 Subject: [PATCH 05/12] Fix Bug With Install when youtube is not pre installed in system and added code check, and returns error message on install if there is one --- .../installer/RootSplitInstallerService.kt | 219 ++++++++++++------ .../com/vanced/manager/utils/PackageHelper.kt | 13 +- 2 files changed, 156 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index 25272a80..58d87008 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -10,6 +10,10 @@ import androidx.annotation.Nullable import androidx.annotation.WorkerThread import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.topjohnwu.superuser.Shell +import com.topjohnwu.superuser.io.SuFile +import com.topjohnwu.superuser.io.SuFileInputStream +import com.topjohnwu.superuser.io.SuFileOutputStream +import com.vanced.manager.BuildConfig import com.vanced.manager.ui.fragments.HomeFragment import com.vanced.manager.utils.AppUtils.sendFailure import com.vanced.manager.utils.FileInfo @@ -20,12 +24,14 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import java.io.File +import java.io.IOException +import java.io.InputStream +import java.io.OutputStream import java.text.SimpleDateFormat import java.util.* import java.util.regex.Pattern import kotlin.collections.ArrayList - class RootSplitInstallerService: Service() { private var vancedVersionCode: Int = 0 @@ -33,43 +39,55 @@ class RootSplitInstallerService: Service() { private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(this) } + suspend fun getVer() { vancedVersionCode = getJsonInt("vanced.json","versionCode", application) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - logDebug("RunBlockBefore"); + + Shell.enableVerboseLogging = BuildConfig.DEBUG + Shell.setDefaultBuilder( + Shell.Builder.create() + .setFlags(Shell.FLAG_REDIRECT_STDERR) + .setTimeout(10) + ) + runBlocking { getVer() } - logDebug("RunBlockAfter"); Shell.getShell { - CoroutineScope(Dispatchers.IO).launch { + var job = CoroutineScope(Dispatchers.IO).launch{ val apkFilesPath = getExternalFilesDir("apks")?.path val fileInfoList = apkFilesPath?.let { it1 -> getFileInfoList(it1) } - logDebug("GotFileInfoList") if (fileInfoList != null) { var modApk: FileInfo? = null - logDebug("FileInfoListIsNotEmpty") for (fil in fileInfoList) { - logDebug(fil.name) if(fil.name == "dark.apk" || fil.name == "black.apk") { - logDebug("found " + fil.name) modApk = fil } } - logDebug("Before modApk Check") if (modApk != null) { - logDebug("modApkCheck Passed") - overwriteBase(modApk, fileInfoList,vancedVersionCode) - logDebug("Finished Patching") + if(overwriteBase(modApk, fileInfoList,vancedVersionCode)) + { + with(localBroadcastManager) { + sendBroadcast(Intent(HomeFragment.REFRESH_HOME)) + sendBroadcast(Intent(HomeFragment.VANCED_INSTALLED)) + } + } + else + { + sendFailure(listOf("Install Failed").toMutableList(), applicationContext) + } } else { - throw IllegalArgumentException("modApk Is Null Cause Missing (dark.apk/black.apk) In apks Folder") + sendFailure(listOf("modApk Is Null Missing (dark.apk/black.apk) In apks Folder").toMutableList(), applicationContext) } //installSplitApkFiles(fileInfoList) + + } } @@ -78,12 +96,9 @@ class RootSplitInstallerService: Service() { return START_NOT_STICKY } - private fun logDebug(s: String) { - Log.d("ZLog", s) - } @WorkerThread - private fun installSplitApkFiles(apkFiles: ArrayList) { + private fun installSplitApkFiles(apkFiles: ArrayList) : Boolean { var sessionId: Int? Log.d("AppLog", "installing split apk files:$apkFiles") run { @@ -116,12 +131,10 @@ class RootSplitInstallerService: Service() { Log.d("AppLog", "committing...") val installResult = Shell.su("pm install-commit $sessionId").exec() if (installResult.isSuccess) { - with(localBroadcastManager) { - sendBroadcast(Intent(HomeFragment.REFRESH_HOME)) - sendBroadcast(Intent(HomeFragment.VANCED_INSTALLED)) - } + return true } else sendFailure(installResult.out, this) + return false } private fun SimpleDateFormat.tryParse(str: String) = try { @@ -176,60 +189,63 @@ class RootSplitInstallerService: Service() { - private fun overwriteBase(apkFile: FileInfo, baseApkFiles: ArrayList, versionCode: Int) + private fun overwriteBase(apkFile: FileInfo, baseApkFiles: ArrayList, versionCode: Int): Boolean { - logDebug("check version") - checkVersion(versionCode,baseApkFiles) - logDebug("Version Check Done, next getting apk path") - var path = getVPath() - logDebug("Path: $path") - apkFile.file?.let { - var apath = it.absolutePath - logDebug("Moving $apath to: $path") - moveAPK(apath, path) - logDebug("Move done setting chConv $path") - chConV(path) - logDebug("Done with chConv $path") - } - - - } - - private fun checkVersion(versionCode: Int, baseApkFiles: ArrayList) { - val path = getVPath() - logDebug("checking if path is in /data/app") - if(path.contains("/data/app/")) + if(checkVersion(versionCode,baseApkFiles)) { - logDebug("Path is in /data/app: $path" ) - when(compareVersion(getPkgVerCode(yPkg),versionCode)) - { - 1 -> {fixHigherVer(baseApkFiles);logDebug("higher version uninstalling then installing base + patched");} - -1 -> {fixLowerVer(baseApkFiles);logDebug("Lower Version installing base + patched");} + val path = getVPath() + apkFile.file?.let { + val apath = it.absolutePath + if(path?.let { it1 -> moveAPK(apath, it1) }!!) + { + return chConV(path) + } + } } - else - { - logDebug("No install in /data/app/ now installing") - fixNoInstall(baseApkFiles) + return false + } + + private fun checkVersion(versionCode: Int, baseApkFiles: ArrayList): Boolean { + val path = getVPath() + if (path != null) { + if(path.contains("/data/app/")) + { + when(getPkgVerCode(yPkg)?.let { compareVersion(it,versionCode) }) + { + 1 -> {return fixHigherVer(baseApkFiles) } + -1 -> {return fixLowerVer(baseApkFiles) } + } + return true + } + else + { + return fixNoInstall(baseApkFiles) + } } + return fixNoInstall(baseApkFiles) } - private fun getPkgVerCode(pkg: String): Int { + private fun getPkgVerCode(pkg: String): Int? { val pm = packageManager return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) - pm.getPackageInfo(pkg, 0).longVersionCode.and(0xFFFFFFFF).toInt() + pm.getPackageInfo(pkg, 0)?.longVersionCode?.and(0xFFFFFFFF)?.toInt() else - pm.getPackageInfo(pkg, 0).versionCode + pm.getPackageInfo(pkg, 0)?.versionCode } - private fun getPkgInfo(pkg: String): PackageInfo + private fun getPkgInfo(pkg: String): PackageInfo? { - val m = packageManager - val p: PackageInfo = m.getPackageInfo(pkg, 0) - return p + return try { + val m = packageManager + val info = m.getPackageInfo(pkg, 0) + info + } catch (e:Exception) { + null + } } private fun compareVersion(pkgVerCode: Int, versionCode: Int): Int @@ -242,33 +258,88 @@ class RootSplitInstallerService: Service() { 0 } - private fun fixHigherVer(apkFiles: ArrayList) { + private fun fixHigherVer(apkFiles: ArrayList) : Boolean { - PackageHelper.uninstallApk(yPkg, applicationContext) - installSplitApkFiles(apkFiles) + if(PackageHelper.uninstallApk(yPkg, applicationContext)) + { + return installSplitApkFiles(apkFiles) + } + with(localBroadcastManager) {sendFailure(listOf("Failed Uninstall Of Installed Version, Try Manually").toMutableList(), applicationContext)} + return false } - private fun fixLowerVer(apkFiles: ArrayList) { - installSplitApkFiles(apkFiles) + private fun fixLowerVer(apkFiles: ArrayList): Boolean { + return installSplitApkFiles(apkFiles) } - private fun fixNoInstall(baseApkFiles: ArrayList) { - installSplitApkFiles(baseApkFiles) + private fun fixNoInstall(baseApkFiles: ArrayList): Boolean { + return installSplitApkFiles(baseApkFiles) } - private fun chConV(path: String) { - Shell.su("chcon -R u:object_r:system_file:s0 $path").exec() + private fun chConV(path: String): Boolean { + val response = Shell.su("chcon -R u:object_r:system_file:s0 $path").exec() + return if(response.isSuccess) { + true + } else { + sendFailure(response.out, applicationContext) + false + } } - private fun moveAPK(apkFile: String, path: String) { - Shell.su("cp $apkFile $path").exec() - Shell.su("chmod 644 $path").exec() + private fun moveAPK(apkFile: String, path: String) : Boolean { + + val apkinF = SuFile.open(apkFile) + val apkoutF = SuFile.open(path) + + if(apkinF.exists()) + { + try { + copy(apkinF,apkoutF) + } + catch (e: IOException) + { + sendFailure(listOf("${e.message}").toMutableList(), applicationContext) + } + } + else { + sendFailure(listOf("Input File Missing").toMutableList(), applicationContext) + return false + } + + val resultmv = Shell.su("mv $apkFile $path").exec().isSuccess + return if(resultmv) { + Shell.su("chmod 644 $path").exec().isSuccess + } else { + sendFailure(listOf("Failed To Apply Mod").toMutableList(), applicationContext) + false + } } - private fun getVPath(): String { - val p = getPkgInfo(yPkg) - return p.applicationInfo.sourceDir + @Throws(IOException::class) + fun copy(src: File?, dst: File?) { + val finputStrem: InputStream = SuFileInputStream(src) + finputStrem.use { finputStrem -> + val out: OutputStream = SuFileOutputStream(dst) + out.use { out -> + // Transfer bytes from in to out + val buf = ByteArray(1024) + var len: Int + while (finputStrem.read(buf).also { len = it } > 0) { + out.write(buf, 0, len) + } + } + } + + } + private fun getVPath(): String? { + return try { + val p = getPkgInfo(yPkg) + p?.applicationInfo?.sourceDir + } catch (e: Exception) { + null + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt b/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt index dbf6f627..ecc096f6 100644 --- a/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt +++ b/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt @@ -6,6 +6,7 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import com.vanced.manager.core.installer.AppUninstallerService +import java.lang.Exception object PackageHelper { @@ -32,10 +33,18 @@ object PackageHelper { activity.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender) } - fun uninstallApk(pkg: String, applicationContext: Context) { + fun uninstallApk(pkg: String, applicationContext: Context): Boolean { val callbackIntent = Intent(applicationContext, AppUninstallerService::class.java) callbackIntent.putExtra("pkg", pkg) val pendingIntent = PendingIntent.getService(applicationContext, 0, callbackIntent, 0) - applicationContext.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender) + try { + applicationContext.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender) + return true + } + catch (e: Exception) + { + e.printStackTrace() + return false; + } } } \ No newline at end of file From b92959d0dd5802babd41ff5e08729506420e10dc Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 06:37:57 +0200 Subject: [PATCH 06/12] Fix Bug With Install when youtube is not pre installed in system and added code check, and returns error message on install if there is one --- app/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/app/build.gradle b/app/build.gradle index bf003d85..b5db7590 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -85,6 +85,7 @@ dependencies { implementation 'com.github.kittinunf.fuel:fuel-coroutines:2.2.3' implementation 'com.github.kittinunf.fuel:fuel-json:2.2.3' implementation 'com.github.topjohnwu.libsu:core:3.0.1' + implementation 'com.github.topjohnwu.libsu:io:3.0.1' implementation 'com.google.firebase:firebase-messaging:20.2.4' implementation 'com.google.firebase:firebase-perf:19.0.8' implementation 'com.mindorks.android:prdownloader:0.6.0' From 2ee709610601a06eab0a64b34659ae8f3617480d Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 07:14:00 +0200 Subject: [PATCH 07/12] Fix Bug With Install when youtube is not pre installed in system and added code check, and returns error message on install if there is one --- .../core/installer/RootSplitInstallerService.kt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index 58d87008..6db391ad 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -295,25 +295,19 @@ class RootSplitInstallerService: Service() { { try { copy(apkinF,apkoutF) + Shell.su("chmod 644 $path").exec().isSuccess + return true } catch (e: IOException) { sendFailure(listOf("${e.message}").toMutableList(), applicationContext) + return false } } else { sendFailure(listOf("Input File Missing").toMutableList(), applicationContext) return false } - - val resultmv = Shell.su("mv $apkFile $path").exec().isSuccess - return if(resultmv) { - Shell.su("chmod 644 $path").exec().isSuccess - } else { - sendFailure(listOf("Failed To Apply Mod").toMutableList(), applicationContext) - false - } - } @Throws(IOException::class) From 3c881104d9d8e8bae528e53f489d286808e3e466 Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 08:35:32 +0200 Subject: [PATCH 08/12] Added some delay between stock yt install and patching to prevent system reboot. also chrown system:system added to prevent youtube from disappearing after restart. (KevinX8 Tip) --- .../manager/core/installer/RootSplitInstallerService.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index 6db391ad..cc6bc910 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -193,6 +193,7 @@ class RootSplitInstallerService: Service() { { if(checkVersion(versionCode,baseApkFiles)) { + Thread.sleep(1000) val path = getVPath() apkFile.file?.let { val apath = it.absolutePath @@ -296,7 +297,13 @@ class RootSplitInstallerService: Service() { try { copy(apkinF,apkoutF) Shell.su("chmod 644 $path").exec().isSuccess - return true + return if(Shell.su("chown system:system $path").exec().isSuccess) { + true + } else { + sendFailure(listOf("Failed To Chown, Try Again").toMutableList(), applicationContext) + false + } + } catch (e: IOException) { From 8794f3cbd5daf9e9d01a32668d23661073764fff Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 15:01:54 +0200 Subject: [PATCH 09/12] fix duped folders, and some more testing --- .../installer/RootSplitInstallerService.kt | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index cc6bc910..01311068 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -23,15 +23,13 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import java.io.File -import java.io.IOException -import java.io.InputStream -import java.io.OutputStream +import java.io.* import java.text.SimpleDateFormat import java.util.* import java.util.regex.Pattern import kotlin.collections.ArrayList + class RootSplitInstallerService: Service() { private var vancedVersionCode: Int = 0 @@ -71,6 +69,10 @@ class RootSplitInstallerService: Service() { if (modApk != null) { if(overwriteBase(modApk, fileInfoList,vancedVersionCode)) { + val launchIntent = packageManager.getLaunchIntentForPackage("com.google.android.youtube") + startActivity(launchIntent) + Thread.sleep(500) + with(localBroadcastManager) { sendBroadcast(Intent(HomeFragment.REFRESH_HOME)) sendBroadcast(Intent(HomeFragment.VANCED_INSTALLED)) @@ -193,12 +195,12 @@ class RootSplitInstallerService: Service() { { if(checkVersion(versionCode,baseApkFiles)) { - Thread.sleep(1000) val path = getVPath() apkFile.file?.let { val apath = it.absolutePath if(path?.let { it1 -> moveAPK(apath, it1) }!!) { + val fpath = SuFile.open(path).parent!! return chConV(path) } @@ -278,7 +280,8 @@ class RootSplitInstallerService: Service() { } private fun chConV(path: String): Boolean { - val response = Shell.su("chcon -R u:object_r:system_file:s0 $path").exec() + val response = Shell.su("chcon -R u:object_r:apk_data_file:s0 $path").exec() + //val response = Shell.su("chcon -R u:object_r:system_file:s0 $path").exec() return if(response.isSuccess) { true } else { @@ -295,6 +298,7 @@ class RootSplitInstallerService: Service() { if(apkinF.exists()) { try { + Shell.su("am force-stop $yPkg").exec() copy(apkinF,apkoutF) Shell.su("chmod 644 $path").exec().isSuccess return if(Shell.su("chown system:system $path").exec().isSuccess) { @@ -316,20 +320,24 @@ class RootSplitInstallerService: Service() { return false } } + private val BUFFER = 8192 @Throws(IOException::class) fun copy(src: File?, dst: File?) { - val finputStrem: InputStream = SuFileInputStream(src) - finputStrem.use { finputStrem -> - val out: OutputStream = SuFileOutputStream(dst) - out.use { out -> - // Transfer bytes from in to out - val buf = ByteArray(1024) - var len: Int - while (finputStrem.read(buf).also { len = it } > 0) { - out.write(buf, 0, len) - } + var fis: InputStream? = null + var fos: OutputStream? = null + try { + fis = BufferedInputStream(SuFileInputStream(src)) + fos = BufferedOutputStream(SuFileOutputStream(dst)) + val buf = ByteArray(BUFFER) + var i: Int + while (fis.read(buf).also { i = it } != -1) + { + fos.write(buf, 0, i) } + } finally { + fis?.close() + fos?.close() } } From bcf52d81736a7a751a95c14c7aaf5cbf06a323dd Mon Sep 17 00:00:00 2001 From: ostajic Date: Sun, 23 Aug 2020 23:46:38 +0200 Subject: [PATCH 10/12] fixed broken none root install, and changed back to mv command --- .../manager/core/downloader/VancedDownloadService.kt | 2 +- .../manager/core/installer/RootSplitInstallerService.kt | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt index 3b5d2d92..915eff83 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt @@ -83,7 +83,7 @@ class VancedDownloadService: Service() { override fun onDownloadComplete() { when (type) { "arch" -> downloadSplits("theme") - "theme" -> downloadSplits("stock") + "theme" -> if(variant=="root") downloadSplits("stock") else downloadSplits("lang") "stock" -> downloadSplits("dpi") "dpi" -> downloadSplits("lang") "lang" -> { diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index 01311068..8a4b1839 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -299,6 +299,9 @@ class RootSplitInstallerService: Service() { { try { Shell.su("am force-stop $yPkg").exec() + + //Shell.su("rm -r SuFile.open(path).parent") + copy(apkinF,apkoutF) Shell.su("chmod 644 $path").exec().isSuccess return if(Shell.su("chown system:system $path").exec().isSuccess) { @@ -324,6 +327,9 @@ class RootSplitInstallerService: Service() { @Throws(IOException::class) fun copy(src: File?, dst: File?) { + val cmd = Shell.su("mv ${src!!.absolutePath} ${dst!!.absolutePath}").exec().isSuccess + Log.d("ZLog", cmd.toString()) + /* var fis: InputStream? = null var fos: OutputStream? = null try { @@ -339,7 +345,7 @@ class RootSplitInstallerService: Service() { fis?.close() fos?.close() } - + */ } private fun getVPath(): String? { return try { From b574177a56dcb196607c65a51050bc2bbcffc882 Mon Sep 17 00:00:00 2001 From: ostajic Date: Mon, 24 Aug 2020 08:09:30 +0200 Subject: [PATCH 11/12] removed thread.sleep and auto start of vanced --- .../manager/core/installer/RootSplitInstallerService.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index 8a4b1839..930d3e48 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -69,9 +69,9 @@ class RootSplitInstallerService: Service() { if (modApk != null) { if(overwriteBase(modApk, fileInfoList,vancedVersionCode)) { - val launchIntent = packageManager.getLaunchIntentForPackage("com.google.android.youtube") - startActivity(launchIntent) - Thread.sleep(500) + //val launchIntent = packageManager.getLaunchIntentForPackage("com.google.android.youtube") + //startActivity(launchIntent) + //Thread.sleep(500) with(localBroadcastManager) { sendBroadcast(Intent(HomeFragment.REFRESH_HOME)) From a21730a8bc7d2c39d8a9d36998bdb3f201aa967c Mon Sep 17 00:00:00 2001 From: ostajic Date: Mon, 24 Aug 2020 09:47:00 +0200 Subject: [PATCH 12/12] Added Sha256 Check on Patch Apk, code cleanup and comments added --- .../core/downloader/VancedDownloadService.kt | 8 +- .../installer/RootSplitInstallerService.kt | 143 +++++++++++++----- 2 files changed, 112 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt index 915eff83..65175c3f 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloadService.kt @@ -57,11 +57,12 @@ class VancedDownloadService: Service() { Build.SUPPORTED_ABIS.contains("arm64-v8a") -> "arm64_v8a" else -> "armeabi_v7a" } - val themePath = "$installUrl/apks/v$vancedVer/$variant/Theme/" + val themePath = "$installUrl/apks/v$vancedVer/$variant/Theme" val url = when (type) { "arch" -> "$installUrl/apks/v$vancedVer/$variant/Arch/split_config.$arch.apk" - "theme" -> "$themePath$theme.apk" + "hash" -> "$themePath/hash.json" + "theme" -> "$themePath/$theme.apk" "stock" -> "$themePath/stock.apk" "dpi" -> "$themePath/dpi.apk" "lang" -> "$installUrl/apks/v$vancedVer/$variant/Language/split_config.${lang?.get(count)}.apk" @@ -85,7 +86,8 @@ class VancedDownloadService: Service() { "arch" -> downloadSplits("theme") "theme" -> if(variant=="root") downloadSplits("stock") else downloadSplits("lang") "stock" -> downloadSplits("dpi") - "dpi" -> downloadSplits("lang") + "dpi" -> downloadSplits("hash") + "hash" -> downloadSplits("lang") "lang" -> { count++ if (count < lang?.count()!!) diff --git a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt index 930d3e48..a16c909b 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/RootSplitInstallerService.kt @@ -8,11 +8,12 @@ import android.os.IBinder import android.util.Log import androidx.annotation.Nullable import androidx.annotation.WorkerThread +import androidx.core.net.toUri import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.beust.klaxon.JsonObject +import com.beust.klaxon.Parser import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.io.SuFile -import com.topjohnwu.superuser.io.SuFileInputStream -import com.topjohnwu.superuser.io.SuFileOutputStream import com.vanced.manager.BuildConfig import com.vanced.manager.ui.fragments.HomeFragment import com.vanced.manager.utils.AppUtils.sendFailure @@ -23,7 +24,11 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import java.io.* +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.FileInputStream +import java.io.IOException +import java.security.MessageDigest import java.text.SimpleDateFormat import java.util.* import java.util.regex.Pattern @@ -32,6 +37,7 @@ import kotlin.collections.ArrayList class RootSplitInstallerService: Service() { + private var hashjson: FileInfo? = null private var vancedVersionCode: Int = 0 val yPkg = "com.google.android.youtube" @@ -65,14 +71,16 @@ class RootSplitInstallerService: Service() { { modApk = fil } - } - if (modApk != null) { - if(overwriteBase(modApk, fileInfoList,vancedVersionCode)) + if(fil.name == "hash.json") { - //val launchIntent = packageManager.getLaunchIntentForPackage("com.google.android.youtube") - //startActivity(launchIntent) - //Thread.sleep(500) + hashjson = fil + } + } + if (modApk != null && hashjson != null) { + val hash = parseJson(modApk.name.split(".")[0], hashjson!!) + if(overwriteBase(modApk, fileInfoList, vancedVersionCode,hash)) + { with(localBroadcastManager) { sendBroadcast(Intent(HomeFragment.REFRESH_HOME)) sendBroadcast(Intent(HomeFragment.VANCED_INSTALLED)) @@ -88,8 +96,10 @@ class RootSplitInstallerService: Service() { sendFailure(listOf("modApk Is Null Missing (dark.apk/black.apk) In apks Folder").toMutableList(), applicationContext) } //installSplitApkFiles(fileInfoList) - - + } + else + { + sendFailure(listOf("Files are missing, Failed Download?").toMutableList(), applicationContext) } } @@ -98,6 +108,13 @@ class RootSplitInstallerService: Service() { return START_NOT_STICKY } + private fun parseJson(s: String, hashjson: FileInfo): String + { + val jsonData = SuFile.open(hashjson.file!!.absolutePath).readText(Charsets.UTF_8) + val jsonObject = Parser.default().parse(StringBuilder(jsonData)) as JsonObject + return jsonObject.string(s)!! + } + @WorkerThread private fun installSplitApkFiles(apkFiles: ArrayList) : Boolean { @@ -111,7 +128,7 @@ class RootSplitInstallerService: Service() { sessionId = Integer.parseInt(sessionIdMatcher.group(1)!!) } apkFiles.forEach { apkFile -> - if(apkFile.name != "black.apk" && apkFile.name != "dark.apk") + if(apkFile.name != "black.apk" && apkFile.name != "dark.apk" && apkFile.name != "hash.json") { Log.d("AppLog", "installing APK : ${apkFile.name} ${apkFile.fileSize} ") val command = arrayOf("su", "-c", "pm", "install-write", "-S", "${apkFile.fileSize}", "$sessionId", apkFile.name) @@ -189,26 +206,39 @@ class RootSplitInstallerService: Service() { return null } - - - private fun overwriteBase(apkFile: FileInfo, baseApkFiles: ArrayList, versionCode: Int): Boolean + //install Vanced + private fun overwriteBase(apkFile: FileInfo,baseApkFiles: ArrayList, versionCode: Int,hash: String): Boolean { if(checkVersion(versionCode,baseApkFiles)) { val path = getVPath() apkFile.file?.let { val apath = it.absolutePath - if(path?.let { it1 -> moveAPK(apath, it1) }!!) + if(sha256Check(apath,hash)) { - val fpath = SuFile.open(path).parent!! - return chConV(path) + if(path?.let { it1 -> moveAPK(apath, it1) }!!) + { + val fpath = SuFile.open(path).parent!! + return chConV(path) + } + } + else + { + sendFailure(listOf("Download Went Corrupt, Retry or clear VanM Data").toMutableList(), applicationContext) + } } } return false } + //do sha256 check on downloaded apk + private fun sha256Check(apath: String, hash: String): Boolean { + val sfile = SuFile.open(apath) + return checkSHA256(hash,sfile) + } + //check version and perform action based on result private fun checkVersion(versionCode: Int, baseApkFiles: ArrayList): Boolean { val path = getVPath() if (path != null) { @@ -261,6 +291,7 @@ class RootSplitInstallerService: Service() { 0 } + //uninstall current update and install base that works with patch private fun fixHigherVer(apkFiles: ArrayList) : Boolean { if(PackageHelper.uninstallApk(yPkg, applicationContext)) @@ -271,14 +302,17 @@ class RootSplitInstallerService: Service() { return false } + //install newer stock youtube private fun fixLowerVer(apkFiles: ArrayList): Boolean { return installSplitApkFiles(apkFiles) } + //install stock youtube since no install was found private fun fixNoInstall(baseApkFiles: ArrayList): Boolean { return installSplitApkFiles(baseApkFiles) } + //set chcon to apk_data_file private fun chConV(path: String): Boolean { val response = Shell.su("chcon -R u:object_r:apk_data_file:s0 $path").exec() //val response = Shell.su("chcon -R u:object_r:system_file:s0 $path").exec() @@ -290,6 +324,7 @@ class RootSplitInstallerService: Service() { } } + //move patch to data/app private fun moveAPK(apkFile: String, path: String) : Boolean { val apkinF = SuFile.open(apkFile) @@ -323,30 +358,15 @@ class RootSplitInstallerService: Service() { return false } } - private val BUFFER = 8192 + @Throws(IOException::class) fun copy(src: File?, dst: File?) { val cmd = Shell.su("mv ${src!!.absolutePath} ${dst!!.absolutePath}").exec().isSuccess Log.d("ZLog", cmd.toString()) - /* - var fis: InputStream? = null - var fos: OutputStream? = null - try { - fis = BufferedInputStream(SuFileInputStream(src)) - fos = BufferedOutputStream(SuFileOutputStream(dst)) - val buf = ByteArray(BUFFER) - var i: Int - while (fis.read(buf).also { i = it } != -1) - { - fos.write(buf, 0, i) - } - } finally { - fis?.close() - fos?.close() - } - */ } + + //get path of the installed youtube private fun getVPath(): String? { return try { val p = getPkgInfo(yPkg) @@ -357,4 +377,55 @@ class RootSplitInstallerService: Service() { } + private fun checkSHA256(sha256: String, updateFile: File?): Boolean { + try { + // get the raw file data of the photo + val mInputPFD = contentResolver.openFileDescriptor(updateFile!!.toUri() , "r") + val mContentFileDescriptor = mInputPFD!!.fileDescriptor + val fIS = FileInputStream(mContentFileDescriptor) + val mGraphicBuffer = ByteArrayOutputStream() + val buf = ByteArray(1024) + while (true) { + val readNum = fIS.read(buf) + if (readNum == -1) break + mGraphicBuffer.write(buf, 0, readNum) + } + + // Generate the checksum + val sum = generateChecksum(mGraphicBuffer) + + return sum == sha256 + } catch (e: Exception) { + e.printStackTrace() + return false + } + } + + @Throws(IOException::class) + private fun generateChecksum(data: ByteArrayOutputStream): String { + try { + val digest: MessageDigest = MessageDigest.getInstance("SHA-256") + val hash: ByteArray = digest.digest(data.toByteArray()) + return printableHexString(hash) + } catch (e: Exception) { + e.printStackTrace() + } + + return "" + } + + + private fun printableHexString(data: ByteArray): String { + // Create Hex String + val hexString: StringBuilder = StringBuilder() + for (aMessageDigest:Byte in data) { + var h: String = Integer.toHexString(0xFF and aMessageDigest.toInt()) + while (h.length < 2) + h = "0$h" + hexString.append(h) + } + return hexString.toString() + } + + } \ No newline at end of file