I'd really like to be able to enjoy vivid colors on my phone screen. I just can't stand the default washed-out, pale color schemes, which make the OLED display feel like a low-cost TN matrix from over a decade ago.
I realize improving upon the Monet monoculture that G***e seems to be so proud of would be a purely cosmetic endeavor, totally outside the scope of the GrapheneOS project: a suboptimal allocation of scarce resources. I'm not complaining. That being said, what are my options?
Built-in settings
It's possible to craft a special wallpaper (or come upon such by accident) that provides sort-of vibrant colors as one of the choices under Settings → Wallpaper & Style. That's just too random to be an acceptable solution though. It's like playing the lottery.
Ideally, the color settings should be independent from the wallpaper: what happened to just letting the user decide for themselves? While there's the choice for Other colors that boldly encourages me to "choose any color," it turns out this "any" color can only be one of the 16 predefined. (Again, I understand why this is just carried over from upstream as is, I'm stating this only for completeness.)
Live wallpaper
Short of superuser access, there exists a user-space application that approaches the problem in a clever way: by defining a custom live wallpaper (out of any user-selected static image), it is able to set custom colors alongside it. While this works, the application is closed-source and ad-ridden, and there's no way to even pay for a clean version compiled without the AdMob/Google services integration, which puts it outside my solution space.
Setting tweaking over Shizuku
Now, there's another application, ColorBlendr, free, libre and open-source this time, which allows color customization either with superuser access or, in a limited scope, with Shizuku. Switching to GrapheneOS, I am deliberately giving up on superuser access, and Shizuku has negative security and performance implications, which in my view make it unacceptable as well as a solution to an entirely cosmetic issue.
Leaving Shizuku out of it
That being said, these color settings can be controlled in a low-level way by means of modifying the Android settings database, which can be done over ADB. As they persist across reboots, I'm not going to be changing them on a daily basis (so it does not have to be super convenient) and as I'm leaving ADB enabled anyway, using it for a number of other purposes, changing the color settings this way would be an acceptable solution.
(There's a difference between leaving ADB over USB on, especially with GrapheneOS's USB hardening, and allowing ADB over Wi-Fi while concurrently authorizing a user-space application to run all kinds of arbitrary ADB commands. The latter is a compromise I'm not willing to make, at this point it'd make more sense to just use more fine-grained superuser privileges but, as I said, that's something I don't want to do either.)
Manual color setting tweaking with ADB
So it seems the color settings can be trivially accessed from adb shell with:
settings get secure theme_customization_overlay_packages
The value stored there is a JSON string, for example:
{"_applied_timestamp":1752144355000,"android.theme.customization.color_index":"1","android.theme.customization.system_palette":"FFDD00","android.theme.customization.accent_color":"EF2B7C","android.theme.customization.color_source":"preset","android.theme.customization.theme_style":"VIBRANT"}
Of which:
_applied_timestamp in _micro_seconds can be trivially generated on device with bc -e "`date +%s` * 1000" or date +%s | bc -e 'read() * 1000'
- An even simpler approach of
$(($(date +%s) * 1000)) should also work in theory but in practice this seems to exceed the integer bounds and yields a negative number
android.theme.customization.accent_color seems to be a legacy setting that doesn't matter since Android 13
android.theme.customization.system_palette is the upper-case, hexadecimal, RRGGBB color value that can be set arbitrarily this way
android.theme.customization.theme_style is one of: EXPRESSIVE, FRUIT_SALAD, RAINBOW, SPRITZ, TONAL_SPOT, VIBRANT and determines in which idiotic way the other colors will be calculated in relation to the only color the user was generously allowed to decide for themselves
So while the scope of customization here still leaves much to be desired, when written back with:
settings put secure theme_customization_overlay_packages '[...]'
The changes take place immediately without any further ado, so at least that's good news.
Concluding thoughts
Sharing the above maybe helps someone who, like me, appreciates being able to set their own colors – especially without having to install tons of third-party applications for that purpose. And if anyone's aware of a better, more common-sense approach to the problem I described, please feel free to let me know.