[GSoC’21] Irdest Android Client – Coding Phase I

NOTE: You can read the same post in LaTeX here

Prelude

Hello! Good to see you here : ) This blog is mostly a summary of work done till now under the first coding phase of summer of code of ’21. Picking from the end of previous blog post, we planned implementing chat feature in the application module, but due to the aforementioned massive refactor in the entire codebase and upgradation of existing modules to support modern hardware the chat API has been deprecated, and some components, because of not being part of CI, got broken : ( To implement features in the module the very first step was to get the project build properly, previously (maybe) due to migration from different version control system to GitLab and that massive refactor there were some unidentified problems that did not let the application codebase build properly, also the main lead of the picture `android-support` crate, not being a part of our GitLab CI workspace too, wasbroken. We fixed all this entire stuff in multiple different steps, each solving a mini problem and writing CI for each missing component so that we or anyone joining the project never encounter similar problem(s) in the future.

I. Fixing the Android Application Codebase

The application codebase was considerably broken and for the very first time when I built the application, it instantly said build failed in10ms, which is really very weird as when for the very first time you build an android application, it takes noticeable time(~6 minutes), this time is for fetching the dependencies that are declared in the dependency management file of android codebase(the ones with the build.gradle name) followed by compiling the android project codebase. It was quite astonishing at first sight,but on closer look to the files present in the android codebase the cause was observable. It was the presence of dependency archives in the android codebase and their corresponding XML files too, and since these dependencies were already present, studio didn’t take the pain of fetching them from maven. So the question arises, When the dependencies were already present still then application didn’t compile, why? Actually what happens is that these dependencies’ XML files are editable so even the slightest edit in them renders them useless and studio doesn’t even report any kind of problem with them, another thing that happens under the hood is that studio stores these dependencies in its local cache so that when user re-compiles the application, no time is taken in fetching the dependencies and it can perform the real build. Also, by time these caches get corrupted and usage of very old cache does not let the project work in the way it should.
Okay, now let’s come to the point how we fixed it. As by now it should’ve been clear that the problem was the existence of binaries and XMLs of dependencies present in the android codebase, so the solution that I anticipated was the deletion of these files. It was not sufficient. After doing this dependency management did go as expected, but still the build failed : ( After some more inspection, I found there was some problem with gradle executable scripts as well and the gradle-wrapper.properties too. So I just referred these scripts from my previous working projects and it finally started working, a moment of joy 🥳, after many days + nights of pain ; ) As this problem was fixed, after working on some other crucial matter(see next section, II one), we wrote a CI pipeline specially for our android application codebase so that it doesn’t break again ever in the mainstream. The android-application pipeline comprises of the 3 stages, in which its lint is checked, followed by build and then the tests are run. In the upcoming coding phase we plan to make this CI pipeline even more robust and enforce stricter formatting rules, introduce Static Analysis and run android Integration Tests on GitLab CI, well we’ll discuss it the next time we meet, leaving some topics for then 👀
You can find the corresponding MRs here:
* Fixing the android application codebase: we/irdest/!21
* CI for android application codebase: we/irdest/!23

II. Fixing the FFI Layer

After the previously mentioned refactor, everything was working fine, only android specific components of the codebase were broken. A part of which, was our FFI layer, the android-support crate. This layer still held references of several deleted and deprecated APIs, therefore compiling this crate too gave a bunch of errors. Fixing them took much more time as this crate was written in Rust and then I was not that fluent with it. So fixing it included updating/modifying existing functions or we had to remove functions as well because of the deprecations. A nice challenge that we encountered was saving the state across multiple platforms(supported hardware), because the crate we used for saving state provided support for almost all the operating systems other than Android. So what we did was using the knowledge of android that an application has access to its own private storage which no other application/service can see, so all we needed to do now was to find this directory in android device file-system, this path we achieved using the ADB, now we investigated where our crate went wrong, so for this we dived deep into the crate’s API and read how it achieved similar behavior for other platforms, which was that, it first of all found the HOME(environment variable) for the OS and then located corresponding path(s) for saving state in dir/file(s), turned out, that the crate was identifying HOME wrong only for android file-system. After this was diagnosed, we wrote a custom API that found HOME env var on all platforms irrespective of their OS (see this patch), by this API we were able to access the app-specific private directory and save state there. It was quite challenging, but we figured it out! Everything related to FFI layer, after this fix was quite easy. We eliminated the problems that existed in FFI layer via refactors and some modifications in functions and then, it built green! After fixing the FFI layer we wrote the CI for it that makes sure it builds each time a commit is pushed to any MR or branch and we can see the build status in pipelines too. Writing the CI for android-support crate was not a cakewalk,actually the application needs cross-compilation of our Rust library in order to function, so we need to make sure that the library which application is going to use on android devices is really compatible with android platform and by virtue we compile it on our PCs directly so that doesn’t work quite, to make expected behavior happen there are two options:
* Compiling the Rust library codebase on android-device(less feasible), or
* Cross-compiling the library on our PC/CI runner via providing support tools for android components
So quite obviously we went with the second option, for this we installed rust and android compatible components in our runners during the CI runtime and then compiled the library via checking out to the correct directory. But since, for compiling Rust library in each CI run we had to install the components and this specific pre-compilation part(or better to say setup portion) consumed a considerable portion of our CI script(and made it look a bit daunting too), so we packaged these components to our custom docker image and pulled it each time in our CI runs, this made our life easy and scripts beautiful : )

NOTE: If you don’t have much idea of cross-compilation, then you can have a look at this awesome blog-post by Milan✨. It gives a clear understanding to the reader what cross-compilation is, irrespective of their previous knowledge on the same(yes, but basic knowledge on compilers is needed a bit). Spoiler alert: That someone in the opening of blog post is me 😛

Also, since the refactor was incomplete in our android application codebase and the android-support crate so between these to big tasks, I fitted this small refactoring, as a light break 😛
You can see the MRs for them here:
* Fixing the FFI Layer: we/irdest/!31
* Refactoring the android-components: we/irdest/!32
* Adding the android-support crate in our CI Pipelines: we/irdest/!33

III. UI Improvements

After fixing issues in android application and our Rust library, and writing a robust end-to-end CI for them we moved forward towards improving the UI of the application. Previously, the application used legacy design components and ideology, under this task we modernized these UI components and followed the material design guidelines(material.io), that improved the overall look of our Authentication screens. There is nothing much to explain in it as it was really quite easy to achieve and also we didn’t encounter any problems.
You can see the related MR here: we/irdest/!26

Acknowledgements

Well, by far it has been the most exciting summer for me and I had interesting experiences working on the project. Fixing components, was very difficult at the beginning due to many reasons one I would mention is the huge codebase which we have and it is not easy to learn about the functionality of each component present in it in short time, and also everything is intertwined too at many places. Going through it and fixing issues would definitely not have been possible without the immense support from my mentor, Spacekookie, who was always there to help me out and direct what to do. Their advice greatly helped in speeding up the development process and they are also a source of inspiration to me. Most importantly, Milan, who is not officially my mentor but has helped me a ton of times in technicalities of CI and setting up Nix environment(which I initially used for cross-compilation) about which I knew nothing, and many more instances. It won’t have been easy for me to accomplish aforementioned tasks without direction and help from Spacekookie & Milan.
Thanks again to both of them : ) and I’m more excited to work on the project with them further!

Cheers Until next time we meet!
~Ayush Shrivastava

[GSoC’21] Irdest Android Client – Overview

Hello everyone, I am Ayush Shrivastava, one of the students selected for Google Summer of Code 2021 for Irdest sub-organization under the umbrella organization freifunk. If you’re wondering which topic/project the blog is focused on, then you may give it a look here!

Irdest

Well, if you don’t know, then let me first introduce what Irdest(irde.st) is and what it does/supports. So, Irdest is a software suite that allows users to create an internet-independent, decentralized, wireless, adhoc mesh network. It removes all the dependencies of the user from a specific single service and enables users to create a mesh of their own. In this network mesh, users can communicate to each other via messaging(both, individual and Room) and placing voice calls. Irdest network mesh service also allows users to share files between them without relying on the internet. And also when a user enters the Irdest mesh network(note that user needs not connected to the internet i.e., without having an IP address, it can be a P2P connection over Wi-Fi or Bluetooth), their IP address is completely hidden thereby maintaining privacy andreducing possible breaches that may occur. In the irdest network mesh, as soon as a user enters the network, they are assigned an ID, which is a unique cryptographic key that helps identifying the users. All the messages/calls/file transfers made in Irdest network mesh are completely end to end encrypted, again a positive sign from security & Privacy perspective. Currently, Irdest is supported for Linux & Android devices. For android, it is pretty much in incubation state and there are a bunch of points & directions where we can improve. This summer, I aim to implement some features on android client from the irdest upstream.

WARNING: This blog has a tons of mentions of FFI, you may get overwhelmed by the term, so it stands for Foreign Function Interface.

Current Progress & FFI Overview

So this was what Irdest is all about and a higher level overview of how things really work in it. As mentioned previously, the android client is pretty much in its incubation state, so we wish to implement it in a clean & modern way. So, since we want to make use of features supported by Irdest(in upstream) on the android application, therefore we need to maintain/create a binding or kind of a link between core Irdest code that makes all this internet independent network mesh possible & application codebase(to call those methods from). The point is that the core Irdest code that supports these functionalities is written natively in Rust, and we we want to utilize this pre-written library on android, without writing it again(in Kotlin)for android. So to make it possible, we’re going to write an FFI Layer(I’ll write in detail about FFI in some other post, but for the time being it is sufficient to know that by FFI we can call functions written in a specific language(mostly native languages like C++, C, Rust) from some other languages). This FFI layer currently exists in the module, but it is a bit old-fashioned, so in the initial phase of my coding period I plan and propose to rewrite this layer with best possible modern day FFI practices and following some standard references. The most crucial part of this project is this FFI layer, because it is the fundamental building block for the android project, once it is set and ready, then we’ll be able to use the functions and services provided in the native Irdest library written in Rust and extend our further development process via writing the application.

FFI Implementation – A Blueprint

The FFI already is quite notorious for the undefined behavior and on top of it, there is very less official documentation available on Rust-Kotlin FFI so this makes it more tricky & challenging to implement, but for the course of our development process, we’ll be following and taking inspiration from how Mozilla have implemented FFI integration between their existing rust library and their firefox android client. Another instance where they use Rust-Kotlin FFI is their Glean project(a telemetry service). I’ll be taking most of the inspiration by and practices being followed in Glean, as a result of which we’ll be writing FFI bindings on our own. After once we’ve written FFI layer, my next step will be to test it again thoroughly and make sure it works perfectly and does not has any bugs residing.

Further Development:

Once we have a robust FFI layer ready, then I’ll move to core android development process, that’ll entail writing UI for the application, architecting it properly, modularizing the application codebase and following the Modern Android Dev practices. Well this will be a relatively easier job to do in comparison to that of writing FFI layer xD
My next step after this would be implementing the chat service in the application. We’ll focus in its detailing after we’re done with the very first milestone, the ”FFI Layer”. We’ll see the plan of action for chat service in a separate blogpost, after the first coding phase : )

Thanks for reading!
Cheers, Until next time we meet!

~Ayush Shrivastava

Our Google Summer of Code Projects

Google Summer of Code Logo

This year, we were finally accepted back as an organization at the Google Summer of Code. In the meantime, the application and selection phase is over. Google has given us 9 project slots. We didn’t make the decision easy and chose the best ones out of the applications.

Organizations

Freifunk manages projects for different initiatives as an umbrella organization. In this Google Summer of Code we have Retroshare, irdest, OpenWrt, LibreMesh and freifunk itself on board.

Timeline

Currently we are in the community bonding period. During this time, all preparations are made so that the students can do their tasks. Also, they should dive into the communities and get to know people and tools.

Coding officially starts on June 7. All projects must be completed by August 23.

Our Google Summer of Code projects in 2021

TitleOrganizationStudent
OpenWRT PPAOpenWrtNeelaksh Singh
Irdest Android ClientirdestAyush Shrivastava
Android native app for network selection capability in LibreMesh routersLibreMeshTomás Assenza
RetroShare WEBUIRetroShareAvinash
Freifunk Digital Twin – test on your virtual mesh before going productiveOpenWrtpschreiber
OpenWrt Device PageOpenWrtAditi-Singh
Freifunk Radio Ressource Management with IEEE 802.11vOpenWrtValerius_B
Updation of the Json Schema to latest version (2020-12) along with the form generation and validation with the updated schema of the toolsfreifunksh15h4nk
LibreMesh Pirania UILibreMeshAngie Ortiz Giraldo

You can find more details for every projects on our GSoC dashboard.

Freifunk @ Google Summer of Code 2021

GSoC Logo

Apply now at https://summerofcode.withgoogle.com/

What is Google Summer of Code (GSoC)?

Google Summer of Code is Google’s summer program for students to learn about, and get involved in open source. It’s happening again for the 17th year in 2021! Over 16,000 students from 111 countries have participated.

Freifunk got accepted as umbrella organization for wireless network communities like Ninux, qaul.net, Guifi.net or WLAN Slovenija and communities developing software we extensively use like OpenWRT, OLSR, BATMAN, libremesh or retroshare. See our GSoC’s profile page for more information.

The goals of the program are to:

  • Motivate students to begin participating in open source development.
  • Help open source projects bring in new, excited developers into their communities who stay long after their GSoC ends.
  • Provide students in Computer Science and related fields the opportunity to do work related to their academic pursuits.
  • Give students exposure to real-world software development scenarios (e.g., testing, version control, software licensing, mailing-list etiquette, etc.).
  • Create more open source code.

How does GSoC work?

Programming online from their home, student participants spend 10 weeks on their projects (about 175 total hrs) earning stipends upon completion of their milestones. Volunteer mentors help students plan their time, answer questions and provide guidance on best practices, project-specific tools, and community norms while helping integrate students into their communities.

Students receive an invaluable learning experience, an introduction to the global FOSS community and something that potential employers love to see on resumes!

Mentoring orgs will gain new contributions & contributors along with recognition from Google and a higher profile for their project.

How to apply for freifunk @ GSoC 2021?

  1. Pick an idea from our projects page and get in touch with mentors and the community.
  2. Discuss your ideas and proposals.
  3. Submit a draft of your proposal early, so we can give you feedback.
  4. If you have any general questions, join our Matrix room.

Student applications are open March 29 – April 13, 2021.

Who can apply?

In short: you have to be at least 18 years when you register and you need to be enrolled in or accepted into a post-secondary academic program, including a college, university, masters program, PhD program, undergraduate program, licensed coding school. For all details, please see GSoC’s FAQ.

VRConfig Final

Hi,

this is the final blog post about my project VRConfig.
VRConfig aims to improve the accessibility and usability especially for inexperienced users of OpenWrt and its Webinterface LuCI.
It achieves this by introducing a graphical configuration option. The users can configure their router by interacting with a picture of the router model they are using, instead of digging through menus full of technical terms they do not understand.
In order to be able to present to every user the correct picture of the more than 1000 different supported router models, the help of the community is needed.
Everyone can take a picture of the backside of their router and annotate the ports on that picture using the annotation-app, I developed (https://vrconfig.gitlab.io/annotator/).

The annotator can be used to mark the location of all ports of the router

 

You could then send in the jpg-file together with the annotation file (which is a json-file) to the luci app via a merge request here: https://gitlab.com/vrconfig/luci-app-vrconfig.
The makefile will automatically choose the right jpg/json file based on their file name during the build process.

The luci application is currently a demo application, which will be improved in the future.
Currently, it looks like this:

You can hover over the different ports, a click will bring you to the corresponding configuration. It also marks those LAN-ports green, which are currently connected with a LAN cable.
For that I developed a lua demon which monitors the corresponding ports in real time and provides the interface with their status.
Also there is list of all currently configured virtual interfaces. Clicking on them will mark the associated physical ports on the image.

Future Plans

In the future I plan to continue to polish the Luci interface. One extension could be to marks those ports, which currently have Internet access. Other extension could revolve around making it possible to configure some setting via drag and drop on the image.

Acknowledgments

Thanks a lot to my mentor Thomas for his excellent support and his long term visions that made this project possible in the first place.
Also thanks to my colleague Benni for his extremely helpful suggestions throughout the project.
Also thanks to Freifunk for letting me work on this project and thanks to Google for organizing GSoC.

The full source code of everything related to this project can be found here: https://gitlab.com/vrconfig

VRConfig Update 2

Hi,

I spent the last weeks mainly developing the LuCI Application for VRConfig. As soon as you want to do advanced things with LuCI, it gets cumbersome.
As the API is mostly undocumented, you have to dig through the LuCI’s source code trying out functions which could be useful according to their name.
It’s a bit of a trial and error game.
Currently the LuCI app does the following.
It displays an image of the router and parses the JSON file, which contains the locations of the components.
With this information it can mark the associated physical ports to the currently selected network interface and display those network ports, which are connected to a cable. You can also hover over the components and click on them, which leads you to their respective settings page.

I also improved the annotation app. It now lets you choose the router name from a list of all currently supported router models of OpenWrt. I got that list with a series of grep and sed commands from the OpenWrt git repository.
For your information, there are currently around 1100 different router models supported. 🙂

In the next weeks I will polish the LuCI Application and try to integrate VRConfig into the openwrt build system to be able to select the correct router image and JSON file at build time.

VRConfig Update

Hi,

I have some quick updates about VRConfig for you.
Short recap: VRConfig aims to introduce a graphical configuration mode for OpenWrt’s Webinterface LuCI.
For that need to collect pictures of the backside of all supported routers. The idea is to do this in a crowdsourcing manner. The community can submit pictures of their routers together with a metadata file which contains the locations of the components on the picture.

I spent the last weeks developing a web application to provide the annotation functionality of the router components.
A working prototype is now ready and can be tested at the following URL: https://vrconfig.gitlab.io/annotator/
Source code: https://gitlab.com/vrconfig/annotator

The annotator produces a JSON file which in turn can be parsed by the LuCI Application to provide the graphical configuration mode.

The LuCI application is being developed right now and will be provided shorty under the following URL: https://gitlab.com/vrconfig/luci-app-vrconfig

More info about that in the next blog post.

OpenWLANMap App: Update 1

Hi,

As I mentioned in the last blog post [0], the first step I did is defining the app’s functionalities[1] and designing the app architecture.

Basically the app contains 1 service, which runs in the background and communicates with UI thread per broadcast (public-subscriber pattern). Since as default, the service will run in the main thread, which is not wanted, I created a ScanThread to handle the scanning. It sends every 2s as default (and should be adapted with user’s speed etc. later) a scan request to the WifiLocator and gets a scan result back from it asynchronous. The WifiValidator then validates the scan result as well as the returned location, and puts the valid wifi access point in a WifiQueue. The WifiStorer will take anything from the WifiQueue and writes it to local disk (simple Consumer-Producer pattern). Based on the user’s upload mode setting, the WifiReader will be triggered if uploading is wanted, reads the local disk files in wanted format for uploading and passes it to the WifiUploader. It then uploads the data to any supported project api and as soon as the uploading is successful, the data will be deleted and ranking will be updated.

The next step I did is designing the new UI, got some feedback from mentor and changed it appropriately. Also in the process I defined all the user’s setting options. I spent a lot of time reading the android documentation for parallel processing and made decision for each functionalities, which is relevant for the next part. (WifiStorer, WifiReader: normal Thread, WifiUploader: AsynTaskLoader etc.) I write more about it in the next post.

Finally I jumped into implementing. I started with the demo mockup and then slowly implemented the logic part. I have finished the scan service and a part of the WifiValidator.The WifiLocator uses gps for defining location if available, otherwise it makes a request to openwifi.su with the surrounding wifis. I provided methods to do it with both new and old openwifi.su api in case we want to use any of them in the future. I ran into an android bug, where the wifi scan result is always 0 if the user disables GPS, even the location permission is granted.(Tested on Android 6). It is kind of weird because scanning wifi does not have anything to do with the gps and turning on gps the whole time will cost phone a lot of energy. Still it’s kind of wanted feature from Android to make users aware that their location information is being accessed when they use kind of app. Because the location of user’s phone could be defined based on the collected wifis. Since it is OS design, I pop up users a message with those information to ask them to turn on their GPS if they turn it off. I also implemented a part of WifiValidator, the WifiFilterer to check if an access point is openwifi, from freifunk or mobil hotspot or marked with _nomap (which should not be collected).

What’s now?

If you want to check the app, feel free to download install file .apk from [2].

If you as usual do not want to install an unknown source, I also provide a short demo video

 

What’s next?

In the next time, I will finish the WifiValidator, which should not only filter the access point but also validate the location to provide scan service a better scan period to save energy (in case the location is not changed for a long time, the scan service should be stopped etc.) and then other parts as shown in architecture image above.

Links

[0] https://blog.freifunk.net/2018/05/14/introduction-openwlanmap-app/

[1] https://github.com/openwifi-su/OpenWLANMap-App

[2] https://androidsmyadventure.wordpress.com/2018/06/03/openwlanmap/

 

VRConfig – Visual Router Configuration for OpenWrt

Hi,

I am Tobias, a Computer Science student at the TU-Berlin. This is my second time participating in GSoC for Freifunk.
I am excited about this project as it helps to reduce the entry barrier for inexperienced users of OpenWrt and its web interface LuCI.

When you look at the current LuCI Webinterface you will notice that it looks fairly decent, especially with the Material Theme.
However for an inexperienced user without a technical background it surely looks scary. All the text full of technical terms with few pictures can look like a book with seven seals.

This project aims to introduce a graphical configuration mode.
To make the configuration interface more connected to the actual router the user owns, we want to display an image of the backside of the ports in the web interface.
The user shall be able to interact with this graphical representation of the router by hovering and clicking on the different parts like LAN ports, antenna etc.

What are the necessary steps to archive this goal?

First, we need pictures of the backside of all the different router models. Here the idea is to collect them via crowdsourcing by the community. Everyone can take a picture of their router and upload it to a Git repository. Also, the location of of the router components must be marked on every picture. For that I will develop a small application which allows the user to annotate a router picture and generates a metadata file.
Second, the annotated pictures need to be integrated into the OpenWrt buildsystem.
Third, a LuCI application needs to be developed to display the result as an interactive graphic in the web interface.

In the next blog post I will go into more detail on the individual steps as well as update you about the progress.

Introduction: OpenWLANMap App

Hi,

My name is Lilli and I am studying technical computer science at the 6.th semester in Hamburg, Germany. In this summer, i will work on a new wardriving app for openwifi.su

OpenWifi.su is working on wifi positioning system. It uses an android app called OpenWLANMap App as the wardriving tool to collect wifi access points and sends it with the geolocation of the phone to the backend. The backend stores the data in database and also offers an API for non-GPS devices to request their positions based on the surrounding wifis.The backend currently uses triangulation technique on the numbers of access points it receives from the request device to calculate it’s geolocation.

A data entry from the wardriving app is currently BSSID + LATITUDE + LONGITUDE, which is stored temporarily effectively in local disk with 28 bytes (12 bytes for 12 characters of the MAC Address, 8 bytes for each latitude and longitude) before being uploaded to backend. The wardriver can do it manual or automatically. The app respects _nomap Wifi APs and does filter out some mobile hotspots on public transportation in europe. Unfortunately the app is hardly out of date. There are no developers working on the app and no updates for years. It does not run in new android devices. The OpenWifi.su has an amazing community of wardriver, over four thousands people. They have to keep very old phones to be able to run the app. But this community began to shrink in fact because peoples buy new phones which are not able to run the old app anymore.

I am so glad to get involved in the project and can spend my Google Summer of Code rewriting the app. Thank to freifunk community I was allowed to participate in the Wireless Community Weekend in Berlin in the community bonding period and had the chance to present my project, as well as talk to people about it and possible solutions for many problems. I spent the last weeks analysing the old app code and was talking a lot with my mentor about the old app performance and functionalities and ended up with many important decision about the design for new app. Here are some of them

  1. Wlocator is a service of getting GPS either from the device itself. In worst case where the GPS is undefined, it will send a request with the surrounding wifis to the Openwifi.su backend to ask for it’s geolocation. The service will run every n seconds
  2. Wifiscan is a service of scanning wifi access points. All the data of the AP such as BSSID, SSID, RSSI, frequency, channel , encrypted method, scan timestamp etc. will be scanned and display as user’s option. Necessary data will then be stored temporally local and later on uploaded to the database. The service will be stopped if the GPS of the device isn’t changed after n seconds in order to save device’s battery.
  3. Wififilter helps filter out: _nomap, mobile hotspot ( Call for help to collect mobile hotspot from different countries), ad_hoc network (I am working on it), collect open wifi to automatic connect and upload data if possible.
  4. Use trilateration or other techniques to define the location of the scanned AP better
  5. WifiUpload let users upload the data manual, automatic if internet available, automatic if only wifi available
  6. Extension: upload data to different APIs
  7. Saving resouces: stop scan service after n second of not changing GPS, put app in standby/doze mode if GPS does not change after n second, reduce brightness, kill app if battery critic
  8. Different languages available
  9. etc.

The plan for the next three months will be:

  1. Design new architecture for new app functionalities
  2. Design new UI
  3. Implement all logic functionalities
  4. JUNIT test + documentation

Stay tuned, I will update it soon.

L3I2