A year ago, I found a very good Black Friday deal on the Redmi Note 9 Pro from Xiaomi. The phone boasts some very interesting specifications, most notably:
- 6GB of RAM
- A very respectable battery size of 5020mAh.
- An 8 core SoC with six efficiency cores and two performance cores clocked at 1.8GHz and 2.3GHz respectively.
Additionally, the phone sports a 3.5 audio jack, and a microSD slot with a capacity of up to 512GB, both a rarity in modern phones1. These specifications were rendered all the more attractive considering the discounted of price of 199€.
Xiaomi has built a reputation for itself of offering very competitive devices at even more competitive prices. However, such competitive prices are probably being subsidized through other monetization channels. In fact, some estimates put Xiaomi’s margins on its smartphones to be around 2$ per device2. Furthermore, preloaded apps and services account for a non-negligible percentage of Xiaomi’s revenue3.
Previous devices from the company were revealed to record users private data. The collected data included the directory structure of the internal storage, settings, and even changes in the device’s status bar4. In a “best case scenario”, the data gathered through these means could be used to serve personalized advertisements to the users. Of course, even in such a scenario, personal data will end up being traded and sold to all kinds of brokers and third parties, with questionable considerations for the users privacy. In a much darker scenario, one must consider ties Xiaomi might have to the Chinese government5, and what effect such possible ties could have on data collected by the company. In both of these scenarios, and every possible scenario in between, users privacy would be put greatly at risk, a risk not worth the price difference in comparison to other vendors.
With these issues clearly known to me, why did I still purchase this phone? The only reason I decided to go for the Redmi was its support by the LineageOS project6. Meaning I could take the device, delete the OS it shipped with along with all the tracking and privacy violating software, and install a blank slate of an operating system. To me, this was truly a golden opportunity to get the best of both worlds: a feature rich phone at a very discounted price, running free and open software with none of the tracking or in-OS advertising the vendor is trying to force on me.
Previously, I had already flashed LineageOS on a couple other phones I owned, and as such, was confident in my ability to do the same this time. As it turned out, these previous experiences had not prepared me enough to the myriad of issues I faced while trying to achieve the same result for my newly purchased Xiaomi phone. In the following is a listing of these issues.
Issue: The bootloader unlocking process
Installing LineageOS on the Redmi Note 9 Pro is well documented on the device’s page in the LineageOS wiki7. As with most other phones, the first step in installing a different OS than the one the device ships with is unlocking the bootloader. I had already conducted this process on a couple other phones from different vendors, and never had any issues with it. However, this time, the process was far from straight-forward.
In order to unlock the phone’s bootloader, one needs to use the Mi Unlock app, which is a Windows’s only executable. As if installing a closed-source piece of software on your computer as a requirement to unlocking your phone was not enough, the Mi Unlock App requires one to create a Mi account on Xiaomi’s website. To make things even worse, creating a Mi account, requires an email address (which is expected) and… a phone number.
Phone number requirement
Requiring the user’s phone number is a very invasive thing. This is because phone numbers are usually linked to more private user information. Such information might include a first and last name, address, bank account or last digits of the credit card used for monthly payments. Although this information is kept by one’s service provider, security breaches which might cause it to be leaked to the public are routine at this point. Furthermore, a multitude of companies and services make use of phone numbers as identifiers making it all the riskier to have this information fall into the wrong hands8. A good indicator of such a risk is perhaps the rise in SIM-swapping attacks in recent years9.
For all the reasons listed above, I was not about to use my real phone number to create the Mi account needed to unlock my device. Sadly, being able to buy a SIM card without giving away your identity is a thing of the past where I live. As such, I went for the next best option available to me, and ordered the cheapest SIM card from my service provider, since they already have my data anyway. This new SIM card would be used for the sole purpose of creating my Mi account, and nothing else.
Mi Unlock App
Creating a Mi account is simply the first step in the process of unlocking the bootloader. Next, the Mi Unlock feature needs to be activated on the phone itself. This feature requires the use of the Mi account on the phone, and for the phone to access the internet through the cellular network (i.e. using the SIM card). Once that is done, the phone needs to be connected to a computer running the Mi Unlock app. Requiring users to run an executable of unknown origin on their computer is also a very invasive and risky thing. Thankfully, I was able to mitigate this risk by using a blank Windows virtual machine, which I only used for the purpose of unlocking this phone.
Having now a (virtual) machine running the Mi Unlock app, the next step was to connect the phone to it and follow the bootloader unlocking instructions from the LineageOS installation guide. In order for the app to function correctly, the correct USB drivers need to be installed. The LineageOS installation guide links to a corresponding page on Google’s Android developers documentation website. The page itself links to another section in the documentation which covers OEM USB drivers. There, a table with a list of links for the drivers of different vendors is provided. In the case of Xiaomi, the link leads to a post on the Xiaomi Forum, which itself finally contains a direct download link (I am not linking to either of those two links here for the reason explained in the next paragraph).
Having to go through all these steps feels unnecessarily complicated, and I haven’t mentioned the worst part yet:
The final direct download link is over HTTP, and not HTTPS!
Meaning you are somehow expected to install a driver found in some obscure forum, and you are given no way to make sure the source of this driver is legitimate. I wouldn’t subject any of my systems to such a risk, not even a virtual machine.
Thankfully, after looking around for alternatives I found a more palatable solution. When first launching the Mi Unlock app from the Xiaomi website, it quickly detects that a more recent version of the software is available and prompts the user to download it (See Figure 2). Getting passed the fact the the notification is partly in Chinese (perhaps Mandarin?), one can click the one button to download the newer version of the app. Going through this process, the newer version is still downloaded through HTTP and not HTTPS. However, the download can be forced to use HTTPS (e.g. by forcing your browser to use HTTPS-only mode).
The newly downloaded archive contains an additional
MiUsbDriver executable (See Figure 3). When launched, the executable installs the required drivers correctly to the system. Even going about this process this way, one is still running closed-source executables on their machine, but at the very least, one can make sure that they originated from Xiaomi’s own servers and not from some attacker spoofing Xiaomi’s domain-name.
Once the drivers are correctly installed, and the Mi Unlock app launched, I was able to move forward with the unlocking process, at which point I was faced with the final hurdle in the road to freeing my device.
The waiting period
The final nail in the un-necessarily complicated coffin of unlocking the bootloader on my Xiaomi phone was the mandatory waiting period. After connecting the phone to the Mi Unlock app, a first verification step is conducted, following which Unlocking is initiated. However, the unlocking quickly fails, prompting the user to wait and try again after 168 hours (that’s 7 days!). Figure 4 shows a photo I took of the unlocking error message, I did not think of taking a screenshot, and had only took the photo because I wanted to share my indignation with a friend.
Xiaomi probably has some nice sounding argument about how this waiting period (along with the very scary-sounding warning messages displayed in the app before the final unlocking step) is for the security of their users. However, blocking users from having full control over devices they have paid for, is never acceptable, no matter how many arguments companies try to throw on their customers to convince them otherwise. Additionally, in my opinion, this is more reasonably a deterrence tactic to dissuade as many people as possible from using different software than the one their device shipped with in the hopes of better protecting their data.
After waiting for the 7 days period, I was able to reconnect my device to the Mi Unlock app and to complete the unlocking process. With the unlocking done, I could delete the virtual machine I had used for this whole process, delete my Mi account, and cancel/throw away the SIM card I had used for the process.
Issue: No pico Open GApps package
Having unlocked the bootloader on my phone, the next step according to the LineageOS installation guide is to install a recovery into the device, re-boot into it, and sideload the LineageOS package7. This process was pretty straight forward, and Figure 5 showcases a photo I took of the Xiaomi phone during the sideloading step. After sideloading the LineageOS image, one can install additional packages before proceeding to the first boot. In the case of Google Apps, the installation is in fact required to take place right after the LineageOS image has been installed and before the first boot.
On Google Services and their unfortunate necessity
The irony of going through all the trouble of replacing Xiaomi’s OS with LineageOS in the name of privacy, only to end-up installing Google Apps is not lost on me. However, it sadly is near impossible to get much use out of a smartphone these days without some form of Google services. In the past, I had managed to use a smartphone with no Google Apps at all, finding good alternatives to practically every google service. In particular, I managed to replace the Play Store with F-Droid, Google Maps with OsmAnd, and Google Drive with Nextcloud. With some getting-used-to, these alternatives work as good as the Google products, and with much improved data protection and privacy. The issue however, comes when it is time to use financial or banking applications. These are usually only available on the Google Play Store, and in some cases would simply refuse to launch if they do not detect Google Services on the device. For this main reason, I regrettingly resort to installing Google Apps on some of my devices even after flashing LineageOS onto them.
The Open GApps project
The Open GApps project provides automatically generated and up-to-date Google Apps packages. The most attractive feature of the project, is that it offers several variants of Google Apps. These variants range from the
super variant, which basically contains every Google Application ever shipped on a Google device, all the way down to the
pico variant which contains the bare minimum necessary to make use of Google Play functionalities10. This variety allows for great flexibility, and for the last few years I have been using the
pico variant whenever I had to use Google Services on my LineageOS devices.
When it came time to install Open GApps on my Xiaomi device, I was disappointed to find that the Open GApps project, only had support for Android version
11.011. Meanwhile, the version of LineageOS available for my device was
19.1, which corresponds to Android version
12L. Here I had two possible options to move forward:
- Option #1: There currently is an open issue in the Open GApps GitHub page specifically concerning support for Android versions
13. It seems that the issue has been fixed and committed to the master branch. The only reason why this is not reflected in Open GApps download page seems to be due to the lack of automated builds for these versions. As such, it is totally possible for me to clone the repository, and build an Open GApps image of the
picovariant that supports Android
12Land would be compatible with my LineageOS installation.
- Option #2: Open GApps is not the only project which maintains Google Apps images. Another popular project is the MindTheGApps project, which is officially supported by LineageOS11. The project currently provides images up to Android version
13. The downside, is that MindTheGApps does not offer as much flexibility as Open GApps does. In fact, for every Android version, a single package is offered which contains the same applications as the
nanovariant of OpenGApps11.
I opted to follow the path of least resistance and chose to go with option #2, reserving option #1 as a possible future learning exercise.
Issue: Reduced Camera functionality
After finalizing the installation of LineageOS and Google Apps, I was able to boot into the new OS and start testing its different functionalities. At this point I was faced with the final issue in this whole process: The huge drop in camera performance.
The default Camera application which ships with LineageOS cannot take full advantage of the device’s hardware. Specifically, the resolution of pictures taken using the default camera app did not match the 64MP advertised for the main camera, and none of the wide-lens or macro-camera features were available. Admittedly, this was to be expected: The default camera application is built to be operational on all devices supported by LineageOS project. The developers cannot afford the time and effort necessary to build a separate camera application matching each of the hardware configurations of the multitude of devices for which they offer support. In fact, most of the time such a task is not even possible, seeing how device manufacturers keep their firmware close-sourced.
Thankfully, a solution exists in the form of the Google Camera application. The app was initially developed by Google for all android devices, before only being officially supported on the Pixel series of phones12. The app makes use of the Camera2 API to interact with the camera hardware13 and packs a multitude of post-processing algorithms which go a long way in improving photo and video quality. A very active developer and modder community has grown around the Google Camera app (more colloquially known as GCAM), porting it to a multitude of other devices that already support the Camera2 API. This community also developed device-specific tweaks made available through in-app-loadable XML configuration files14. As it turns out, a GCAM port for my Redmi Note 9 Pro, along with a fine-tuning configuration file does exist15. The port is hosted on the GCAM Hub, which I learned to be the main hosting platform for all GCAM ports.
This is where I was again faced with a dilemma, similar to that of needing to install Google Services after purposefully replacing my device’s stock Android image with LineageOS: The ports hosted on the GCAM Hub are binaries which have been created by manipulating the original Google Camera application image and adapting it to different devices not originally supported. Installing such images, implies trusting the modder not to have introduced any malicious functionalities into their port. Furthermore, one also needs to trust the host of these images (in this case GCAM Hub) to also have preserved the images as created by the modder and to not have modified them in a malicious manner. These are some very though asks, especially in a world of ever new, more complex, and more surreptitious vulnerabilities and attacks. There are multiple links to the chain of trust one must have faith in before installing a GCAM mod, and here are my thoughts about them:
- The modders: A group of main modders seems to have built itself a good reputation within the community of Android ROM hobbyist. These modders have been continuously delivering ports of GCAM, but also ROMs and other images to the community for years now without any complaints about possible maliciousness (or at least none that I could find). Of course, all it needs is a single compromise from a single modder for this trust to be violated, but so far this system of “community built reputation” seems to be working. The GCAM port I found for my device was modded by BSG whose work I have seen regularly being praised on hobbyist forums and websites.
- GCAM Hub: As mentioned earlier, this is the most popular hosting website for GCAM ports. The owner of the website started archiving Android-related content after the shutdown of CyanogenMod in December 2017, at which point he needed a place to host content he deemed useful for himself and potentially others16. According to him, he had also been a user of GCAM since 2017, and started hosting GCAM APKs too after getting frustrated with previously available means of hosting (See posts he had previously made on Reddit here and here). The GCAM Hub comes with a very explicit safety warning, acknowledging the trust issues which comes with installing binaries from unknown sources17. Although the risk still remains, this acknowledgments, in addition to online history of the maintainer of GCAM Hub are at the very least reassuring.
- The port itself: Finally, I have tested the port myself on my device right after installing LineageOS and before loading it with any of my personal data. The permissions required by the application (file access, microphone and camera) are nothing out of the ordinary. Additionally, Android 12 (the version upon which LineageOS 19.1 is based) allows to enable and disable camera and microphone access for all apps on the device from a toggle option available on the status bar18. This too, gives some additionally assurance.
Taking into account the considerations above, I have weighted the risk of malicious code making it into the GCAM port available for my device, alongside the damage such possible malicious code might cause to my device. Although I do not like it, I have still opted to take that risk and make use of GCAM on my device instead of using the default LineageOS Camera application and wasting the capabilities of my device’s hardware.
Reading back through this article, it certainly feels like this whole process has been nothing but a series of compromises. A phone number that can be linked to me is now stored in some database on the other side of the planet, I have had to install more Google Services on my device than I am comfortable with, and I needed to install an app from possibly untrusted sources to get full functionality of my device. Attempting to turn my Redmi Note 9 Pro into a more privacy-respecting device has required me to make a concession at every step, and I am not sure I have achieved what I had initially set up to do. For these reasons, I cannot in good conscience recommend this journey to anyone else who is considering embarking on it.
My experience with the Redmi Note 9 Pro, can probably be extrapolated to other Xiaomi devices, so if you are considering purchasing one and installing LineageOS on it, you probably will face similar issues to mine. I will be using my new Redmi phone as a backup/second phone, and plan on passing it on to a friend or family member who do not have as many privacy concern as I do, and who probably are using an even less privacy-mindful phone.
Finally, As of recent years, I have been looking into other options to improve the security and privacy of my mobile experience. Following this whole ordeal with the Xiaomi phone, the GrapheneOS project is looking more and more like a better approach to security than LineageOS so I might try it next. If I do end up trying it, I will make sure to cover it in a future article, so stay tuned for that!