Pixel 1 data recovery.. (backup your data)

Like many parents, my kids have hand me down phones. This is generally a great way to extend the life of a device, and teenagers can be tough on phones. Some more than others.

My oldest has been one of those kids who has been generally gentle with technology, and the devices tend to last. I’ve replaced a few tempered glass screen protectors but those are disposable. I have to admit that I didn’t take the signs of problems seriously when the screen on the Google Pixel 1 started to go black occasionally – a hard reboot often fixed things up. This was just some mysterious software issue I thought.

Nope. It was the early signs of the screen going bad. One day, the screen just stayed black no matter what I did. Did we have a recent backup? Nope, it was many months old. That’s also on me. At the first sign of any weirdness with a mobile device, checking the current backup status should be a high priority.

This device was running LineageOS, and unfortunately the default security is pretty good. Oh, I tried lots of things. Blindly, boot device into fastboot mode. Load a recovery via fastboot – connect to that via adb.. but just not enough magic to get through decrypting the filesystem via recovery without access to the screen. This was back in 2020. I would try from time to time to figure out a way to recover a screen-less Android phone running LineageOS, but it continued to resist my attempts.

The picture at the top of the post is the very busted screen from the Pixel 1. At one point in my recovery attempts I thought – maybe it’s simply that the ribbon cable needs to be re-seated? Despite being careful, I can safely report that removing the screen is very hard and you’re likely to break it. I pretty much destroyed that screen.

I had reached out to a local repair shop, but they only were interested in selling me a complete screen replacement – not helping me hook up a screen and recover the data. I continued to look for economical screen replacement options, but at this point I didn’t even know if the screen was the problem.

Just the other day, I found a pair of used Pixel1 screens for $30 + $10 shipping. This was cheap enough that it was worth the risk. I got lucky, the used screen was exactly what I needed.

Cool. There is hope. The phone battery was very dead, so it wasn’t allowing me to power it on. My initial attempts to power on were also scary, I kept getting “no OS found, corrupted data”. I was able to boot to the fastboot screen, but not able to start the recovery image (if there even is one?).

After a few minutes of charging, and more attempts to boot – it started to load!

I was so happy to see the LineageOS boot screen. Now I was crossing my fingers hoping I’d get a full boot without problems. This next image increased my joy.

The touch screen worked fine, and I was able to log in. I was so close to being able to recover the files from this phone, but I had to let it charge up.

Once it was charged, unlocking the phone and connecting a laptop to it was trivial. I was able to pull down the 900+ photos and push them up to my fileserver for safe keeping. In the end it took a couple of years to recover, but I’m glad I kept at it. I also was very lucky that it was only the screen.

Go backup your data. Better yet, invest the time to create a regular backup system. Test your backups.

Running Selenium testing in a single Docker container

Selenium is a pretty neat bit of kit, it is a framework that makes it easy to create browser automation for testing and other web-scraping activities. Unfortunately it seems there is a dependency mess just to get going, and when I hit these types of problems I turn to Docker to contain the mess.

While there are a number of “Selenium + Docker” posts out there, many have more complex multi-container setups. I wanted a very simple single container to have Chrome + Selenium + my code to go grab something off the web. This article is close, but doesn’t work out of the box due to various software updates. This blog post will cover the changes needed.

First up is the Dockerfile.

The changes needed from the original article are minor. Since Chrome 115 the chromedriver has changed locations, and the zip file layout is slightly different. I also updated it to pull the latest version of Selenium.

ChromeDriver is a standalone server that implements the W3C WebDriver standard. This is what Selenium will use to control the Chrome browser.

The second part is the Python script tests.py

Again, only minor changes here to account for changes in Selenium APIs. This script does do some of the key ‘tricks’ to ensure that Chrome will run inside Docker (providing a few arguments to Chrome).

This is a very basic ‘hello world’ style test case, but it’s a starting point to start writing a more complicated web scraper.

Building is as simple as:

And then we run it and get output on stdout:

Armed with this simple Docker container, and using the Python Selenium documentation you can now scrape complex web pages with relative ease.

Update: Managing docker containers with makefiles

I’ve been a bit of an old school “just use docker” vs. “docker-compose”, but it was the other day when I learned that they’ve now baked “compose” into the base docker cli. This means there is less reason to avoid using the features of docker compose.

Still, as previously discussed, I like using Makefiles to manage my containers. There is a very good argument to adopt using Watchtower, despite it being not recommended.

We do not endorse the use of Watchtower as a solution to automated updates of existing Docker containers. In fact we generally discourage automated updates.

Let me go on record that if you’re going to blindly run your update process, you may as well just use Watchtower. This is a good way to automatically break things of course, so maybe don’t auto-update things that you rely on to work (like wireguard or your web server).

With that out of the way – let me point out one of the downsides to my previous Makefile approach to managing containers: I’d slowly run out of disk space with many old images. I had gotten into the habit of running

every once in a while. This would get rid of all the containers, and images, that were no longer active. It did have the downside of removing images that were not currently running – so you need to be aware of that if you had assumptions.

Still my makefile approach saved me a few times allowing me to easily re-name / re-run the -old version of a container and back out of a bad update.

What I needed to do was make sure that the old, -old image was removed. This was where most of the disk space growth was. This turns out to be easier to do than to explain. Here is my update makefile

There are only two new lines. The first is

This is assigning the variable IMAGEID to have the docker image id value from the current -old image.

The second is the obvious removal of the image based on that id.

I believe that these two additional lines result in nearly no filesystem growth as I update images. Very handy as some of the linuxserver.io images pull down ~1GB of data every time, and they are updated weekly.