Running a shell script on android device using adb - android

Manually, we can run:
adb shell
su
chmod 666 /dev/graphics/fb0
export CLASSPATH=/data/local/device.jar
export LD_LIBRARY_PATH=/data/local
exec app_process /system/bin com.device.client.Main /data/local/device.conf &
However, we need to be able to run that from a bash script on the computer compiling the program.
I have tried:
adb shell "su
&& chmod 666 /dev/graphics/fb0
&& export CLASSPATH=/data/local/device.jar
&& export LD_LIBRARY_PATH=/data/local
&& exec app_process /system/bin com.device.client.Main /data/local/device.conf &"
But since we are entering the su shell, this does not work.
Can you please suggest a solution?

Try this:
adb shell "su -c '
chmod 666 /dev/graphics/fb0
&& export CLASSPATH=/data/local/device.jar
&& export LD_LIBRARY_PATH=/data/local
&& exec app_process /system/bin com.device.client.Main
/data/local/device.conf &'"
It might be possible to simplify it, too:
adb shell "su -c '
chmod 666 /dev/graphics/fb0 &&
CLASSPATH=/data/local/device.jar
LD_LIBRARY_PATH=/data/local
app_process /system/bin com.device.client.Main
/data/local/device.conf &'"
This is because you can set environment variables for one job just by prepending them on the line, rather than the export this, export that form.

Related

Screen freezes when I run Android program with Valgrind

I am new to Valgrind. I learnt how to use Valgrind on Android from this thread:
Can't run a Java Android program with Valgrind
The scripts on my Desktop are almost the same as the original ones, except that I built the Valgrind using aarch-64 toolchains manually and ran Valgrind on Samsung S6. I have tested the Valgrind on Android using compiled c binary, and it worked. When I tested the HelloJni application, the screen froze and I cannot see the output of the application. I used "adb shell top" to see the running process, and there was a process called:
{main} valgrind --error-limit=no --trace-children=yes --compress-strings=no --compress-pos=no --log-file=/sdcard/valgrind.log.%p --tool=callgrind
When I kill this process, there were some log files on /sdcard/. And the logcat worked OK. So, Valgrind did work on the background, but I could not see the application run on the foreground.
I am really stuck here. Anyone has any ideas?
Also, does anyone know how to run Valgrind on an apk file?
Thanks a lot.
My code:
build_valgrind.sh: (I built my Valgrind somewhere else and pushed it to /data/local/Inst already)
#!/usr/bin/env bash
#set -x
adb root
adb remount
# Ensure Valgrind on the phone is running
adb shell "/data/local/Inst/bin/valgrind --version"
# Add Valgrind executable to PATH (this might fail)
adb shell "export PATH=$PATH:/data/local/Inst/bin/"
export NDK_HOME=$HOME/Downloads/android-ndk-r10e
export SDK_HOME=$HOME/Downloads/android-sdk-linux
export PATH=$SDK_HOME/tools:$PATH
export PATH=$SDK_HOME/platform-tools:$PATH
RUN_HELLO_JNI_THROUGH_VALGRIND=true
cd valgrind-3.11.0
if [ $RUN_HELLO_JNI_THROUGH_VALGRIND = true ]; then
PACKAGE="com.example.hellojni"
# The location of the Hello JNI sample application
HELLO_JNI_PATH="$NDK_HOME/samples/hello-jni"
pushd "$HELLO_JNI_PATH"
# Update build target to the desired Android SDK version
ANDROID_PROJECT_TARGET="android-18"
android update project --target "$ANDROID_PROJECT_TARGET" --path . --name hello-jni --subprojects
# Enable Android NDK build with Ant
echo '<?xml version="1.0" encoding="utf-8"?>
<project name="HelloJni" basedir="." default="debug">
<target name="-pre-build">
<exec executable="${ndk.dir}/ndk-build" failonerror="true"/>
</target>
<target name="clean" depends="android_rules.clean">
<exec executable="${ndk.dir}/ndk-build" failonerror="true">
<arg value="clean"/>
</exec>
</target>
</project>
' > "custom_rules.xml"
# Set NDK HOME for Ant (only if not already set)
if ! grep -P -q "ndk.dir=.+" "local.properties" ; then
echo -e "\nndk.dir=$NDK_HOME" >> "local.properties"
fi
# Fix for Java 8 warning (warning: [options] source value 1.5 is obsolete and will be removed in a future release)
echo "java.compilerargs=-Xlint:-options" >> "ant.properties"
# Workaround INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES error
adb uninstall "$PACKAGE"
# Build Hello JNI project in debug mode and install it on the device
ant clean && ant debug && ant installd
popd
cd ..
# Start HelloJNI app
adb shell am start -a android.intent.action.MAIN -n $PACKAGE/.HelloJni
# Make the script executable
chmod a+x bootstrap_valgrind.sh
# Run application through Valgrind on the phone
/usr/bin/env bash bootstrap_valgrind.sh
adb shell ls -lR "/sdcard/*grind*"
adb shell ls -lR "/storage/sdcard0/*grind*"
adb shell ls -lR "/storage/sdcard1/*grind*"
fi
bootstrap_valgrind.sh:
#!/usr/bin/env bash
PACKAGE="com.example.hellojni"
adb push start_valgrind.sh /data/local/
adb shell su -c "chmod 777 /data/local/start_valgrind.sh"
adb root
adb shell setprop wrap.$PACKAGE "logwrapper /data/local/start_valgrind.sh"
echo "wrap.$PACKAGE: $(adb shell getprop wrap.$PACKAGE)"
adb shell am force-stop $PACKAGE
adb shell am start -a android.intent.action.MAIN -n $PACKAGE/.HelloJni
adb logcat -c
adb logcat
exit 0
start_valgrind.sh:
#!/system/bin/sh
PACKAGE="com.example.hellojni"
# Callgrind tool
VGPARAMS='--error-limit=no --trace-children=yes --compress-strings=no --compress-pos=no --log-file=/sdcard/valgrind.log.%p --tool=callgrind --callgrind-out-file=/sdcard/callgrind.out.%p'
# Memcheck tool
#VGPARAMS='-v --error-limit=no --trace-children=yes --log-file=/sdcard/valgrind.log.%p --tool=memcheck --leak-check=full --show-reachable=yes'
export TMPDIR=/data/data/$PACKAGE
exec /data/local/Inst/bin/valgrind $VGPARAMS $*

How to install an app in system/app while developing from android studio

Is there a way to make an app install directly in the system/app folder while developing on Android Studio (the device is rooted)?
Meaning, when I press on the 'Run app' button, I want the apk to be placed in system/app.
If this is not possible, what is the recommended most convenient way to work on building and testing a system app?
Deploy automatically system app from AS
You can create a script that will do the job, and run it automatically each time you hit run in AS.
1. Create the script
You can adapt this script that I've created from my needs. Place it in: project_directory/installSystem.sh
#!/bin/bash
# CHANGE THESE FOR YOUR APP
app_package="com.example"
dir_app_name="MySysApp"
MAIN_ACTIVITY="SysAppMainActivity"
ADB="adb" # how you execute adb
ADB_SH="$ADB shell" # this script assumes using `adb root`. for `adb su` see `Caveats`
path_sysapp="/system/priv-app" # assuming the app is priviledged
apk_host="./app/build/outputs/apk/app-debug.apk"
apk_name=$dir_app_name".apk"
apk_target_dir="$path_sysapp/$dir_app_name"
apk_target_sys="$apk_target_dir/$apk_name"
# Delete previous APK
rm -f $apk_host
# Compile the APK: you can adapt this for production build, flavors, etc.
./gradlew assembleDebug || exit -1 # exit on failure
# Install APK: using adb root
$ADB root 2> /dev/null
$ADB remount # mount system
$ADB push $apk_host $apk_target_sys
# Give permissions
$ADB_SH "chmod 755 $apk_target_dir"
$ADB_SH "chmod 644 $apk_target_sys"
#Unmount system
$ADB_SH "mount -o remount,ro /"
# Stop the app
$ADB shell "am force-stop $app_package"
# Re execute the app
$ADB shell "am start -n \"$app_package/$app_package.$MAIN_ACTIVITY\" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER"
2. Bind it with AS Run
Go to Run -> Edit Configurations
Do the following changes on General tab (of your module)
Installation Options->Deplay: Nothing
Launch Options->Launch: Nothing
Before launch: press +, then Run External Tool, to select your script.
In the new dialog:
set any name.
On 'Tool Settings'->Program: navigate to the project's dir, and select your script
Caveats :
First installation
The device needs to be restarted (adb reboot) only once, on the very first installation of your app. Afterwards, you can simply press Run and everything will happen automatically.
This is because the host compiler (dex2oat) is not invoked automatically. Somehow the OS is not yet informed for this new system app. Calling dex2oat manually should solve this, but I had no luck. If anyone solves it please share.
adb root issues
Sometimes (usually the initial execution after the restart) the call to adb root does not find the device. You can simply re-play from AStudio, or sleep for a second after a successful adb root.
using su instead of adb root
adb push won't be working despite mounting system and giving permissions. To make it work replace the ADB_SH variable and the install section of the script with the following:
..
ADB_SH="$ADB shell su -c"
..
# Install APK: using adb su
$ADB_SH "mount -o rw,remount /system"
$ADB_SH "chmod 777 /system/lib/"
$ADB_SH "mkdir -p /sdcard/tmp" 2> /dev/null
$ADB_SH "mkdir -p $apk_target_dir" 2> /dev/null
$ADB push $apk_host /sdcard/tmp/$apk_name 2> /dev/null
$ADB_SH "mv /sdcard/tmp/$apk_name $apk_target_sys"
$ADB_SH "rmdir /sdcard/tmp" 2> /dev/null
Windows script for those interested:
Store this file the same way: in the root of your project directory (installSysPrivApp.bat)
::WIN BATCH SCRIPT
:: CHANGE THESE
set app_package=com.example.package
set dir_app_name=app
set MAIN_ACTIVITY=MainActivity
set ADB="adb"
::ADB_SH="%ADB% shell" # this script assumes using `adb root`. for `adb su`
see `Caveats`
set path_sysapp=/system/priv-app
set apk_host=.\Application\build\outputs\apk\Application-debug.apk
set apk_name=%dir_app_name%.apk
set apk_target_dir=%path_sysapp%/%dir_app_name%
set apk_target_sys=%apk_target_dir%/%apk_name%
:: Delete previous APK
del %apk_host%
:: Compile the APK: you can adapt this for production build, flavors, etc.
call gradlew assembleDebug
set ADB_SH=%ADB% shell su -c
:: Install APK: using adb su
%ADB_SH% mount -o rw,remount /system
%ADB_SH% chmod 777 /system/lib/
%ADB_SH% mkdir -p /sdcard/tmp
%ADB_SH% mkdir -p %apk_target_dir%
%ADB% push %apk_host% /sdcard/tmp/%apk_name%
%ADB_SH% mv /sdcard/tmp/%apk_name% %apk_target_sys%
%ADB_SH% rmdir /sdcard/tmp
:: Give permissions
%ADB_SH% chmod 755 %apk_target_dir%
%ADB_SH% chmod 644 %apk_target_sys%
::Unmount system
%ADB_SH% mount -o remount,ro /
:: Stop the app
%ADB% shell am force-stop %app_package%
:: Re execute the app
%ADB% shell am start -n \"%app_package%/%app_package%.%MAIN_ACTIVITY%\" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
To bypass reboot issue from the #paschalis answer reinstall application with a help of package manager before remounting system to read only:
# Reinstall app
$ADB_SH "pm install -r $apk_target_sys"
# Unmount system
$ADB_SH "mount -o remount,ro /"
Package manager will invoke dex2oat by itself.
(Android Q >> Windows)
::WIN BATCH SCRIPT
::setup emulator https://stackoverflow.com/a/64397712/13361987
:: CHANGE THESE
set app_package=com.project.package
set dir_app_name=NewApkName
set MAIN_ACTIVITY=Package.MainActivity
set ADB="adb"
set path_sysapp=/system/priv-app
set apk_host=.\app\build\outputs\apk\debug\app-debug.apk
set apk_name=%dir_app_name%.apk
set apk_target_dir=%path_sysapp%/%dir_app_name%
set apk_target_sys=%apk_target_dir%/%apk_name%
:: Delete previous APK
del %apk_host%
:: Compile the APK: you can adapt this for production build, flavors, etc.
call gradlew assembleDebug
set ADB_SH=%ADB% shell su 0
:: Install APK: using adb su
%ADB_SH% mount -o remount,rw /system
%ADB_SH% chmod 777 /system/lib/
%ADB_SH% mkdir -p /sdcard/tmp
%ADB_SH% mkdir -p %apk_target_dir%
%ADB% push %apk_host% /sdcard/tmp/%apk_name%
%ADB_SH% mv /sdcard/tmp/%apk_name% %apk_target_sys%
%ADB_SH% rm -r /sdcard/tmp
:: Give permissions
%ADB_SH% chmod 755 %apk_target_dir%
%ADB_SH% chmod 644 %apk_target_sys%
:: Unmount system
%ADB_SH% mount -o remount,ro /
:: Stop the app
%ADB% shell am force-stop %app_package%
:: Re execute the app
%ADB% shell am start -n \"%app_package%/%app_package%.%MAIN_ACTIVITY%\" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
:: from >> https://stackoverflow.com/questions/28302833/how-to-install-an-app-in-system-app-while-developing-from-android-studio
For mac
By using the script of #Paschalis I got 3 problems first I couldn't mount the system from adb so I did it with "terminal emulator for android" from jack palevich only (needed once) https://play.google.com/store/apps/details?id=jackpal.androidterm
mount -o rw,remount /system
the second problem was the JRE that was not the same as Android studio.
so I added
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jre/jdk/Contents/Home/
to have the same version of java that android studio was using ("ctrl + ;" in android studio to get this path)
And the last problem because of adb root that can not run in production build so I flashed this zip with magisk
https://github.com/evdenis/adb_root
Android: adbd cannot run as root in production builds
but then my phone was not detected anymore so I removed adb root and this time all works well.
Also try to run the script manually line by line in a terminal to debug this script android studio does not give all the error.
I think adb push *.apk /system/app/*.apk should do just fine.
I don't know about Android Studio, but if you are on Linux you can get try to create an alias for
adb install
that points to that command, It should work!

How to remove file from /system/xbin Android

I had copy tcpdump to /system/xbin on my device.
How can I remove It? when I try :
adb shell rm /system/xbin
I get:
rm failed for /system/xbin/tcpdump, Read-only file system
I had to do
adb root
adb remount
then rm is possible
There are two ways:
adb root
adb remount
adb shell rm /system/xbin/tcpdump
or
adb shell
su
mount -o remount,rw /system
adb shell rm /system/xbin/tcpdump

Get result code of adb shell command

How should I get $? of adb shell <command>?
I would like to check the result of adb shell mkdir /xxx.
I executed mkdir command by adb shell and failed but the result of $? is 0.
$ adb shell mkdir /xxx
mkdir failed for /xxx, Read-only file system
$ adb shell echo $?
0
$ adb shell "mkdir /xxx; echo $?"
mkdir failed for /xxx, Read-only file system
0
I would like to get the result code of adb shell <command> but not in the interactive mode like below:
$ adb shell
shell#android:/ $ mkdir /xxx
mkdir failed for /xxx, Read-only file system
255|shell#android:/ $ echo $?
255
You should do:
$ adb shell 'mkdir /xxx; echo $?'
mkdir failed for /xxx, Read-only file system
255
Notice the single quotes, otherwise $? is evaluated before reaching adb.
If you are using an older emulator, then adb shell does not return the exit value. Then you have to use adb shell 'false; echo $?' like in https://stackoverflow.com/a/17480194/306864
In newer emulators, it works properly, then you can do adb shell false || echo failed. Here's how I tested:
$ adb -e android-22 shell false; echo $?
0
$ adb -e android-22 shell 'false; echo $?'
1
$ adb -e android-29 shell false; echo $?
1
$ adb -e android-29 shell 'false; echo $?'
1

How can I install sqlite3 on rooted NexusOne runs Gingerbread

I am rooted my nexus one which runs Gingerbread. But like the following post, I can't find sqlite3 and would like to install sqlite3 on Nexus One:
Why do I get a "sqlite3: not found" error on a rooted Nexus One when I try to open a database using the adb shell?
I did in 1 shell
$ adb shell
$ su
# mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system
and in another shell, I did
$ cd ~/NexusOne/SuperOneClickv1.7-ShortFuse
$ adb push sqlite3 /system/bin
failed to copy 'sqlite3' to '/system/bin/sqlite3': Permission denied
I have tried the answer. But I get this. I clearly have 'sqlite3' but it does not let me move to /usr/bin.
# mv sqlite3 /usr/bin
failed on 'sqlite3' - No such file or directory
# pwd
/mnt/sdcard
# ls sqlite3
sqlite3
# mv sqlite3 /usr/bin
failed on 'sqlite3' - No such file or directory
# ls -l sqlite3
----rwxr-x system sdcard_rw 24120 2010-10-16 22:04 sqlite3
How can I create '/usr/bin' on my Nexus one? and have /usr/bin on my shell path?
Use the following commands sequence.
Before entering "su" command unlock your device to see dialog for granting access
$ adb push sqlite3 /sdcard/
$ adb shell
$ su
# mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system
# dd if=/sdcard/sqlite3 of=/system/bin/sqlite3
# chmod 4755 /system/bin/sqlite3
# mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system
$ cd ~/NexusOne/SuperOneClickv1.7-ShortFuse
$ adb push sqlite3 /sdcard/
$ adb shell
$ su
# cp /sdcard/sqlite3 /usr/bin

Categories

Resources