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.

Android on Chrome OS rooting shell scripts

Tested on Chrome OS v. 54-72


NOTE (Nov '18): 


The scripts have been updated (to version 0.27) to address a few recent minor changes in Chrome OS.

 If anyone is experiencing issues (such as unable to write to /system) on recent Chrome OS versions, even after trying the latest version of the script, I'd appreciate it if you leave a comment on the blog, or on this related issue report on github, noting your device model and Chrome OS version.

PREREQUISITES:


A Chromebook with storage space for a ~2GB file in /usr/local/. Exact space usage varies depending on device, but will usually be at least 1.3 GB.

The Chrome OS system partition needs to have been made writable. 
A straightforward way to enable this is usually to enter the following command in the shell, then reboot:
sudo /usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification --partitions $(( $(rootdev -s | sed -r 's/.*(.)$/\1/') - 1))


INSTRUCTIONS:


I recommend trying the latest combined script first, which will attempt to auto-download and extract the required files. 

The combined script may be run by copy/pasting the following into the Chrome OS shell prompt:

curl -Ls https://raw.githubusercontent.com/nolirium/aroc/onescript/RootandSEpatch.sh | sudo sh


Once the script has finished, check its output for any error messages and - assuming success - after a reboot, the Android subsystem should be rooted and fully working.

If any errors are experienced with the combined script, the following method may be tried:

1. Manually download the SuperSU 2.82-SR5 zip 

2. Extract/copy the folders from inside the SuperSU zip to 'Downloads'

3. Run the script(s) - either the combined version (above) which is recommended, or the more widely tested version with separate scripts to root and patch SE Linux (a little further down the page).

IMPORTANT: If you powerwash after running the scripts (without also updating the OS), the Play Store/Android apps may no longer work. If you experience this, the easiest way to fix it is usually to restore the original Android system image by running the following command (then rebooting):


sudo mv /opt/google/containers/android/system.raw.img.bk /opt/google/containers/android/system.raw.img

The combined script, after creating a writable ext4 container and adding SuperSU, attempts to bind mount certain directories within the Android container in order to patch the SE Linux policy file without having to reboot first. In case of any problem with this, the rooting and SE Linux patching scripts may be ran one by one, by pasting the following two commands in the Chrome OS shell. With this method, a reboot is required after running the first script, and again after running the second.

The command to run script 1:

curl -Ls https://raw.githubusercontent.com/nolirium/aroc/master/01Root.sh | sudo sh

The command to run script 2:

curl -Ls https://raw.githubusercontent.com/nolirium/aroc/master/02SEPatch.sh | sudo sh


DESCRIPTIONS:


RootandSEPatch.sh 


Combines the actions from the two scripts listed below, by completing the actions of the first script, then bind mounting files from SuperSU to a location on the (unrooted) container's $PATH, thus being able to patch the SE Linux policy file (the second script) without having to reboot first.


01Root.sh


Creates & formats a ~2GB sparse filesystem image in /usr/local/Android_Images, and copies Android system files therein. Modifies Chrome OS system files: either /usr/share/arc-setup/config.json, /etc/init/arc-setup-env or /etc/init/arc-system-mount.conf and /etc/init/arc-setup.conf (as per CrOS version) - changing the ro.debuggable and mount-as-read-only flags. Renames the original Android filesystem image to *.bk & replaces it with a symlink to the newly-created image. Mounts the newly created image to a folder, and copies SuperSU files to the mounted image as specified in the SuperSU update-binary. Copies BusyBox to the mounted image and installs its symlinks in the Android system/xbin directory.

02SEpatch.sh


Copies an SELinux policy file found at /etc/selinux/arc/policy/policy.30 to the Downloads folder, opens an Android root shell for the SuperSU policy patching command to be entered, then copies the patched policy back to the original location.Backup copies of the original policy.30 are saved at /etc/selinux/arc/policy/policy.30.old and /usr/local/Backup/policy.30.old.

Unroot.sh


If a backup Android image is present in the original location, removes the symlink and restores the backup. Failing this, if a backup is present in in 'Downloads', replaces the modified image with the backup. Attempts to revert the debuggable and mount-as-read-only flags to their original state.

Tested with SuperSU 2.79 & 2.82



KNOWN ISSUES:

  • There is an issue with certain recent Chrome OS versions wherein the Android root filesystem can only be mounted as read-only at runtime. This first occurred on CrOS versions 65. In CrOS versions 68-70, it appears to be necessary to change a line in Android's init.rc in order to enable the expected behaviour (allowing writing to /system in Android, once the relevant environment variable string has been set).
  • After rooting with this script, certain non English fonts may no longer display properly in Android apps. This can be fixed/worked around by copying the relevant NotoSans fonts over from Chrome OS to Android's /system/fonts/chromeos folder. Further details can be found at this issue report on github. If this affects you, feel free to leave a comment below,  (This appears to no longer be an issue on Chrome OS version 66 and newer).
  • At present, updates to Chrome OS will usually overwrite any rootfs customizations, including those carried out by this script. In theory it is possible to keep a watcher script running which, when an OS update is detected, can re-apply the customizations to the updated partition. In practice there are certain issues with this (for instance, if the background script detects that an update has been downloaded and proceeds to re-root the updated Android system, Android apps will stop working until the system has been rebooted). In addition, the OS seems to be subject to constant development and improvement, hence there is no guarantee that what works now will continue to work in future. If anyone has any thoughts to share regarding this topic, feel free to comment below.
  • The current version of the script replaces the original Android system image with a symlink. In order to revert to the original (unrooted) image if required, it will be necessary to either manually restore the backup (easiest),  force an update e.g. with a channel change, or restore from USB.
  • After a powerwash, modified system files may remain modified, and /usr/local may be empty. Again, either manually restoring the backup image, channel changing, or restoring from USB will be necessary in order to have a functioning Android subsystem.
  • Updating the su binary from within the SuperSU GUI app may not work.
  • Stability may be an issue. This remains to be seen. A few OS crashes have been noted. Likely unrelated, though - it seems to crash occasionally in any case (Dev/Canary channels).
  • The modified system image takes up a fair amount of space in /usr/local/. Storing the image in certain other places doesn't seem to work, probably due to mount timings.

PARTIAL CHANGELOG:


v 0.27 - Modified rootfs writable check, which broke due to a CrOS change. Add check if writable container and debug flags are in "/usr/share/arc-setup/config.json" Added fix for ro system in init.rc (substituted '|mount rootfs rootfs / remount bind rw' for '|mount rootfs rootfs / remount bind ro').

v 0.26 - Fixed adding BusyBox to Android system/xbin. Changed SuperSU version used from 2.82SR3 to 2.82SR5. Removed duplicate function in combined script. 

v 0.25 - Rooted container is now a sparse file, which takes up only as much disk space as is necessary. (thanks @hall757 on GitHub for suggesting this). Minor tidying up of combined script. 

v 0.24 - Combined scripts 01Root and 02SEpatch into a single script. 

v 0.23 - Minor changes to support CrOS v62. Patched SE Linux policy is now also copied to /sepolicy inside the Android container, SuperSU apk is now installed in /system/priv-app in the container, and font sharing between Chrome OS and Android is disabled in CrOS in /etc/init/arc-setup-env.  

v 0.22 - Unified arm and Intel versions into a single script. Added functionality to auto-download /extract required files. Removed necessity for additional user interaction in script 2.

v 0.21 - Fixed context of init daemon to properly support launching at boot.

v 0.20 - Added support for 7.1.1 Nougat. Daemon now launched as init service rather than app_process hijack.

v 0.19 - Added support for /etc/init/arc-setup-env (present in latest Canary). Added info for patching SELinux policy with SuperSU 2.8x (--sdk=xx)

v 0.18 - Added support for Chrome v. 59/60 (changed mounting method to mount via symlink. Fixed backing-up of original image file. Added search for extra backup image paths (e.g. when re-running script). 

Making SD card content accessible to Android on Chrome OS with bind mounts

At present, SD card content is not fully accessible to the Android container on Chrome OS.

I wanted to play my PSP games on the go, but the built-in storage on the Asus Flip C100PA is rather meagre (16GB). So, as a temporary workaround I did the following:

  1. Created a new folder named "Bound" in "Downloads".
  2. Created a folder named "PSP_Backups" on my 64 GB SD card (named "UNTITLED").
  3. Plugged in a USB HD and copied all my PSP backup games (.cso files) to the folder on the SD card.
  4. Opened a root shell and entered:
mount -o bind /media/removable/UNTITLED/PSP_Backups /run/arc/sdcard/default/emulated/0/Download/Bound && mount -o bind /media/removable/UNTITLED/PSP_Backups /run/arc/sdcard/read/emulated/0/Download/Bound && mount -o bind /media/removable/UNTITLED/PSP_Backups /run/arc/sdcard/write/emulated/0/Download/Bound
(Which is the following three commands strung into one with &&):

mount -o bind /media/removable/UNTITLED/PSP_Backups /run/arc/sdcard/default/emulated/0/Download/Bound
mount -o bind /media/removable/UNTITLED/PSP_Backups /run/arc/sdcard/read/emulated/0/Download/Bound
mount -o bind /media/removable/UNTITLED/PSP_Backups /run/arc/sdcard/write/emulated/0/Download/Bound


This gave Android apps read access to the folder. (at least, those I've tried).

An potential issue with bind mounting the card like this is that Chrome OS by default apparently seems to unmount the SD card during deep sleep. So the mounted folders might stop working necessitating a reboot and repeat of the procedure.

This seems to have been fixed by switching off idle suspend as per the following (from https://github.com/dnschneid/crouton/wiki/Power-manager-overrides). 

sudo su                                                                        #cant sudo next command
echo 1 >/var/lib/power_manager/disable_idle_suspend                            #change the action to do nothing
chown power:power /var/lib/power_manager/disable_idle_suspend                  #it belongs to power
restart powerd                                                                 #let the change take effect
exit  
An alternative option might be to temporarily disable the power manager.

Perhaps more complete SD card access integration will be added with an update to Chrome OS  soon, rendering this unnecessary. 

A different method of mounting the SD card to make it available for Android apps is detailed here. It enables write access, and is automated at boot, but does involve modifying a Chrome OS system file - which could potentially crash your computer. Only for the brave (or foolhardy).

UPDATE:  I've also found another, similar method which seems to work on all devices tested. If you have already tried the bind mount method, without success, with an ext* formatted card - please see my most recent comment at the bottom of this page for an alternative.