Skip to content

Android (LineageOS 15.1) Execute Script on Start Up

For a project I am currently working on I needed my old mobile phone (a Nexus 5X) to start a script directly after start up. I already did it for a Motorola Moto G 2014 running LineageOS 16. However, the hardware broke down because of old age. So I needed to do all the same for my next old mobile phone. Unfortunately, the steps I took on LineageOS 16 did not work for LineageOS 15.1 which is the only available for the Nexus 5X. Hence, here is a description how to do it on LineageOS 15.1.


Installing LineageOS 15.1

The first step is to install LineageOS 15.1 onto your mobile phone. I will not describe how this is done, because the LineageOS website has really good tutorials for this (here for the Nexus 5X). I used this to flash my mobile phone. Additionally, please install the LineageOS SU Addon to get root permissions on the phone. When everything is working, we can start our changes to the operating system.


Execute Script on Start Up

As I said, I tested a lot of different methods I found on the Internet. The one that worked for me is a combination of this forum thread and that forum thread. In a short description, we have to change the init.rc in the boot image to enable the init.d process to execute start scripts. However, for this we have to reflash the mobile phone. I tried to change the file directly via adb (getting write permissions to the file and editing it directly). However, after each reboot it changes back to the original file. So, we have to change it in the boot image itself.

Normally, I work on Linux. However, since there is a Windows tool that does all the packing and repacking (and I actually do not care about the Android image internals), I used Windows for this part. The steps we have to do are the following:


  1. Download Android Image Kitchen. I used version 3.5.

  2. Unzip our LineageOS file (the lineage-15.1-20200107-nightly-bullhead-signed.zip) and copy the boot.img into the Android Image Kitchen directory (next to unpackimg.bat and repackimg.bat).

  3. Open a command line in Windows into this directory and execute:



  4. unpackimg.bat boot.img
     


  5. Go into the directory ramdisk and edit the file init.rc. I would suggest to use Notepad++ for this, since the normal Windows editor could fuck up the charset (e.g., by using \r\n instead of \n).

  6. Go to the end of the file and add the following to enable init.d:



  7. Find the section that starts with on charger and change it to the following:



  8. #[...]

    service init_d /system/bin/sh /system/bin/sysinit
        user root
        group root
        disabled
        oneshot
        seclabel u:r:sudaemon:s0

    on property:sys.boot_completed=1 && property:sys.logbootcomplete=1
        start init_d
     


  9. Repack the image by open a command line into the Android Image Kitchen directory and execute repackimg.bat. You should now have a file that is called image-new.img. This is our new boot image.

  10. Copy the image-new.img to your phone (I used adb push for this, however, SD card also works).

  11. Start TWRP on your phone (you used it to flash your LineageOS onto your phone, so do the same steps to go into the recovery mode which uses TWRP).

  12. In TWRP, go to install, switch to install image and then select the image-new.img file you copied to your phone. Select the boot partition and swipe to install it. In short, do install -> install image -> select image-new.img -> select boot partition -> swipe to install.

  13. Reboot.

  14. Done.

  15. Now you can go into the directory /system/etc/init.d and create scripts that are executed on start up.



After this, the mobile phone should boot up as normally. If you want to check if your changes are now on the phone, you can use adb for it. Do the following if you want to check:


  1. Turn on the developer options on your mobile phone.

  2. Allow USB debugging.

  3. Allow adb to have root access.

  4. Use the command adb root on your computer to restart adb with root access.

  5. Use the command adb shell to get a shell on the phone.

  6. Output the file init.rc file via cat init.rc and see if your changes are there.



To give an example, I add a script that loops and checks if the mobile phone is charged. If it is not charged for more than 5 seconds, it shuts down the mobile phone. The following has to be done:


  1. Go to the directory /system/etc/init.d and execute:



  2. touch 99batteryshutdown
     


  3. Execute the following commands to give the correct permissions:



  4. chgrp shell 99batteryshutdown
    chmod 755 99batteryshutdown
     


  5. Place the following content into the file:


    #!/system/bin/sh

    # Start script in background
    /system/bin/batteryshutdown.sh &
     


  6. Now go to directory /system/bin and create the file batteryshutdown.sh with the correct permissions:



  7. touch batteryshutdown.sh
    chmod 755 batteryshutdown.sh
     


  8. Place the following content into the script file:


    #!/system/bin/sh

    CTR=0
    while true; do
        STATUS=$(cat /sys/class/power_supply/battery/status)

        # Observed states: Charging, Discharging, Full
        if [ $STATUS == "Discharging" ]; then
            let CTR=CTR+1
        else
            CTR=0
        fi

        # Tested: when on battery mode, after around 20 seconds the process
        # does not wake up from sleep until charger is plugged in again
        # or mobile phone is used by user.
        if [ $CTR -gt 1 ]; then
            # On Lineage 15 with 'su -c', the command returns
            # CANNOT LINK EXECUTABLE "su": cannot locate symbol
            svc power shutdown
            # On Lineage 16 without the 'su -c', the command returns just 'Killed'
            # (perhaps SELinux settings).
            #su -c 'svc power shutdown'
        fi

        sleep 5
    done
     



With this script, around 10 seconds after the charger has been removed from the mobile phone it gets shutdown. Please note, that the Android operating system optimizes the processes for the battery usage. This means as soon as the phone runs on battery, processes get suspended when the system goes to sleep. You can see my observations in the comments of the script above. Hopefully, this helps some of you to not spend hours on testing.

Dude, where is my car? (Android Edition) - Part 2

A year ago I started a project to be able to track my car in real time. Additionally, my idea was to use it as a car alarm system. I went through different iterations until I had a working system with which I was satisfied. This is the second part of a blog post series that describes how to track your car in real time and how to use it as a car alarm system.



The Problem: SD Card

The Raspberry Pi built into my car worked great. I got real-time location information about my car and was happy. However, after around half a year it stopped working sporadically. And then more often until it completely stopped. I hooked up the Raspberry Pi to a display and saw the problem: the SD card. Since the Raspberry Pi was directly connected to the power my car engine provided, it got power as soon as I started the car and lost it as soon as I turned off the engine. Because of all these abrupt power losses, the SD card was more heavily used than normally. Since it is a flash memory with only a certain number of read/write accesses, it died pretty early.

Now the easiest would be to just replace the SD card wit a new one. However, then I would run into this problem again. And since I am no hardware tinkerer, my skills in building a battery in front of the Raspberry Pi to provide it with enough power for a normal shutdown are limited. Furthermore, the Raspberry Pi needs some kind of signal that it should shutdown which means designing some kind of circuit for this. Also the Raspberry Pi has to start up again as soon as the engine starts. So, I was at a loss here first.


The Solution: Old Mobile Phone

I was thinking about the hardware problem I had and came to the realization: a mobile phone has exactly the hardware I need. Come to think of it, I do not know why I did not think about this in the first place. I need a GPS receiver for the GPS tracking. A mobile phone has one build in. I need a GSM/UMTS modem to transfer the data. A mobile phone has one build in. Now I need a battery to compensate abrupt power loss. A mobile phone has one build in. So, it has actually all the hardware I need and additionally needs less space. So I would call it a win-win situation. And since almost anyone has some old mobile phone lying around, there is no shortage on supply.

However, for this to work the mobile phone has to do two things it normally does not:


  1. Turn on as soon as it gets power from a power supply, and

  2. shutdown as soon as the power supply is turned off.



Since these are things I have to change in the operating system, I decided to give LineageOS a try. This Android based operating system gives me total access to the operating system and supports a wide range of mobile phones. I had an old mobile phone at home (a Motorola Moto G 2014) and started to tinker with it. After some searching in the Internet and some tinkering the mobile phone did what I wanted. I wrote two separated articles on how to modify your mobile phone for this:


  1. Android (LineageOS 15.1 and 16) Auto Boot on Charging

  2. Android (LineageOS 16) Shutdown when Power Supply Turned off

  3. Android (LineageOS 15.1) Shutdown when Power Supply Turned off



After that, the only missing piece was an Android App that gathers the GPS locations and transfers these to the server (basically the logger App for ChasR was missing). The source code for the Android logger is available on Github and it can be directly installed via Google Play. The App has to be configured to start automatically (just a checkbox in the App itself) and the power management of Android has to allow running the ChasR Logger in the background. This is just a setting in the power management options of Android one has to set. After that, everything works like a charm. The final setup in the car looked like this:



Again, I was able to track my car in real time either on my browser at home or via an Android App on my mobile phone:




Postscript

This setup runs now for over 3 months without any problems. The only shortcoming I could find so far is the long boot up time the mobile phone needs (around 40 seconds). I am thinking about trying to build a ChasR logger for a microcontroller. There are some controller boards that have exactly the hardware build in that I need for this. Then it should almost instantly track the GPS location. However, I never build something with a microcontroller. So it will be a steep learning curve for me :-)

The additional cool part about having written the logger Android App is that if car manufacturers should start shipping Android to their cars in the future, one can use this App directly in the car. Since a car will by then also have a GPS receiver and GSM/UMTS modem build in, it should work without any problems.

Dude, where is my car? (Raspberry Pi Edition) - Part 1

A year ago I started a project to be able to track my car in real time. Additionally, my idea was to use it as a car alarm system. I went through different iterations until I had a working system with which I was satisfied. This is the first part of a blog post series that describes how to track your car in real time and how to use it as a car alarm system.



The Beginning: GPS Tracking System

The first idea I had was to put a Raspberry Pi into my car that gathers the GPS data and submits it to a server. So I started to look into GPS tracking systems usable with Linux. Unfortunately, all GPS tracking systems I found where either in a way that I had to host them myself by using MQTT or they were only available as a service. The self-hosting suited me fine, but the MQTT part not. Why not? Because I have to open a port to the Internet for a MQTT server which I do not know the code quality of. Being a security enthusiast, I would rather have the GPS tracking system using HTTPS via a standard web server which I know is tested a millionfold. The GPS tracking as a service would also be fine for me as long as it gives me access to the data via an API. Unfortunately, the data is stored unencrypted (no end-to-end encryption) by the services and therefore do not protect my privacy (I do not want some provider to know where my car is all the time). Also, some other GPS tracking services did not have an API to fetch the stored data.

So, I started to develop an end-to-end encrypted GPS tracking system myself, called ChasR. The complete source code is available on Github if you want to host it yourself or you can just use it as a service (since the data is stored encrypted, your privacy is protected).


The Raspberry Pi

In order to install the GPS tracking into my car, I bought a Raspberry Pi (version 1), a USB GPS receiver and an UMTS modem. Obviously, the GPS receiver is used to gather the current location. The UMTS modem is necessary so the Raspberry Pi can transfer the GPS location data to the server. With the help of the Linux client for ChasR, the Raspberry Pi is able to do that. An early test setup looked like this:



To not drain the battery of my car, I connected the Raspberry Pi to the ignition of my car. Meaning, every time I started the engine of my car, the Raspberry Pi got powered up. However, I had a problem. Every time I turned off the engine of my car, the Raspberry Pi lost also power. First I thought I do not care. However, the temporary files stored locally by the ChasR logger were corrupted by this. Therefore, I added code to the client that syncs the filesystem each time a file is touched by the logger. As a result, the loss of power did not corrupt the temporary files anymore.

Finally, I was able to track my car in real time either on my browser at home or via an Android App on my mobile phone:

Android (LineageOS 16) Execute Script on Start Up

For a project I am currently working on I needed my old mobile phone (a Motorola Moto G 2014) to start a script directly after start up. I searched a lot in the depth of the Internet but did only find outdated information. Therefore, I write this article so others do not have the same problem (and I have notes available if I want to do it again ;-) ). Since this is a change to the operating system, I needed something like LineageOS to have access to it. So, this is a description how to set up your LineageOS 16 to start a script on start up.


Installing LineageOS 16

The first step is to install LineageOS 16 onto your mobile phone. I will not describe how this is done, because the LineageOS website has really good tutorials for this (here for the Moto G 2014). Since my phone is no longer supported, there are no official images for it. But I did not want to build LineageOS for myself. So I searched for unofficial builds and found one with the name lineage-16.0-20190420-UNOFFICIAL-titan.zip. I used this to flash my mobile phone. Additionally, please install the LineageOS SU Addon to get root permissions on the phone. When everything is working, we can start our changes to the operating system.


Execute Script on Start Up

As I said, I tested a lot of different methods I found on the Internet. The one that worked for me I found in a forum thread. In a short description, we have to enable the init.d process to execute start scripts. Everything you have to do can be done via adb under root permissions: The steps we have to do are the following:


  1. Turn on the developer options on your mobile phone.

  2. Allow USB debugging.

  3. Allow adb to have root access.

  4. Use the command adb root on your computer to restart adb with root access.

  5. Use the command adb shell to get a shell on the phone.

  6. Remount the file system with write permissions via:



  7. mount -oremount,rw /system
     


  8. Go to the directory /system/etc/init/ and create the file init_d.rc with the following content:



  9. service init_d /system/bin/sh /system/bin/sysinit
        user root
        group root
        disabled
        oneshot
        seclabel u:r:sudaemon:s0

    on property:sys.boot_completed=1 && property:sys.logbootcomplete=1
        start init_d
     


  10. Now you can go into the directory /etc/init.d and create scripts that are executed on start up.



To give an example, I add a script that loops and checks if the mobile phone is charged. If it is not charged for more than 5 seconds, it shuts down the mobile phone. The following has to be done:


  1. Go to the directory /etc/init.d and execute:



  2. touch 99batteryshutdown
     


  3. Execute the following commands to give the correct permissions:



  4. chgrp shell 99batteryshutdown
    chmod 755 99batteryshutdown
     


  5. Place the following content into the file:


    #!/system/bin/sh

    # Start script in background
    /bin/batteryshutdown.sh &
     


  6. Now go to directory /bin and create the file batteryshutdown.sh with the correct permissions:



  7. touch batteryshutdown.sh
    chmod 755 batteryshutdown.sh
     


  8. Place the following content into the script file:


    #!/system/bin/sh

    CTR=0
    while true; do
        STATUS=$(cat /sys/class/power_supply/battery/status)

        # Observed states: Charging, Discharging, Full
        if [ $STATUS == "Discharging" ]; then
            let CTR=CTR+1
        else
            CTR=0
        fi

        # Tested: when on battery mode, after around 20 seconds the process
        # does not wake up from sleep until charger is plugged in again
        # or mobile phone is used by user.
        if [ $CTR -gt 1 ]; then
            # On Lineage 15 with 'su -c', the command returns
            # CANNOT LINK EXECUTABLE "su": cannot locate symbol
            #svc power shutdown
            # On Lineage 16 without the 'su -c', the command returns just 'Killed'
            # (perhaps SELinux settings).
            su -c 'svc power shutdown'
        fi

        sleep 5
    done
     



With this script, around 10 seconds after the charger has been removed from the mobile phone it gets shutdown. Please note, that the Android operating system optimizes the processes for the battery usage. This means as soon as the phone runs on battery, processes get suspended when the system goes to sleep. You can see my observations in the comments of the script above. Hopefully, this helps some of you to not spend hours on testing.

Android (LineageOS 15.1 and 16) Auto Boot on Charging

For a project I am currently working on I needed an old mobile phone with Android (a Motorola Moto G 2014) to automatically boot up as soon as it gets charged. In this project, the mobile phone is always connected to a charger and as soon as this charger gets power, the phone should start its boot process. Normally, any mobile phone goes into a special "charging screen". I searched a lot in the depth of the Internet but did not find much about this topic. Therefore, I write this article so others do not have the same problem (and I have notes available if I want to do it again ;-) ). Since this is a change to the operating system, I needed something like LineageOS to have access to it. So, this is a description how to set up your LineageOS 16 to boot up as soon as it gets power via the charger. However, I also tested it on LineageOS 15.1 on a Nexus 5X and it works.


Installing LineageOS 16

The first step is to install LineageOS 16 onto your mobile phone. I will not describe how this is done, because the LineageOS website has really good tutorials for this (here for the Moto G 2014). Since my phone is no longer supported, there are no official images for it. But I did not want to build LineageOS for myself. So I searched for unofficial builds and found one with the name lineage-16.0-20190420-UNOFFICIAL-titan.zip. I used this to flash my mobile phone. Additionally, please install the LineageOS SU Addon to get root permissions on the phone. When everything is working, we can start our changes to the operating system.


Auto Boot on Charging

As I said, I tested a lot of different methods I found on the Internet. The one that worked for me I found in a forum thread. In a short description, we have to change the init.rc in the boot image. However, for this we have to reflash the mobile phone. I tried to change the file directly via adb (getting write permissions to the file and editing it directly). However, after each reboot it changes back to the original file. So, we have to change it in the boot image itself.

Normally, I work on Linux. However, since there is a Windows tool that does all the packing and repacking (and I actually do not care about the Android image internals), I used Windows for this part. The steps we have to do are the following:


  1. Download Android Image Kitchen. I used version 3.5.

  2. Unzip our LineageOS file (the lineage-16.0-20190420-UNOFFICIAL-titan.zip) and copy the boot.img into the Android Image Kitchen directory (next to unpackimg.bat and repackimg.bat).

  3. Open a command line in Windows into this directory and execute:



  4. unpackimg.bat boot.img
     


  5. Go into the directory ramdisk and edit the file init.rc. I would suggest to use Notepad++ for this, since the normal Windows editor could fuck up the charset (e.g., by using \r\n instead of \n).

  6. Find the section that starts with on charger and change it to the following:



  7. #[...]
    on charger
        class_start charger
        class_stop charger
        trigger late-init
    #[...]
     


  8. Repack the image by open a command line into the Android Image Kitchen directory and execute repackimg.bat. You should now have a file that is called image-new.img. This is our new boot image.

  9. Copy the image-new.img to your phone (I used a SD card for this).

  10. Start TWRP on your phone (you used it to flash your LineageOS onto your phone, so do the same steps to go into the recovery mode which uses TWRP).

  11. In TWRP, go to install, switch to install image and then select the image-new.img file you copied to your phone. Select the boot partition and swipe to install it. In short, do install -> install image -> select image-new.img -> select boot partition -> swipe to install.

  12. Reboot.

  13. Done.



After this, the mobile phone should boot up as soon as your charger delivers power to it. If you want to check if your changes are now on the phone, you can use adb for it. Do the following if you want to check:


  1. Turn on the developer options on your mobile phone.

  2. Allow USB debugging.

  3. Allow adb to have root access.

  4. Use the command adb root on your computer to restart adb with root access.

  5. Use the command adb shell to get a shell on the phone.

  6. Output the file init.rc file via cat init.rc and see if your changes are there.


So, I hope this is useful for others that have the same problem as I did.