Skip to content

Commit

Permalink
Initial commit!
Browse files Browse the repository at this point in the history
DSU Sideloader 1.0
  • Loading branch information
VegaBobo committed Jan 31, 2022
0 parents commit d82460d
Show file tree
Hide file tree
Showing 79 changed files with 3,023 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*.iml
.gradle
/local.properties
/.idea
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

# DSU Sideloader

A simple app made to help users easily install GSIs via DSU's Android feature.

## Requirements
- Android 10 or higher
- Unlocked Bootloader
- Device with Dynamic Partitions
- A GSI you want to use!

Community GSIs: https://github.com/phhusson/treble_experimentations/wiki/Generic-System-Image-%28GSI%29-list

Google GSIs: https://developer.android.com/topic/generic-system-image/releases

**Remember to use GSIs compatible with your architeture, vndk implementation..*

You don't need root to use this app, however, running on non-rooted devices, requires adb (you will be prompted to run a shell script to invoke DSU installation activity)

Rooted devices via Magisk, should be running Magisk v24 or higher, older versions may break DSU feature.

We highly recommend using this app with Stock ROM, Custom ROMs aren't supported.

## How to use?
1. Install app
2. When opening for the first time, you need to give read/write permission to a folder, create a new folder and allow access

**this folder will be used to store temporary files, like extracted GSIs from compressed files)*

3. Select a GSI to install

**accepted formats are: gz, xz and img*

4. You can customize installation as you want

**like changing userdata size for dynamic system*

**changing gsi file size is not recommended (let app do it automatically)*

5. Tap on "Install GSI via DSU"
6. Wait until finishes! (it may take a some time)
7. Once it finishes, next step may vary:
- On rooted devices, DSU screen will appear, prompting you to confirm installation, after that, check your notifications, DSU should start installing GSI
- On non-rooted devices, you will be prompted to run a command in adb, once you run, DSU screen will appear asking you to confirm installation, after that, DSU should start installing GSI
8. Once dynamic system is ready, you can boot it through notifications

## Other information
- DSU feature may be broken in some ROMs.
- gsid does not let you install GSIs via DSU when you have less than 40% of free storage.
- gsid checks if selected GSI size is multiple of 512 (preventing corrupted system images).
- If you have disabled/debloated system apps, make sure "Dynamic System Updates" app is not disabled.
- To use "ADB mode" on rooted device, deny root permission.

## About DSU
DSU (Dynamic System Updates), is a feature introduced on Android 10, that let developers boot GSIs without touching current system partition, this is done by creating new partitions to hold a GSI and a separated userdata, to boot on them when desired.

Unfortunelly, DSU depends on Dynamic Partitions (your device need to support, otherwise, won't work), and most GSIs requires unlocked bootloader to get them booting properly (since only OEM-Signed GSIs are allowed to boot on locked bootloader).

GSIs can be installed via DSU without root access, using ADB, running some commands, you can read more about installation process here: https://developer.android.com/topic/dsu

Once installation finishes, Android creates a persistent notification allowing you to boot into "Dynamic System" (GSI installed via DSU), and you can boot into installed GSI, without touching your system partition, or breaking the "real userdata" partition.

After booting Dynamic System, you can try and test whatever you want, when you need to switch back to device's original system image, everything you need to do, is just, a simple reboot!

When doing a long test, that may requires lots of reboots, this can be a pain, however, is possible to enable "sticky mode", that enforces dynamic system, instead of device's original system image, once tests are done, you can disable sticky mode and return to original system image.

That is basically a quickly explanation about DSU, a amazing feature, like a "dual-boot" solution, limited, however, very safe (since no read-only partition will be modified, and if GSI does not boot, just a simple reboot will return you to the original device's system image).

You can read more about DSU here: https://source.android.com/devices/tech/ota/dynamic-system-updates

## How to enable Sticky Mode?

Reboot to Dynamic System, and:
- use this command on adb: `adb shell gsi_tool enable`
- or from local adb shell: `gsi_tool enable`
- or from local rooted shell (eg. Termux on rooted GSI): `su -c 'gsi_tool enable'`

When sticky mode is enabled, device will always boot into dynamic system, instead of device's original system image.

To disable, use the same command, instead of `enable` , use `disable`


## Why creating this app?

Since this process can be done without any app, using adb, why creating a app to do that?

Well, to be honest, i think the same, however, having a app that can automate the "installation" process, and making DSUs more easier for end-user, would be a nice thing, also, i want to learn some kotlin, so, i've made this app!
1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
41 changes: 41 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}

android {
compileSdk 31

defaultConfig {
applicationId "vegabobo.dsusideloader"
minSdk 29
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'org.tukaani:xz:1.9'
implementation 'com.github.topjohnwu.libsu:core:3.2.1'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.fragment:fragment-ktx:1.4.1'
implementation 'androidx.preference:preference-ktx:1.2.0'
implementation 'com.google.android.material:material:1.5.0'
}
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
38 changes: 38 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="vegabobo.dsusideloader">

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.DSUHelper"
tools:targetApi="31">
<activity
android:name=".AboutActivity"
android:exported="false" />
<activity
android:name=".LogsActivity"
android:exported="false" />
<activity
android:name=".RunOnAdbActivity"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true" />
<activity
android:name=".SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
41 changes: 41 additions & 0 deletions app/src/main/assets/install_script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/sh

# Script made to launch DSU installation activity.
# Unrooted users can run this script using ADB to start
# installation of GSI via DSU.
# Values are populared by String.format

# Prevent users running Magisk
# equal or older than 23016
# since this version may break DSU boot
# this script was made for users running without root
# but some users may, just, well, refuse root permission
magisk_version=$(su -V) &>/dev/null

if [ ! -z "$magisk_version" ]; then
if [ $magisk_version -lt 23016 ]; then
echo "Detected older Magisk version, please update to the latest Magisk build"
exit 1
fi
fi

# required prop
setprop persist.sys.fflag.override.settings_dynamic_system true

# invoke DSU activity
am start-activity -n com.android.dynsystem/com.android.dynsystem.VerificationActivity \
-a android.os.image.action.START_INSTALL \
-d %s \
--el KEY_SYSTEM_SIZE %s \
--el KEY_USERDATA_SIZE %s

# if debug mode == log it (greping for gsid and dynsys)
# else delete installation file
debug_mode=%s
if [ $debug_mode == true ]; then
logcat -c
echo "" > /sdcard/dsu_sideloader_logs.txt
(logcat | grep -e gsid -e dynsys) | tee /sdcard/dsu_sideloader_logs.txt
else
rm '%s'
fi
Binary file added app/src/main/ic_launcher-playstore.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions app/src/main/java/vegabobo/dsusideloader/AboutActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package vegabobo.dsusideloader

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class AboutActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_about)
findViewById<TextView>(R.id.tv_version).text =
getString(R.string.version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)
}

private fun launchUrlIntent(url: String) {
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(url)
startActivity(i)
}

fun btnGitHubSource(view: View) {
launchUrlIntent("https://github.com/VegaBobo/DSU-Sideloader")
}

fun btnAuthorLink(view: View) {
launchUrlIntent("https://github.com/VegaBobo/")
}

fun btnXzUtils(view: View) {
launchUrlIntent("https://tukaani.org/xz/")
}

fun btnLibsu(view: View) {
launchUrlIntent("https://github.com/topjohnwu/libsu")
}

fun btnGoogle(view: View) {
launchUrlIntent("https://developer.android.com/")
}

}

0 comments on commit d82460d

Please sign in to comment.