Running a shell command with a single click on a shelf shortcut on Chrome OS

I wanted to find a way to execute a shell command on a Chromebook via a single click on a bookmarked icon in the shelf. After a bit of research, I discovered a way to do it. It involves setting up the Chromebook as a ssh host, which is perhaps overkill, and could potentially have security implications, but also means I can access the chromebook's shell via ssh from my Android phone/tablet (or any other computer), which could be useful some day.

Here's how I did it on a freshly powerwashed device (in Developer mode). Not all of the below steps are strictly necessary; as ever, YMMV.

Briefly, what I did was: 

Installed Secure Shell extension; setup sshd on the Chromebook; added public key from ConnectBot (Android app) to ~/.ssh/authorized_keys in order to test connection; created profile to connect to chronos@localhost/my local IP address in Secure Shell extension; generated keys on Chromebook (in  ~/.ssh); added generated public key to ~/.ssh/authorized_keys; imported newly-generated private/public key pair within Secure Shell app (one by one); created bookmark link to chronos@localhost profile in shelf, and, finally, added required command to 'arguments' field of profile in Secure Shell.

A more detailed description follows.


1. Installed Secure Shell extension


Installed Secure Shell extension from https://chrome.google.com/webstore/detail/secure-shell/pnhechapfaindjhompbnflcldabbghjo?hl=en


2. (a) Added ssh upstart job to /etc/init/


Entered the following in the shell:

sudo ln -s /usr/share/chromeos-ssh-config/init/openssh-server.conf /etc/init/openssh-server.conf

The above file, openssh-server.conf, will auto-start sshd at boot, and, additionally, will add a firewall rule which opens port 22, enabling ssh access to the device from external networks. This firewall rule is only required if connecting from another device - to use ssh purely within the Chromebook, it is not necessary to open port 22. Therefore, if not intending to connect to the Chromebook from another device via ssh, one may create a .conf in /etc/init omitting this part. For instance, for purely accessing localhost, the following works for me:

sudo su -
echo "start on starting system-services

script

exec /usr/sbin/sshd

end script" > /etc/init/openssh-server.conf 
chmod 644 /etc/init/openssh-server.conf

2. (b) Registered and initialised upstart job


sudo initctl reload-configuration
sudo initctl start openssh-server 

The above pair of shell commands registered and then initialised the open ssh server. After entering the commands, the server was running in the background.


3. (a) Optional: Tested the connection with ConnectBot on Android tablet (Nexus 9)


This step is not actually necessary (unless you specifically want to control your Chromebook in the shell with an Android device).

Rebooted Chrome OS, launched ConnectBot, generated Pubkey, long-pressed on newly-generated key, chose Copy public key. Mailed it to self. Opened Gmail on the Chromebook, copied key from email, opened shell tab (non-root) and added the key to Chrome OS as follows:

(*DOUBLETAP* indicates a double tap on the touchpad to paste the key)

touch ~/.ssh/authorized_keys
echo *DOUBLETAP* > ~/.ssh/authorized_keys
chmod 600  ~/.ssh/authorized_keys

Created a new host profile in ConnectBot; set the second field as chronos@192.168.0.17 (my local IP address); left all other fields as default.

Connected to the profile...

chronos@localhost / $

Success! Disconnected ConnectBot. Back in the host profile, edited the field "Post-login automation". to add a shell command:

powerd_dbus_suspend

Connected to the profile...

The Chromebook sleeps!

Long pressed the N9 homescreen to bring up the "Add Widget" dialog. Dragged ConnectBot to homescreen. Chose chronos@192.168.0.17 from the pop-up list of hosts. Tapped the new homescreen shortcut...

The Chromebook sleeps!

Unfortunately, the current implementation of Android on Chrome OS doesn't appear to support  creating homescreen 'widget shortcuts'. So it seemed that another approach was required in order to create the one-click shortcut.


3. (b) Connected to the Chromebook... from the Chromebook


Opened Secure Shell extension in Chrome with the keyboard shortcut Ctrl+Alt+T, typed ssh, in omnibar, hit Tab, hit Enter.


Clicked on "New Connection"

Typed chronos@localhost

Clicked on "Connect"

At this point, it only seemed to be possible to connect after setting a password for chronos (passwd chronos), and then the password had to be entered manually at every connection. No good for automation. 

Some further setup seemed to be required.

Generated a new key, added the generated key to ~/.ssh/authorized_keys, and copied the keys to ~/Downloads.

cd ~/.ssh/
echo | ssh-keygen -P ''
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
cp -a ~/.ssh/id_rsa* ~/Downloads

Opened Secure Shell

Chose 'Import'

Navigated to private key in the file explorer (/home/chronos/user/Downloads/id_rsa). Clicked on it.

Chose 'Import', again

Navigated to public key in the file explorer (/home/chronos/user/Downloads/id_rsa.pub). Clicked on it.

Tried connecting to the chronos@localhost profile in Secure Shell again and... Boom!

chronos@localhost / $


4. Bookmarked the extension


With the Secure Shell profile command prompt tab open (which looks identical to the regular shell command prompt tab, except that in the address bar, rather than ending with crosh.html, the address ends with a profile number):

Three dot menu at top right>More tools>Add to shelf (open as window)

This created a clickable shelf bookmark icon.

5. Added the shell command


So now it was possible to open a shell command prompt with a single click, the final part of the puzzle was to add the command of interest. This turned out to be a piece of cake, once the syntax was correct. All that needed to be added to the saved Secure Shell profile was 

-- thecommand

...to the SSH Arguments field.

So, after adding 

-- powerd_dbus_suspend

to the SSH Arguments field for my chronos@localhost profile, the final result is a bookmark in the shelf which, when clicked, sends the Chromebook to sleep. Since I added it to the 9th position on the shelf, it can also be triggered with the keyboard shortcut: Alt+9.

I am not sure if it will be possible to set it up so that the command runs without opening a window, but it does at least seem to remember the window size and position, so the window can be hidden away at the side, or rolled up' into a small bar. I think it might be possible to set it up so the command runs in the background but I haven't looked into this yet.


Other use cases: Crouton etc.


Over on xda, user DandyRandyMarsh posted that he was able to successfully use this procedure to set up a shelf shortcut to open single apps within a crouton chroot in a window, simply by following the above and adding the relevant crouton command to the SSH Arguments field. He shared his example, a shortcut to enter steam;

-- sudo enter-chroot xiwi steam

One thing to bear in mind with this is that if your setup requires a password to sudo, you may need to change the command slightly. I haven't tested it out too much, but in my case, with a password prompt for sudo and a chroot on an external drive, I can open Firefox within my Ubuntu chroot in a xiwi window with a shelf shortcut after adding 

-t -- echo mypassword | sudo -S sh /media/removable/3/bin/enter-chroot xiwi firefox

to the Arguments field.

Similarly, I set up a shelf shortcut to open my chrooted Ubuntu desktop in a window with the argument

-t -- echo mypassword | sudo -S sh /media/removable/3/bin/startxfce4

Another way to do it is to save the string to a file in /usr/bin, then just put -- thefile as the argument. This is what I did with a few commands that I find it tedious to regularly open up a prompt and enter in, such as the ectool command(s) to switch off the bright LEDs on the side of the device:

sudo ectool led power off
sudo ectool led battery off


Customizing the icons


Of course, no-one wants a bunch of generic black squares darkening their desktop, so, in order to customize the shelf icon for these shortcuts, a few extra steps are necessary. 

Although the trick of injecting a favicon via js only seems to work for websites, and customizing the icon for Secure Shell itself might be pretty pointless as it'd be the same for all shortcuts (and get lost after the extension updates), we can set custom icons for our shell shortcuts as follows:

When you add shortcuts to the shelf on Chrome OS like this, a minimal app is created for each one, with its own manifest.json, and icon.pngs. Initially, the shell shortcuts were getting created with blank pngs as the icons by default (appearing as a black box with P in the center). 

So, all we need to do, is get some icons, find the right directory for our shelf shortcut app, then copy our new icons into it...

For instance, here's how I made a nice shiny icon for my single app shelf shortcut to Firefox.

(a) Prepared icons


Created a temporary directory in ~/Downloads to store my icons. 

Prepared a set of six icons in ~/Downloads/firefox. (I downloaded mine from findicons.com). 
To avoid any manifest editing, saved them as *size*.png



e.g. 32.png; 48.png; 64.png; 96.png; 128.png; 256.png

(b) Located correct directory to copy icons into; copied icons into folder:

Easy way:

As long as a somewhat unique name was chosen for the shelf shortcut, the easiest way to locate its directory is probably

cd ~/Extensions
grep -r thenameoftheshelfshortcut

Navigate to the Icons subdir, check its contents and copy over the new icons i.e. in my case:

cd thenameoftheshelfshortcut
cd */icons
ls
sudo cp ~/Downloads/firefox/* .

Other way:

If a generic name was chosen, and grepping it brings up too many results to go through,
another way to locate the correct directory is as follows:


(It is probably easiest to do this directly after clicking "add to shelf")

To change directory into the most recently modified extension icon subfolder automatically, the following works for me. 

cd ~/Extensions/&&cd $(ls -v1td */ | sed '/\Temp/d' | head -1)/&& cd $(ls -v1td */ | head -1)/icons&&ls -al
If the above one-liner worked correctly, a list of blank icons (*.png) should be visible. The file creation time/dates should be checked, and if they match the time the shortcut was added to the shelf, the directory is the right one, and new icons can simply be copied over these, e.g.

sudo cp ~/Downloads/firefox/* .


If the one-liner didn't work;  the icons directory can be located manually i.e.


ls -ltr ~/Extensions 

The most recently added folder is at the bottom. Then, 

cd themostrecentlyaddedfolder

(or, the folder modified at the date/time that the shortcut was "added to shelf"). Then,

cd */icons
ls
sudo cp ~/Downloads/firefox/* .

I repeated the above with a set of Ubuntu icons for my startxfce4 shortcut, and a few other Linux programs I use via crouton, for good measure.

Then just did sudo restart ui, and enjoyed the shiny new shelf icons!

I hope that these changes will get picked up by CrOS's extension sync, thus getting backed-up and restored automatically. At this point I am not sure if that will be the case, though.

Update regarding the latter: After an OS update, the only part that needed redoing was the SSH upstart job. After a powerwash, however, in addition to having to generate keys and add them to Secure Shell again, while the extension shortcuts (and Secure Shell profiles) themselves synced and restored OK , the icons did not. Next time, I'll see if adding a favicon URL instead of icon files works at all, and, if not, to restore them, I suppose I might have to add this into the customization scripts I run post-powerwash.

Sources:


(1) https://www.dereckson.be/blog/2015/01/15/chromebook-run-a-ssh-server-on-chrome-os/

(2) https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/chromeos-base/openssh-server-init/openssh-server-init-0.0.1.ebuild


(3) https://chromium.googlesource.com/apps/libapps/+/master/nassh/doc/FAQ.md


(4) https://groups.google.com/a/chromium.org/forum/#!msg/chromium-hterm/UpQRttX_LJk/Wj241kcSCAAJ

Configuring a gamepad manually for Android on Chrome OS


UPDATE: 

As of recent versions of Chrome OS, the procedure detailed below (using jscal) no longer works to remap keys for Android apps. The original post should now be considered deprecated and no longer applicable. 

 In some cases, Android apps will suffice to remap keys, and in other cases it may be possible to remap events in CrOS via evdev.


In order to play Android games on Chrome OS with a wireless Xbox 360 gamepad I found that, while the gamepad worked well in some games, for others it seemed that some configuration was required.

I wanted to play the game "War Robots" but when I opened it up I discovered that, while I could move and aim, the buttons to fire were incorrectly mapped.


First of all, I tried creating /system/usr/keylayout/Vendor_045e_Product_0719.kl on the Android filesystem, as this was what had worked for me to configure this gamepad on my Nexus 9. However, editing the Android keylayout didn't seem to do anything on the Chromebook. I had a look around the device and found that in the list of CrOS installable packages at /etc/portage/make.profile/package.installable, the following was included: games-util/joystick-1.4.2.


Accordingly, I emerged joystick-1.4.2 and played around with jstest and jscal.


The set of commands to emerge these binaries:


shell

sudo su -
dev_install
emerge joystick

Turned out I that with this I was able to easily swap gamepad button mappings around.


First of all I dumped the current mapping with


jscal -q /dev/input/js0


which gave the following output

jscal -u 6,0,1,2,3,4,5,15,304,305,307,308,310,311,314,315,316,317,318,704,705,706,707 /dev/input/js0

In order to determine which number corresponded to which button, I tried


jstest /dev/input/js0


However, when I pressed some buttons on the gamepad, numbers for the buttons were displayed which did not correspond with the set above. So I tried evtest


emerge evtest

evtest

Output:


No device specified, trying to scan all of /dev/input/event*

Available devices:
/dev/input/event0:      cros_ec
/dev/input/event1:      ROCKCHIP-I2S Headset Jack
/dev/input/event2:      RockchipHDMI HDMI Jack
/dev/input/event3:      gpio-keys.10
/dev/input/event4:      Elan Touchpad
/dev/input/event5:      Elan Touchscreen
/dev/input/event6:      Xbox 360 Wireless Receiver
/dev/input/event7:      Xbox 360 Wireless Receiver
/dev/input/event8:      Xbox 360 Wireless Receiver
/dev/input/event9:      Xbox 360 Wireless Receiver
Select the device event number [0-9]:

6


Hooray! Pressing the buttons on the gamepad gives useful output, such as


code 311 (BTN_TR), value 1

code 315 (BTN_START), value 1

and so on


Armed with this information I was easily able to fix the mapping in War Robots, which had one "Fire" button mapped to "Start" and another "Fire" button mapped to "Back". I found a number of reports online suggesting that this is a current issue with (lack of) controller support in the game itself, rather than any quirk of running Android on Chrome OS.


jscal original dump of mappings:
jscal -u 6,0,1,2,3,4,5,15,304,305,307,308,310,311,314,315,316,317,318,704,705,706,707 /dev/input/js0
Mod for War Robots;
swapped Start (315) with R1 (311) and Back (314) with L1 (310):
jscal -u 6,0,1,2,3,4,5,15,304,305,307,308,314,315,310,311,316,317,318,704,705,706,707 /dev/input/js0
Opened up the game. Now L1 and R1 are the fire buttons!

Saved the config. to a file with:


jscal -q /dev/input/js0 > /usr/local/WR_gamepad.sh


Unfortunately I also had another issue to fix. There is a fair amount of play in both the analog axis of my controller, the right one particularly, meaning that with the controller at rest, it's sometimes still pointing to the right slightly. In order to stop the annoying 'camera moving to the right without me moving it' issue, I needed to calibrate the dead zones.


Back to jscal:


jscal -c


(went through the calibration, which involves pressing each button/moving each axis once)


Output:


Calibrated axis:



Setting correction to:

Correction for axis 0: broken line, precision: 0.
Coeficients: -338, -338, 16555, 16217
Correction for axis 1: broken line, precision: 0.
Coeficients: -8, -8, 16388, 16380
Correction for axis 2: broken line, precision: 0.
Coeficients: 126, 126, 4260750, 4161663
Correction for axis 3: broken line, precision: 0.
Coeficients: -64, -64, 16416, 16352
Correction for axis 4: broken line, precision: 0.
Coeficients: 55, 55, 16357, -16357
Correction for axis 5: broken line, precision: 0.
Coeficients: 111, 128, 4836527, 4227201

Dumped the above corrections with



jscal -p /dev/input/js0
which gave the following output:

jscal -s 6,1,0,-338,-338,16555,16217,1,0,-8,-8,16388,16380,1,0,126,126,4260750,4161663,1,0,-64,-64,16416,16352,1,0,55,55,16357,-16357,1,0,111,128,4836527,4227201 /dev/input/js0
Dumped it to a file:

jscal -p /dev/input/js0 > /usr/local/jscal.sh


First attempt at editing dead zones.


vi/usr/local/jscal.sh


Original file contents (as above):


jscal -s 6,1,0,-338,-338,16555,16217,1,0,-8,-8,16388,16380,1,0,126,126,4260750,4161663,1,0,-64,-64,16416,16352,1,0,55,55,16357,-16357,1,0,111,128,4836527,4227201 /dev/input/js0


Changed the 4th and 5th values (axis 0) and the 22nd and 23rd values (axis 3) from -338,-338 and -64, -64 respectively to +/- ~3000 (Axis 0 and 3 are L-<  >+R on the two analogs).


New file contents:

jscal -s 6,1,0,-3038,3038,16555,16217,1,0,-8,-8,16388,16380,1,0,126,126,4260750,4161663,1,0,-3064,3064,16416,16352,1,0,55,55,16357,-16357,1,0,111,128,4836527,4227201 /dev/input/js0
:wq!
sh /usr/local/jscal.sh

Opened up the game. Still some drift in the right-hand analog. Let's have a look at what's going on with jstest:


jstest /dev/input/js0


Moving the analogs different ways, dropping them to center, and watching the values change in jstest confirms that while there is play in both sticks, the right hand side of the right hand stick is particularly loose.


Second attempt at modifying the calibration


vi /usr/local/jscal.sh


Tried -3064,10064 on axis 3.


:wq!

sh /usr/local/jscal.sh

Opened up the game. This one works quite well! I probably set it a little too high, but at least there's no right hand drift at all, now.


Final file contents:

#!/bin/bash
jscal -s 6,1,0,-3038,3038,16555,16217,1,0,-8,-8,16388,16380,1,0,126,126,4260750,4161663,1,0,-3064,10064,16416,16352,1,0,55,55,16357,-16357,1,0,111,128,4836527,4227201 /dev/input/js0  
Added a shebang as it appears that a rule can be added to udev on other Linux systems, and the calibration file placed in /usr/local/bin, meaning that it would auto-calibrate whenever the gamepad is plugged in. I would expect this to would work on Chrome OS also, though I imagine it'd get wiped out when the system auto-updates. For now, I'll just pop open a shell and run sh /usr/local/jscal.sh when I want to play Android games with the Xbox 360 joypad, and, similarly, sh /usr/local/WR_gamepad.sh when I want to play War Robots. 

Having tested with a few other games, it turns out that after manually editing the dead zone values, the next pair of values also needs to be changed in order for the full range of stick movement to be correctly recognised. Not an issue in WR, but it would be in some games. Testing the gamepad in "Modern Combat 5", I found that in addition to changing the dead zone value pairs to eliminate camera drift, I also had to increase the next set of values by a few thousand, in order for the game to recognize when I had moved the right analog stick all the way to the top/bottom/sides. (confirmed in jstest)

The following config seems to work well in MC5 to eliminate camera drift while still passing maximum values reasonably close to the original. It still doesn't quite give the proper maximum range, but seems close enough to work well for this game.

#!/bin/bash 
jscal -s 6,1,0,237,237,16266,16503,1,0,797,797,16153,16792,1,0,126,126,4260750,4161663,1,0,-3908,3908,18086,18694,1,0,-6989,6989,19894,19904,1,0,122,125,4400447,4129650 /dev/input/js0
My setup could use some further editing/fine tuning in order to achieve the best operating results (optimize the dead zones even more, could do with adding a "Jump" button in WR), but I'm happy enough with the config as is at the moment. 

I imagine that for other 360 gamepads needing to be configured, a slightly different set of values would probably need to be applied as, depending on the state of the analog sticks, the dead zone areas would most likely differ somewhat.


TL;DR version:

It's possible to change the button mappings on a 360 gamepad on Chrome OS by emerging joystick-1.4.2, dumping the values with jscal -q, changing some values, and applying them with jscal -u. Similarly, analog stick dead zone calibration can be dumped and applied with jscal -p and jscal -s respectively. The changes won't persist after the gamepad is removed, but by saving the edited values to a shell script, the fix is convenient to reapply. 

Customizing the Chrome OS boot animation

Somehow I prefer the look of the Chrome logo in black and white, so I thought I'd see if I could change the boot animation to one which was more aesthetically pleasing (for me).

It turns out that this is very simple and easy to do. Developer mode needs to be on, of course, and rootfs verification switched off.

The boot animation comprises 17 images, which can be found in PNG format in /usr/share/chromeos-assets/images_200_percent and /usr/share/chromeos-assets/images_100_percent,named boot_splash_frame1.png thru boot_splash_frame17.png.

The file at /etc/init/boot-splash.conf can be checked in order to see which set of images is being used (if in doubt, change one set and reboot to see if it sticks).

The images can then simply be copied out, edited, and replaced. Extra images can also be added, named boot_splash_frame18.png, boot_splash_frame19.png, and so on, extending the animation. It fades to the desktop after the usual period of time, more-or less, though. I copied frame 17 to frame 18, frame 16 to 19, 15, to 20, and so on, so the animation starts to reverse after it would usually finish.

In addition, the display frame interval can easily be changed in order to speedup or slowdown the animation. Look for --frame-interval in  /etc/init/boot-splash.conf (the first instance - the frecon command, is the relevant one on my device).

By default, the frame interval is set to 25.

Change it to 50 or 75 for a slightly slower animation. It is also possible to change the animation background screen colour hex code here as well (although sadly not the initial white boot screen, which is coded into the firmware & requires removal of the write-protect screw to modify). 

As an example, here's what I did:

mkdir ~/Downloads/Edited
mkdir ~/Downloads/Backup
cd /usr/share/chromeos-assets/images_100_percent
cp * ~/Downloads/Edited
cp * ~/Downloads/Backup

Opened boot splash files in image editor, made changes. The built-in image viewer in Chrome OS is rather limited so I downloaded the free app  'Image Editor' from the Play Store. Saved edited files to Downloads/Edited. Copied files back to /usr/share/chromeos-assets/images_100_percent

sudo cp ~/Downloads/Edited/boot_splash* /usr/share/chromeos-assets/images_100_percent

vi /etc/init/boot-splash.conf 


(changed frame interval from 25 to 50)

sudo reboot

Here's a GIF of what it looks like (if it shows up in a box, that's just due to it being a GIF):




Could be improved, but it's not too bad, for a first attempt, I think.

The edited PNGs forming the above can be downloaded here

Mounting SD card content read/write in Android on Chrome OS






One way to mount SD card content r/w in Android on Chrome OS is to edit the Chrome OS system file arc-sdcard.conto pass a custom mount argument to minijail0 at boot.

As this does involve modifying a system file, rootfs verification needs to be off. Chrome OS will likely undo the modifications when it auto-updates*. 
Modifying system files can potentially lead to a forced powerwash and/ or USB recovery situation. It would be best to ensure any important files have been backed up. 

In any case, here's what's working for me:

Create a folder on the SD card named android-shared.

Backup the Chrome OS system file /etc/init/arc-sdcard.conf.

Add the following lines to
etc/init/arc-sdcard.conf at line 69, (line 67 in some versions) - the blank space directly after the line 
args="$args -k none,/,none,0x44000" # rec,private 

If the SD card is formatted vfat (Chromebook file browser default):
if [ -d /media/*/*/android-shared ]
  then
  mkdir -p /home/chronos/user/Downloads/sd-android
  mkdir -p /home/chronos/user/Downloads/.tmpsdmount

  mount /dev/mmcblk1 /home/chronos/user/Downloads/.tmpsdmount -o umask=0000
  mount -o remount --make-rshared /home/chronos/user/Downloads/.tmpsdmount

  # Mount shared mount points.
  args="$args -b /home/chronos/user/Downloads/.tmpsdmount/android-shared,/Downloads/sd-android,1"
  # Remount to make it writable.
  args="$args -k none,/Downloads/sd-android,none,0x2e"  # remount,nosuid,nodev,noexec
fi 
e.g. SD card formatted vfat in file browser, folder "android-shared" on SD card created in file browser.
Lines added to arc-sdcard.conf at line 69directly after the line 
args="$args -k none,/,none,0x44000"  # rec,private



If the SD card is formatted ext*:
if [ -d /media/*/*/android-shared ]
  then
  mkdir -p /home/chronos/user/Downloads/sd-android
  mkdir -p /home/chronos/user/Downloads/.tmpsdmount

  mount /dev/mmcblk1 /home/chronos/user/Downloads/.tmpsdmount -o user,rw
  mount -o remount --make-rshared /home/chronos/user/Downloads/.tmpsdmount

  # Mount shared mount points.

  args="$args -b /home/chronos/user/Downloads/.tmpsdmount/android-shared,/Downloads/sd-android,1"
  # Remount to make it writable.
  args="$args -k none,/Downloads/sd-android,none,0x2e"  # remount,nosuid,nodev,noexec
fi
e.g. SD card formatted ext2 in shell, folder "android-shared" on SD card created either in browser or in shell (if in shell chmod 777).
Lines  added to arc-sdcard.conf at line 69directly after the line 
args="$args -k none,/,none,0x44000"  # rec,private


After a reboot, Android apps should be able to save files to /Downloads/sd-android, which should actually point to android-shared on the SD card.

Tested with various Android apps, including tTorrent and Excel.

Android apps still cannot be moved/installed to the SD card with this method. One method to gain space for Android apps is to clone the whole of Chrome OS to the SD card and run it from there with Ctrl+U in the BIOS. This seemed to run incredibly slowly on a 64GB Kingston. Somewhat faster on a 32GB Sandisk but still laggy, especially when gaming.


Note:
If any part of a command is entered incorrectly, or there otherwise is a problem with the mount -  the SD card might become unavailable and/or Android apps might fail to load  - until the card is removed, and and the device rebooted.  In addition, if you need to remove the SD card, it would be prudent to first shut down the device (or restore the original arc-sdcard.conf & reboot) before doing so.

Further Note:
For this method to work, and not crash the OS, the removable device name MUST be entered correctly, in accordance with your own personal setup.

For example, if your SD card is partitioned, you would need to substitute /dev/mmcblk1px for /dev/mmcblk1, where x is the mounted partition holding the folder to share with Android. 

Or you might have a USB drive mounted at, for instance, /dev/sda1, in which case you would need to substitute /dev/sda1 for /dev/mmcblk1

Especial caution is advised if using this method with a USB drive, as removing the external storage while it is still mounted in this manner may result in an OS crash.

You can check your removable device setup with the shell command:
 mount | grep media/removable

*The frequency of auto-updates, and thus, how often the procedure may need to be repeated, will depend on what release channel you are running. If you are on the Dev or Canary channel and find yourself having to regularly repeat this (or any other) modification, it might be worth considering switching to the stable or beta release channel where auto-updates are less frequent.

UPDATE: I should also note that I have a previous post on this subject, with a 'safer' shell command method (now also supports writing to ext4). If you are new to this sort of thing, it might be better to try the shell command method, as it is unlikely to crash your computer, even if you get it wrong. 

In fact, it might be worth first trying the shell command method in the previous post anyway, as the chief advantage of the method on this page was R/W access. The other difference is that this is automated at boot, for which a new upstart job could easily be created, in any case.