Add support for local development with an emulator
This commit is contained in:
parent
77fed00a74
commit
a922b69094
8 changed files with 285 additions and 1 deletions
68
.idea/runConfigurations/app_emulator.xml
Normal file
68
.idea/runConfigurations/app_emulator.xml
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="app-emulator" type="AndroidRunConfigurationType" factoryName="Android App">
|
||||||
|
<module name="Seedvault.app.main" />
|
||||||
|
<option name="DEPLOY" value="false" />
|
||||||
|
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
|
||||||
|
<option name="DEPLOY_AS_INSTANT" value="false" />
|
||||||
|
<option name="ARTIFACT_NAME" value="" />
|
||||||
|
<option name="PM_INSTALL_OPTIONS" value="" />
|
||||||
|
<option name="ALL_USERS" value="false" />
|
||||||
|
<option name="ALWAYS_INSTALL_WITH_PM" value="false" />
|
||||||
|
<option name="CLEAR_APP_STORAGE" value="false" />
|
||||||
|
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
|
||||||
|
<option name="MODE" value="specific_activity" />
|
||||||
|
<option name="CLEAR_LOGCAT" value="false" />
|
||||||
|
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
|
||||||
|
<option name="INSPECTION_WITHOUT_ACTIVITY_RESTART" value="false" />
|
||||||
|
<option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
|
||||||
|
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
|
||||||
|
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
|
||||||
|
<option name="DEBUGGER_TYPE" value="Auto" />
|
||||||
|
<Auto>
|
||||||
|
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||||
|
<option name="SHOW_STATIC_VARS" value="true" />
|
||||||
|
<option name="WORKING_DIR" value="" />
|
||||||
|
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||||
|
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||||
|
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="true" />
|
||||||
|
<option name="DEBUG_SANDBOX_SDK" value="false" />
|
||||||
|
</Auto>
|
||||||
|
<Hybrid>
|
||||||
|
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||||
|
<option name="SHOW_STATIC_VARS" value="true" />
|
||||||
|
<option name="WORKING_DIR" value="" />
|
||||||
|
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||||
|
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||||
|
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||||
|
<option name="DEBUG_SANDBOX_SDK" value="false" />
|
||||||
|
</Hybrid>
|
||||||
|
<Java>
|
||||||
|
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||||
|
<option name="DEBUG_SANDBOX_SDK" value="false" />
|
||||||
|
</Java>
|
||||||
|
<Native>
|
||||||
|
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||||
|
<option name="SHOW_STATIC_VARS" value="true" />
|
||||||
|
<option name="WORKING_DIR" value="" />
|
||||||
|
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||||
|
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||||
|
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||||
|
<option name="DEBUG_SANDBOX_SDK" value="false" />
|
||||||
|
</Native>
|
||||||
|
<Profilers>
|
||||||
|
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="STARTUP_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Java/Kotlin Method Sample (legacy)" />
|
||||||
|
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
|
||||||
|
</Profilers>
|
||||||
|
<option name="DEEP_LINK" value="" />
|
||||||
|
<option name="ACTIVITY_CLASS" value="com.stevesoltys.seedvault.settings.SettingsActivity" />
|
||||||
|
<option name="SEARCH_ACTIVITY_IN_GLOBAL_SCOPE" value="false" />
|
||||||
|
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="RunConfigurationTask" enabled="false" run_configuration_name="seedvault [installEmulatorRelease]" run_configuration_type="GradleRunConfiguration" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
|
@ -58,6 +58,8 @@ It uses the same internal APIs as `adb backup` which is deprecated and thus need
|
||||||
## Contributing
|
## Contributing
|
||||||
Bug reports and pull requests are welcome on GitHub at https://github.com/seedvault-app/seedvault.
|
Bug reports and pull requests are welcome on GitHub at https://github.com/seedvault-app/seedvault.
|
||||||
|
|
||||||
|
See [DEVELOPMENT.md](app/development/DEVELOPMENT.md) for information on developing Seedvault locally.
|
||||||
|
|
||||||
This project aims to adhere to the [official Kotlin coding style](https://developer.android.com/kotlin/style-guide).
|
This project aims to adhere to the [official Kotlin coding style](https://developer.android.com/kotlin/style-guide).
|
||||||
|
|
||||||
## Third-party tools
|
## Third-party tools
|
||||||
|
|
|
@ -72,7 +72,7 @@ android {
|
||||||
// https://android.googlesource.com/platform/build/+/refs/tags/android-11.0.0_r29/target/product/security/platform.pk8
|
// https://android.googlesource.com/platform/build/+/refs/tags/android-11.0.0_r29/target/product/security/platform.pk8
|
||||||
keyAlias "platform"
|
keyAlias "platform"
|
||||||
keyPassword "platform"
|
keyPassword "platform"
|
||||||
storeFile file("platform.jks")
|
storeFile file("development/platform.jks")
|
||||||
storePassword "platform"
|
storePassword "platform"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,3 +171,42 @@ configurations {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.register('provisionEmulator', Exec) {
|
||||||
|
group("emulator")
|
||||||
|
|
||||||
|
dependsOn(tasks.assembleRelease)
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
commandLine "${project.projectDir}/development/scripts/provision_emulator.sh",
|
||||||
|
"seedvault",
|
||||||
|
"system-images;android-33;google_apis;x86_64"
|
||||||
|
|
||||||
|
environment "ANDROID_SDK_HOME", android.sdkDirectory.absolutePath
|
||||||
|
environment "JAVA_HOME", System.properties['java.home']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register('startEmulator', Exec) {
|
||||||
|
group("emulator")
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
commandLine "${project.projectDir}/development/scripts/start_emulator.sh", "seedvault"
|
||||||
|
|
||||||
|
environment "ANDROID_SDK_HOME", android.sdkDirectory.absolutePath
|
||||||
|
environment "JAVA_HOME", System.properties['java.home']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register('installEmulatorRelease', Exec) {
|
||||||
|
group("emulator")
|
||||||
|
|
||||||
|
dependsOn(tasks.assembleRelease)
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
commandLine "${project.projectDir}/development/scripts/install_app.sh"
|
||||||
|
|
||||||
|
environment "ANDROID_SDK_HOME", android.sdkDirectory.absolutePath
|
||||||
|
environment "JAVA_HOME", System.properties['java.home']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
50
app/development/DEVELOPMENT.md
Normal file
50
app/development/DEVELOPMENT.md
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# Development
|
||||||
|
|
||||||
|
## Using an emulator
|
||||||
|
|
||||||
|
It is possible to install and run Seedvault in an emulator. This is likely the path of least resistance, since you don't need to build AOSP from source to make and test code changes.
|
||||||
|
|
||||||
|
It's also helpful for quickly testing Seedvault on newer versions of Android.
|
||||||
|
Please note that this process has only been tested on Linux.
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
After opening the project in Android Studio, try running the `app:provisionEmulator` Gradle task.
|
||||||
|
|
||||||
|
This task runs the script in `scripts/provision_emulator.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./app/development/scripts/provision_emulator.sh "seedvault" "system-images;android-33;google_apis;x86_64"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Starting the emulator
|
||||||
|
|
||||||
|
You should use the Gradle task `app:startEmulator` to develop with the emulator. This is to ensure
|
||||||
|
the `-writable-system` flag is set when the emulator starts (required to install Seedvault).
|
||||||
|
|
||||||
|
This task runs the script in `scripts/start_emulator.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./app/development/scripts/start_emulator.sh "seedvault"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing changes
|
||||||
|
|
||||||
|
Once the emulator is provisioned and running, you should be able to use the `app:installEmulatorRelease`
|
||||||
|
Gradle task to install updates.
|
||||||
|
|
||||||
|
This task depends on `app:assembleRelease` and runs the script in `scripts/install_app.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./app/development/scripts/install_app.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
There's also an Andriod Studio [runtime configuration](https://developer.android.com/studio/run/rundebugconfig) `app-emulator` which will build, install, and automatically launch the `com.stevesoltys.seedvault.settings.SettingsActivity` as if you clicked `Backup` in settings.
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
The `MANAGE_DOCUMENTS` permission will not be granted unless you are using a base AOSP
|
||||||
|
image. Currently by default we are using the `google-apis` version of the image, which does not provide the
|
||||||
|
permission because it is not signed with the test platform key.
|
||||||
|
|
||||||
|
The [generic AOSP images](https://developer.android.com/topic/generic-system-image/releases) are signed with the test platform key, but at the time of writing there is no AOSP emulator image for Android 13 in the default SDK manager repositories.
|
32
app/development/scripts/install_app.sh
Executable file
32
app/development/scripts/install_app.sh
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# assert ANDROID_HOME is set
|
||||||
|
if [ -z "$ANDROID_SDK_HOME" ]; then
|
||||||
|
echo "ANDROID_SDK_HOME is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
|
||||||
|
DEVELOPMENT_DIR=$SCRIPT_DIR/..
|
||||||
|
ROOT_PROJECT_DIR=$SCRIPT_DIR/../../..
|
||||||
|
|
||||||
|
EMULATOR_DEVICE_NAME=$($ANDROID_SDK_HOME/platform-tools/adb devices | grep emulator | cut -f1)
|
||||||
|
|
||||||
|
if [ -z "$EMULATOR_DEVICE_NAME" ]; then
|
||||||
|
echo "Emulator device name not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ADB="$ANDROID_SDK_HOME/platform-tools/adb -s $EMULATOR_DEVICE_NAME"
|
||||||
|
|
||||||
|
$ADB root
|
||||||
|
sleep 3 # wait for adb to restart
|
||||||
|
$ADB remount # remount /system as writable
|
||||||
|
|
||||||
|
echo "Installing Seedvault app..."
|
||||||
|
$ADB shell mkdir -p /system/priv-app/Seedvault
|
||||||
|
$ADB push $ROOT_PROJECT_DIR/app/build/outputs/apk/release/app-release.apk /system/priv-app/Seedvault/Seedvault.apk
|
||||||
|
|
||||||
|
echo "Installing Seedvault permissions..."
|
||||||
|
$ADB push $ROOT_PROJECT_DIR/permissions_com.stevesoltys.seedvault.xml /system/etc/permissions/privapp-permissions-seedvault.xml
|
||||||
|
$ADB push $ROOT_PROJECT_DIR/allowlist_com.stevesoltys.seedvault.xml /system/etc/sysconfig/allowlist-seedvault.xml
|
71
app/development/scripts/provision_emulator.sh
Executable file
71
app/development/scripts/provision_emulator.sh
Executable file
|
@ -0,0 +1,71 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# assert ANDROID_HOME is set
|
||||||
|
if [ -z "$ANDROID_SDK_HOME" ]; then
|
||||||
|
echo "ANDROID_SDK_HOME is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# assert 2 parameters are provided
|
||||||
|
if [ $# -ne 2 ]; then
|
||||||
|
echo "Usage: $0 <emulator_name> <system_image>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
EMULATOR_NAME=$1
|
||||||
|
SYSTEM_IMAGE=$2
|
||||||
|
|
||||||
|
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
|
||||||
|
DEVELOPMENT_DIR=$SCRIPT_DIR/..
|
||||||
|
ROOT_PROJECT_DIR=$SCRIPT_DIR/../../..
|
||||||
|
|
||||||
|
echo "Downloading system image..."
|
||||||
|
$ANDROID_SDK_HOME/cmdline-tools/latest/bin/sdkmanager --install "$SYSTEM_IMAGE"
|
||||||
|
|
||||||
|
# create AVD if it doesn't exist
|
||||||
|
if $ANDROID_SDK_HOME/cmdline-tools/latest/bin/avdmanager list avd | grep -q "$EMULATOR_NAME"; then
|
||||||
|
echo "AVD already exists. Skipping creation."
|
||||||
|
else
|
||||||
|
echo "Creating AVD..."
|
||||||
|
echo 'no' | $ANDROID_SDK_HOME/cmdline-tools/latest/bin/avdmanager create avd -n "$EMULATOR_NAME" -k "$SYSTEM_IMAGE"
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Starting emulator..."
|
||||||
|
$SCRIPT_DIR/start_emulator.sh "$EMULATOR_NAME"
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
# get emulator device name from ADB
|
||||||
|
EMULATOR_DEVICE_NAME=$($ANDROID_SDK_HOME/platform-tools/adb devices | grep emulator | cut -f1)
|
||||||
|
|
||||||
|
if [ -z "$EMULATOR_DEVICE_NAME" ]; then
|
||||||
|
echo "Emulator device name not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ADB="$ANDROID_SDK_HOME/platform-tools/adb -s $EMULATOR_DEVICE_NAME"
|
||||||
|
|
||||||
|
echo "Waiting for emulator to boot..."
|
||||||
|
$ADB wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;'
|
||||||
|
|
||||||
|
echo "Provisioning emulator for write access to '/system'..."
|
||||||
|
$ADB root
|
||||||
|
sleep 3 # wait for adb to restart
|
||||||
|
$ADB remount # remount /system as writable
|
||||||
|
|
||||||
|
echo "Rebooting emulator..."
|
||||||
|
$ADB reboot # need to reboot first time we remount
|
||||||
|
$ADB wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;'
|
||||||
|
|
||||||
|
echo "Provisioning emulator for Seedvault..."
|
||||||
|
$SCRIPT_DIR/install_app.sh
|
||||||
|
|
||||||
|
echo "Setting backup transport to Seedvault..."
|
||||||
|
$ADB shell bmgr enable true
|
||||||
|
$ADB shell bmgr transport com.stevesoltys.seedvault.transport.ConfigurableBackupTransport
|
||||||
|
|
||||||
|
echo "Rebooting emulator..."
|
||||||
|
$ADB reboot
|
||||||
|
$ADB wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;'
|
||||||
|
|
||||||
|
echo "Emulator '$EMULATOR_NAME' has been provisioned with Seedvault!"
|
22
app/development/scripts/start_emulator.sh
Executable file
22
app/development/scripts/start_emulator.sh
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# assert ANDROID_HOME is set
|
||||||
|
if [ -z "$ANDROID_SDK_HOME" ]; then
|
||||||
|
echo "ANDROID_SDK_HOME is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# assert 1 parameter is provided
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Usage: $0 <emulator_name>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
EMULATOR_NAME=$1
|
||||||
|
|
||||||
|
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
|
||||||
|
DEVELOPMENT_DIR=$SCRIPT_DIR/..
|
||||||
|
ROOT_PROJECT_DIR=$SCRIPT_DIR/../../..
|
||||||
|
|
||||||
|
echo "Starting emulator..."
|
||||||
|
nohup $ANDROID_SDK_HOME/emulator/emulator -avd "$EMULATOR_NAME" -gpu swiftshader_indirect -writable-system -no-snapshot-load >/dev/null 2>&1 &
|
Loading…
Reference in a new issue