How to setup boot on charge on TB-8504X/F running Nougat

Note: The Oreo ROM for this device supports fastboot oem off-mode-charge 0 This tutorial is for the Nougat ROM.

I was able to get it to work by updating the init.rc file

I found the on charger trigger and added the following lines below it:

setprop ro.bootmode "normal"
setprop sys.powerctl "reboot"

The entire trigger block ends up looking like this

on charger
    class_start charger
    setprop ro.bootmode "normal"
    setprop sys.powerctl "reboot"

You then need to repack and flash the boot image created after the updates.

Connect the device over USB

Power on device and get to bootloader mode

adb reboot bootloader 

To flash boot image execute the following command while in fastboot

fastboot flash boot new-boot.img

Note: This fix will cause the device to reboot when its plugged in even when shutting it off using the power button or software shutdown.


You can see the commit that contains these changes for my project here:

How to build TWRP for the TB-8504X/F

I recently started a project to build LineageOS for the Lenovo TB-8504X/F. Part of the journey typically involves building a custom recovery. TWRP is now the defacto so I started there.


  1. An Android build environment: or something like
  2. Repo Installed:


  1. Create a working directory and cd into it
    • mkdir twrp && cd twrp
  2. Check out limited manifest for building TWRP
    • repo init -u git:// -b twrp-7.1
  3. Sync
    • repo sync
  4. Make a directory for the tb_8504x device inside the repository directory and cd into it
    • mkdir -p device/lenovo/tb_8504x && cd device/lenovo/tb_8504x
  5. Clone the recovery source into the tb_85004x directory
    • git clone
  6. Go back to the top level directory and lets start to build
    • source build/
      lunch omni_tb_8504x-userdebug
      mka recoveryimage

If everything goes well you should have a recovery image available in out/target/product/tb_8504x/

Big thanks to

You can find the final output and a continuing thread here:

Tips and Tricks with Flutter HTTPClient

On a recent project, I had the opportunity to use the HTTPClient to integrate with a medical device. During the integration, I learned a few things that are not immediately apparent from the docs and wanted to share what I learned with you all.

Sometimes you need to use Charles Proxy to debug what is happening. The HTTPClient ignores proxies by default. We can modify the HTTPClient to use the proxy with the following configuration:

Using a Proxy (Charles Proxy/Fiddler)

HttpClient client = HttpClient();
client.findProxy = (uri) {
  return "PROXY;";

A more advanced configuration that will override a bad certificate check:

  static HttpClient getHttpClient() {
    HttpClient client = new HttpClient()
      ..findProxy = (uri) {
        return "PROXY;";
      ..badCertificateCallback =
      ((X509Certificate cert, String host, int port) => true);

    return client;

Configuring Digest Access Authentication

Basic Authentication is fairly straightforward to integrate, but Digest Access Authentication takes a little more work. Below you can see a sample Digest Access Authentication configuration:

static HttpClient getHttpClient(String userName, String password) {
HttpClient client = new HttpClient()
..badCertificateCallback =
((X509Certificate cert, String host, int port) => true)
client.authenticate = (uri, scheme, realm) {
uri, realm, new HttpClientDigestCredentials(userName, password));
return new Future.value(true);
return client;

The above snippet sets a function on the authenticate property of the client. When a resource the client is connecting to asks for authentication, we will supply HttpClientDigestCredentials to authenticate the request. I found this to work well with GET requests, but would fail with POST requests that included an attachment. This is because the client retries the request once credentials are provided, but it does not include attachments when replaying POST requests

Digest Authentication with POST

To handle the situation with Digest Authentication not working with POST, I created an authentication header that I would send with the initial POST request:

String ha1 = getHA1(userName, "websvc", password);
String ha2 = getHA2("POST", "/1.0/restrictedResource");
String response = getResponse(ha1, ha2, "3a15147c7e97b692f01a78ad53f887cd", "00000001", "SpL0Prz6");

HttpClientRequest httpClientRequest = await client.postUrl(Uri.parse(path));
httpClientRequest.headers.contentLength = csvAttachment.length;
httpClientRequest.headers.contentType = ContentType.text;
httpClientRequest.headers.add("Authorization", 'Digest username="$userName", realm="websvc", nonce="3a15147c7e97b692f01a78ad53f887cd", uri="/1.0/restrictedResource", algorithm="MD5", qop=auth, nc=00000001, cnonce="SpL0Prz6", response="$response"');


return await httpClientRequest.close();

// Helper methods

static String getHA1(String username, String realm, String password) {
List<int> toConvert = [];
return md5.convert(toConvert).toString();

static String getHA2(String method, String url) {
List<int> toConvert = [];
return md5.convert(toConvert).toString();

static String getResponse(String ha1, String ha2, String nonce, String nonceCount, String cnonce) {
List<int> toConvert = [];
return md5.convert(toConvert).toString();

Those are a few tips/tricks I picked up. Maybe they will help you along your journey. Thank you!

Friendly Austin is now over 1200 Members!

Friendly Austin was started almost a year ago and we recently hit 1200 members.

Some of the events I’ve particularly enjoyed are Movies in the Park, Hiking in the Greenbelt, and dancing and listening to swing and Motown music.

The Meetup group has sometimes been a challenge, but I am thankful for all of the experiences that we’ve shared together.

I have posted a few events on It’s Time Texas and am excited to see what ITT has planned for the rest of 2016.

You can join Friendly Austin at this link!

Thank you!

Getting started with Android and CircleCI

Continuous Integration provides many benefits to the software development process. Did I break the build? How many of our tests pass on the latest version? How can we distribute the latest version of our app to our testers smoothly? Continuous Integration can help answer all of these questions.

For those that have been around for a while, there have been many CI tools (CruiseControl) along the road to CircleCI and many are still relevant (Jenkins).

Yesterday, I started looking at CircleCI in depth after watching Donn Felker’s excellent video on and here are a few simple steps to get started with CircleCI and Android.

To start, sign up for a CircleCI account here and sync your Github repositories.

Add a project that you would like to add to CircleCI. CircleCI will try to build your project automatically, but to maintain better control over your CI process you should use a circle.yml file. This file should be placed in the base directory of your project.

A sample circle.yml can be found below. Change the words CriminalIntent to the name of your project and make sure that the build-tools version in the circle.yml matches the build tools version in your build.gradle file for your app module.

Check in the circle.yml file and push it to GitHub.

CircleCI should now automatically build your project!

Screen Shot 2016-05-01 at 6.23.56 PMTo see what a passing build looks like you can check here:

Full source for the project including the circle.yml file and build.gradle can be found here:



Where to put the file on Jenkins

TL;DR: Put your file in the /var/lib/jenkins/.gradle/ directory on a standard Ubuntu install.

Sometimes you need to have a file that is not included in your git repository. Many times this is because you need to have an api key that you would not like to be made public.

Because your file will not be checked into your git repository, the job will fail to build if your api key value is not able to be found.

One way to fix this is by placing your file in a place that jenkins will look for it. By default this location is in the .gradle directory of your Jenkins user.home directory.

To find the user.home directory open the Jenkins console in your browser, click “Manage Jenkins”, and then click the “System Information” link.

Scroll down until you find “user.home”


In this example, the user.home directory is /var/lib/jenkins.

Now that we know this, we need to copy our file that contains our api key to /var/lib/jenkins/.gradle

For example:

sudo cp ~/source/a-caring-text/ /var/lib/jenkins/.gradle/

Change the file permissions so that Jenkins can read the file:

sudo chown jenkins:jenkins /var/lib/jenkins/.gradle/

Now you can build the job that was depending on this api key!


Friendly Austin hit 900 Members :)

We’re about 8 months in and this week we hit 900 members.

We are reaching a critical mass of 1000. Now we’re working on planning the rest of 2016 and enhancing our social media on Facebook and Twitter.

Lastly, Friendly Austin is now working with It’s Time Texas and is excited about what they have planned for 2016.

Thank you! <3

Click this link to join Friendly Austin!

Friendly Austin hit 500 Members :)

After starting about 4 months ago, last week we hit 500 members.

We are reaching a critical mass of 1000. Now I’m working on planning the rest of the year and getting the group setup on Facebook and Twitter.

All I have to say is thank you! <3

Friendly Austin

Austin, TX
2,640 Friends

Friendly Austin is a group dedicated to developing friendships and sharing healthy experiences with each other.We will be exploring all that Austin has to offer including:Hi…

Next Meetup

Adult Skate Night at Playland Skate Center

Tuesday, Jan 29, 2019, 7:00 PM
5 Attending

Check out this Meetup Group →

I started a Meetup Group – Friendly Austin!

After being an event organizer for a few Meetup groups in Austin, I decided to start my own! It’s mainly focused on outdoor activities and music events, but will probably end up having a little bit of everything!

Please join if you’d like!

Friendly Austin

Austin, TX
2,640 Friends

Friendly Austin is a group dedicated to developing friendships and sharing healthy experiences with each other.We will be exploring all that Austin has to offer including:Hi…

Next Meetup

Adult Skate Night at Playland Skate Center

Tuesday, Jan 29, 2019, 7:00 PM
5 Attending

Check out this Meetup Group →

First Code Contribution to Ubuntu was Approved!

Yesterday my first merge request to the Ubuntu project was approved! It is small, but feels great. It’s an automated test that tests the deletion of a playlist from the Ubuntu Music App.

Screenshot from 2015-03-24 17:59:49

Thank you to everyone who has written and published tutorials on how to get up to speed with Ubuntu QA and automating with Autopilot! The Orange Notebook was a great resource. Thank you to everyone who helped me with fix the formatting issues I had. Working on a project this size, I now realize how important it is to keep code structure and syntax consistent.

Link to the commit on launchpad: