Menu

Advanced FAQ Log in to Edit

Zachary Powell Brent Baccala William Means

How do I give Linux more space?

As with all advanced articles you must have a good understanding of linux and android in order to get this working as most devices work differently etc. If you have problems I will try to help but can not offer much help with this matter (As it can be device dependent) also this can result in your sdcard getting wiped so proceed with caution! Note that the download page indicates the '''default''' image sizes as "'''extracted''' size".

There are a few ways of going about this, I will look at two here the first being the safest but limited and the second harder but has really only the limit of how big your storage is! For both of these methods you must have a computer running Ubuntu or any other linux distro.

Method 1

For this method we shall simply make a bigger image file and copy the content from the old file to the new one, however its important to note if your storage is formatted for FAT32 you will only be able to increase the image to 4GB, if your storage is formatted to ext2/3/4 this can be much larger, but be warned Android starts to not like mounting large image files if you go to high!

Start by copying your image file you want to 'make larger' to your computer, place it on the Desktop to make things easier.

Now open a terminal, cd to the desktop and create the new blank image of the size you want using the following commands
~~~~~~
cd ~/Desktop
dd if=/dev/zero of=ubuntunew.img bs=1M count=0 seek=4096
~~~~~~
This creates a new image file called 'ubuntunew.img' change the seek value to the size you want (e.g 4096 = 4GB)

Next we must format the new image to the ext2 file system using the below command
~~~~~~
mke2fs -F ubuntunew.img
~~~~~~
next create two folders on your desktop call one ubuntunew and one ubuntuold, we will use these as a place to mount the two images.

You now need to mount the old and new images in there respective folders, do this using the follow commands:
~~~~~~
sudo mount -o loop ubuntu.img ubuntuold
sudo mount -o loop ubuntunew.img ubuntunew
~~~~~~

Now we shall copy all the files from the old image into the new image:
~~~~~~
sudo cp -r ubuntuold/* ubuntunew
~~~~~~

(Using cp -rp will preserve ownerships, so if you have created your own account, it will still be owned by you.)
Once this is complete simply unmount the images and your ubuntunew.img is ready to be used!
~~~~~~
sudo umount ubuntuold
sudo umount ubuntunew
~~~~~~

Method 2

The second option involves creating a partition on your sdcard and 'installing' ubuntu to the partition. This will wipe your sdcard and requires a good knowledge of both linux and android. I will write up this method shortly along with a edited boot script to allow booting from it.

How do I open a PDF/DJVU/audio file?

Android activities can be started using the Android Activity Manager am. This allows you to open PDF documents, for example, from a command prompt. am can be used from within the linuxonandroid environment, though a few changes are needed.

  1. /system must be mounted

    This can be done as a user mount, which are specified in a file in the same directory as the image file. Within the linuxonandroid environment, this directory is mounted as /root/cfg. Append ".mounts" to the image file name, so if your image file is called "ubuntu.img", add the following line to "ubuntu.img.mounts", creating the file if it doesn't exist:

    ~~~~
    /system;system
    ~~~~

    All user mounts are done in the /android directory, so symlink /android/system to /system, since that's where the Android commands expect to find it.

  2. LD_LIBRARY_PATH must be set

    Since am is a short shell script, I did this by making a copy of am and adding the following line:

    ~~~~
    export LD_LIBRARY_PATH=/system/lib:/system/vendor/lib
    ~~~~

Triggering Android activities

Now I can open my tethering settings window with the following command:

am start com.android.settings/.TetherSettings

I can open my VPN settings window with this:

am start -a android.net.vpn.SETTINGS

Opening files in the linuxonandroid environment is a little bit more difficult, since the pathnames used within the chroot environment are different from the native pathnames. Also, to trigger the right action, the MIME type must be specified. I've added a extra 'view' subcommand to my am script to do all of this correctly. My modified am script looks like this:

#!/bin/bash
#
# Script to start "am" on the Android device

base=/system
export CLASSPATH=$base/framework/am.jar
export LD_LIBRARY_PATH=/system/lib:/system/vendor/lib

if [ "$1" = "view" ]; then
    file=`readlink -f "$2"`
    nativefile=$file
    if [[ $file =~ ^/android(/.*)$ ]]; then
    nativefile=${BASH_REMATCH[1]}
    else
    nativefile="/data/local/mnt$file"
    fi
    mimetype=`file --brief --mime-type "$file"`
    exec app_process $base/bin com.android.commands.am.Am start -d "file://$nativefile" -t $mimetype
else
    exec app_process $base/bin com.android.commands.am.Am "$@"
fi

Now I can open files with commands like this:

am view andy.pdf

How can I escape from the chroot environment?

A common misconception is that it is impossible to escape from a chroot environment and run commands in the native environment. In fact, it is impossible only if you don't leave yourself a backdoor, and an SSH server app is the easiest way to do that.

I (Brent) currently use SSHDroid. I've tried several SSH server apps from the Play Store and found that only SSHDroid (currently) starts automatically on boot and allows command execution, not just login.

I run SSHDroid on port 2222, disable the login banner, turn off screen lock and all of the WiFi requirements, and allow only key authentication (no passwords).

In the linuxonandroid environment, I generated an RSA key with ssh-keygen:

root@cdma_maserati:/root # ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
2e:61:48:f5:84:34:57:7b:02:e0:80:45:78:52:a4:ea root@localhost
The key's randomart image is:
+--[ RSA 2048]----+
|   B*.=o+..      |
|  +..+.= . .     |
|  .o. . . o .    |
| . . .     o     |
|.   . o S        |
|.    . o         |
| E    . .        |
|       .         |
|                 |
+-----------------+
root@cdma_maserati:/root #

Then I copied .ssh/id_rsa.pub to /sdcard, switched over to SSHDroid, and imported the key.

I also wrote a trivial shell script to give this feature an appropriate name, "native":

#!/bin/sh

ssh -p 2222 localhost $*

Now I can obtain a native prompt by typing "native", and can run commands like "native mount".

How do users and groups work under linuxonandroid?

Linuxonandroid requires root access to mount its filesystem. This is achieved by running 'su' in the native Android environment. A typical rooted Droid will use a superuser management app that includes a modified su binary which checks linuxonandroid against a list of authorized superuser apps. If any password is required at this point, it must be requested by that superuser management app. Once 'su' has completed successfully, bootscript.sh will setup the linuxonandroid environment and present you with a root prompt with no further password required.

If you now run 'su', you are running a different su binary, /bin/su within the linuxonandroid chroot environment, which will query /etc/passwd and /etc/shadow, all within the chroot environment. Likewise, if you start a linuxonandroid ssh server, it will run chroot'ed, will use the chroot password files, and will login to the chroot environment. Installing an ssh server app, on the other hand, will login to the native environment using whatever password protection scheme the server app provides.

User and group IDs are shared between the native and chroot environments. Every Android app get its own user ID and group ID, starting at 10000. Lower numbers are allocated as described in this file:

https://android.googlesource.com/platform/system/core/+/master/include/private/android_filesystem_config.h

Of particular interest are the supplemental group IDs in the 3000 range, which control access to networking, as well as groups 1015 and 1028, which control access to the SD card.

For example, I installed a tor client in my chroot environment which runs under user debian-tor (UID 106, on my system). I had to add this user to group 3003 to give it access to networking.

http://source.android.com/tech/security/

How can I easily encrypt my data?

Several apps exist in the Play Store for password protecting other apps and managing superuser access. Using one of these apps will keep unauthorized users from running linuxonandroid, but that won't protect your data if someone can make a copy of your image file, and SD card access is the only thing required to do that.

However, Android comes with native support for ecryptfs, so this is an easy way to password protect your files. Ecryptfs works similarly to a bind mount, except that the underlying files are encrypted. It supports a per-user ~/Private directory by default, with the encrypted files stored in ~/.Private

Start by installing the ecrypt tools in your linuxonandroid environment:

apt-get install ecryptfs-utils

Now set up your Private and .Private directories, as well as a keychain, by running:

ubuntu@localhost:~$ ecryptfs-setup-private -w
Enter your wrapping passphrase [ubuntu]:
Enter your wrapping passphrase [ubuntu] (again):
Enter your mount passphrase [leave blank to generate one]:

************************************************************************
YOU SHOULD RECORD YOUR MOUNT PASSPHRASE AND STORE IT IN A SAFE LOCATION.
  ecryptfs-unwrap-passphrase ~/.ecryptfs/wrapped-passphrase
THIS WILL BE REQUIRED IF YOU NEED TO RECOVER YOUR DATA AT A LATER TIME.
************************************************************************


Done configuring.

Testing mount/write/umount/read...
Inserted auth tok with sig [eea634d2e29b2542] into the user session keyring
Inserted auth tok with sig [b234b12b09172116] into the user session keyring
Inserted auth tok with sig [eea634d2e29b2542] into the user session keyring
Inserted auth tok with sig [b234b12b09172116] into the user session keyring
Testing succeeded.


Logout, and log back in to begin using your encrypted directory.

ubuntu@localhost:~$

The "-w" option selects a wrapping password, instead of using the login password; I let the script pick a random mount passphrase.

The ~/Private directory now contains Access-Your-Private-Data.desktop and README.txt, which indicates that it is not the ecrypt filesystem.

Run this command to access your encrypted ~/Private directory:

ecryptfs-mount-private

~/Private will now be empty, and ready to accept sensitive data, which will be automatically encrypted and placed into files in ~/.Private

You can umount the ~/Private directory and clear the associated keys from the kernel keyring by running:

ecryptfs-umount-private

A problem arises if you neglect to umount ~/Private before logging out. I've circumvented this by using the following script:

#!/bin/sh

if /usr/bin/ecryptfs-mount-private; then
   echo umount /data/local/mnt/root/Private >> /root/cfg/ubuntu.img.shutdown
fi

This will require modification if you use an image other than Ubuntu. We definitely need a better way to handle startup and shutdown scripts in linuxonandroid!

How Do I Adjust My Screen Size to Accommodate Softkeys?

(Equation Based on 720p Resolution and may vary per device)

To achieve this it is a simple account of mathematics to screen size and resolution of display.

The Softkeys specifically take up a 50 x (insert portrait width res here). When asked in the terminal emu to input your desired screen size, input your resolution -50 x (insert portrait width res here).

Again this may very per device due to different variables of screen size. Simple mathematics should be all you need to compensate as I cant post a guide for every device differential.

When I get the chance (WEM97) I will figure the numbers for the average 1080p Display variables.

For those who are curious this was based on a 720p Galaxy Nexus Display

How can I debug Android apps using jdb?

First, you need jdb:

apt-get install java-sdk

Next, set adb to allow local connections (see above for native):

native setprop service.adb.tcp.port 5555
native stop adbd
native start adbd

If you want to stop your app as soon as it loads, you need to set a breakpoint on the main activity's onCreate() function in the jdp.ini file:

stop in jp.yhonda.MaximaOnAndroidActivity.onCreate

Now you're ready to debug your app! You need to start the app with debugging turned on, wait for it to appear in the jdwp list, then connect to it with jdb. Since a dialog box grabs the screen while the app is waiting for the debugger, all of this should be automated in a shell script:

#!/bin/sh
#
# Usage: debugapk <COMPONENT>
#
# <COMPONENT> should be PACKAGE/CLASS
#   like jp.yhonda/.MaximaOnAndroidActivity

# start application with debugging on

am start -D $1

# wait for jdwp connection to appear, then attach to it

while true; do
      pid=`adb jdwp`
      if [ -n "$pid" ]; then
         adb forward tcp:3333 jdwp:$pid
         rlwrap jdb -attach 3333
         break
      fi
      sleep 1
done

Start your app with a command like:

debugapk jp.yhonda/.MaximaOnAndroidActivity

Your app will start, you'll see a dialog box indicating that it's waiting for the debugger, then the dialog box will disappear. If you now switch back to the terminal emulator, you'll find jdb running, attached to the app, and stopped where you set the breakpoint. Run debugapk from the top level of your source tree, and you'll have source debugging, too!

Note: I used rlwrap in the shell script to provide minimal readline functionality, but this is not required. Also, the script assumes that only a single app is set for debugging using jdwp.

Accessing the clipboard (and other system services)

Scripting Layer for Android (SL4A) is a very useful Android app that can be used to access the Android clipboard. SL4A uses a client/server architecture to allow client scripts, written in standard scripting languages like Python, to access system services. Client scripts can be run within the linuxonandroid environment.

Here's a shell script that I use to start the SL4A server on port 3333 and invoke Python:

#! /bin/sh

export EXTERNAL_STORAGE=/sdcard
PYTHONPATH=$EXTERNAL_STORAGE/com.googlecode.pythonforandroid/extras/python
PYTHONPATH=${PYTHONPATH}:/data/data/com.googlecode.pythonforandroid/files/python/lib/python2.6/lib-dynload
export PYTHONPATH
export TEMP=$EXTERNAL_STORAGE/com.googlecode.pythonforandroid/extras/python/tmp
export PYTHON_EGG_CACHE=$TEMP
export PYTHONHOME=/data/data/com.googlecode.pythonforandroid/files/python
export LD_LIBRARY_PATH=/data/data/com.googlecode.pythonforandroid/files/python/lib
export AP_PORT=3333

if ! netstat -nta | grep ":$AP_PORT" | grep -q LISTEN; then
    am start -a com.googlecode.android_scripting.action.LAUNCH_SERVER -n com.googlecode.android_scripting/.activity.ScriptingLayerServiceLauncher --ei com.googlecode.android_scripting.extra.USE_SERVICE_PORT 3333 > /dev/null
fi

/data/data/com.googlecode.pythonforandroid/files/python/bin/python "$@"

Now I can write a Python script to access the Android clipboard:

#! /root/bin/pythonforandroid

import android
import sys

droid = android.Android()

if len(sys.argv) > 1 and sys.argv[1] == "copy":
   droid.setClipboard(''.join(sys.stdin.readlines()))
else:
   print droid.getClipboard().result

Here's a script that will print GPS location data:

#! /root/bin/pythonforandroid

import android
import sys

droid = android.Android()

print droid.getLastKnownLocation().result['gps']

Related

Wiki: General FAQ

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.