The Treehouse Blog

Automated hotspot control on the Nexus 5x, continued: Android 7.1.1

on Jan.23, 2017, under Android

I’m in the habit of manually upgrading the OS on my Nexus 5x for each monthly update of the AOSP from Google. I root my phone, and from some past experiences, don’t bother trying to apply the OTA updates. I also reinstall my HSC (hot spot control) application in /system/priv-app each time, and then run it through its paces – I use an NFC widget to do an almost-end-to-end test of my automation with Macrodroid. When I see the WiFi icon disappear, the LTE connection come up, and the hotspot icon appear, I know I’m good to go.

Until recently. On Saturday morning, I was trying to get Google navigation to work in my car. It showed that it was connected to the AP, but it acted like it did not have data. Manually cycling the hotspot on the phone solved the problem. I dismissed it as a fluke. Then on Sunday, the exact same thing happened. The fact that the WiFi was showing connected had me thinking there was something wrong with the car radio instead of my hotspot. I tried it at home with my NFC widget and laptop… and the laptop would connect, but it would never get an IP address. Manually enabled it would. So… again there is something that has changed with the (private) hotspot APIs in Android. Since my testing method didn’t catch it, I’m not certain which version it broke in, but 7.1.1 seems to be a reasonable guess.

The method I had been using, setWifiApEnabled() would bring up the access point mode, but it would not set up the other network services needed to tether traffic. I found this git log entry that seemed to be relevant:

commit 26bd4efcaaad4a866310d6421909645e81167d1f
Author: Christopher Wiley
Date: Wed Jul 13 19:36:03 2016 -0700

TetherUtil: Use ConnectivityManager for tethering

In the past, enabling the SoftAP would cause tethering to happen because
of some unfortunate side effects. This is no longer the case, and
using WifiManager for this purpose is not a good idea.

With some more poking around, I found that the ConnectivityManager class now (well, it looks like the code is from Jan 2016, 36c7aa03255d91cfa0808323ac475ad02d161d7d) has startTethering() and stopTethering() methods, which handle the necessary service startups. After a few more annoying attempts (my workflow to test this is to reboot the phone in recovery, apply the update, reboot in system, and then try it… do I really need to do that?), I dialed in some reflection that seems to work (AndroidStudio annoyingly can’t see @SystemApi stuff, and it seems non-trivial to fix it), and found that I additionally had to give myself ACCESS_NETWORK_STATE and MANAGE_USERS permissions. The relevant code (which is not as clean/safe as it could be) now looks like this:

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
final int TETHERING_WIFI = 0;

if (enableHotspot) {
Method startTethering = null;
for (Method method : cm.getClass().getDeclaredMethods()) {
if (method.getName().equals("startTethering") && (method.getParameterTypes().length == 3)) {
startTethering = method;

startTethering.invoke(cm, TETHERING_WIFI, false, null);
Method stopTethering = cm.getClass().getMethod("stopTethering", int.class);
stopTethering.invoke(cm, TETHERING_WIFI);

The updated APK is here.

And Google… how about giving us a public API for controlling the mobile hotspot? Please?

Comments Off on Automated hotspot control on the Nexus 5x, continued: Android 7.1.1 more...

Automated hotspot control on the Nexus 5x

on Feb.07, 2016, under Android

There are few things more frustrating than when an upgrade causes the loss of features you depend upon.  In the case of my upgrade from the Nexus 4 to the Nexus 5x (and therefore from Android 5 to 6, ahem, Lollipop to Marshmallow) I lost my automation that would enable the WiFi hotspot while in my vehicle.  Tethering works fine by enabling it through Settings, but it generates an error when enabling it with Macrodroid.

Enabling the hotspot is not something that is accessible from a public API, so the ordinary method seems to be to use reflection to make the change using the private API.

From setWifiApEnabled(), eventually enforceTetherChangePermission() is called in This method checks if config_mobile_hotspot_provision_app is set, and if so, requires the CONNECTIVITY_INTERNAL permission which is only granted to system applications.

The cause of my problem, therefore, seems to be that “Entitlement APP provisioning for Tethering” (config_mobile_hotspot_provision_app) is enabled in the Nexus 5x-specific configuration for at least my mcc/mnc, and was not present on the Nexus 4.

After not finding any other applications or configuration to solve this problem, the path I went down was to create my own system application with the CONNECTIVITY_INTERNAL permission, to see if it could enable the hotspot. I was successful, so I implemented the application as a Locale plugin (i.e., quickly hacked it together with the example plugin) so that it could be called directly by Macrodroid. This seems to be working fine. You can (at your own risk) download it here and then you will need to move it into /system/priv-app for it to get the privileges of a system application, probably using your recovery image (TWRP, for instance).

It may also be possible (and perhaps better) to resolve this by removing the config_mobile_hotspot_provision_app configuration, after which it should be possible to use the native Macrodroid hotspot actions, as described here, but I’ve not tried it yet for myself.

Update 2016-09-10: For Android 7 / Nougat, the permission required is now TETHER_PRIVILEGED, but otherwise the above method still works. An updated APK is here.

Comments Off on Automated hotspot control on the Nexus 5x : more...

Pennsylvania Game Commission and Hiking

on Feb.16, 2015, under Hiking, Politics

Over the past year or so, there has been the occasional threat of the Pennsylvania Game Commission requiring permits for and partially banning hiking on State Game Lands.  As someone who grew up with Game Lands literally in the back yard, I’ve been following this with concern.

Naturally, media coverage is abysmal, but at least it exists.  But fortunately, the PGC does post its meeting minutes.  Reading from the September minutes (the January minutes are not yet posted… does that wait until they are approved at the next meeting?), the most vocal dissent of the proposal came from Commissioner Martone:

Before this proposal comes to a vote, I want to make it clear the details surrounding this proposal.  As of last Thursday there were 869 comments from hunters and non-hunters opposed to this, while 197 were in favor.  That’s the initial count.  I will admit, that includes 597 Rails-to-Trails comments that were all opposed.  Key legislators, including take 25 member at a House Game and Fisheries Committee and two other legislators are opposed to this.  The Governor’s Advisory Council for hunting, fishing, and conservation unanimously opposed this.  Our key conservation partners, including the Western Pennsylvania Conservancy, National Wild Turkey Federation, United Bow Hunters of Pennsylvania, Pennsylvania Federation of Sportsmen’s Clubs, all opposed to this.

Major organizations representing the Pennsylvania Equine Council, Pennsylvania State Snowmobilers Association, International Mountain Bikers Association, Keystone Rails-to-Trails, all opposed to this proposal.  And most important of all, this issue is opposed by the Pennsylvania Game Commission itself.  From the field staff, regional staff, headquarters staff and even senior administration, all oppose this proposal.

I would encourage everyone following this issue to pay close attention to the results of today’s vote and pay attention to who voted and how they voted, I think it’s important.  Thank you.

But Commissioner Martone no longer has his position.  He was replaced by a new Commissioner as one of Governor Corbett’s final acts.  Ostensibly, it was administrative issue – his term was due to expire, and his replacement was named.

Now, we do know that the revised proposal was removed from the agenda of the January meeting.  But it seems likely it’s not dead and buried, and in some form, it will resurface again.  In the meantime, you may want to let your opinion be known on this, through the PGC, PA legislature, etc.

I’m starting to think that my preferred solution would be for all of the State Game Lands to be ceded to the Bureau of Forestry, which of all of the state lands, seems the most accommodating of all uses of public land.  Now, you can cry about Game Fund money having been used to purchase all of this land, but really – with 1.5 million acres already… can’t you give some of us folks who would like to privately buy some land a chance?  Perhaps the license fees need to start contributing back to the state’s general fund, instead of contributing to the Game Commission’s empire building.  I’m sure there’s lots of red tape that causes it to be the way it is (which has Federal fingerprints all over it with money from the Firearms and Ammunition Excise Tax involved).


Comments Off on Pennsylvania Game Commission and Hiking : more...

2014 Read List

on Jan.02, 2015, under Happenings

What did I read in 2014?

Not as much as I should have.  I have a lot of books on the queue, and just didn’t spend a lot of time reading this past year.

The Three Investigator’s (read these from the library as a kid; building my own collection now and re-reading them as I get them):


  • The Liberty Amendments: Restoring the American Republic (ad)
    • Levin presents some interesting ideas on constitutional amendments, many in support of providing for additional checks and balances in the system.
  • One Second After (ad)
    • Forstchen provides an account of how a small town is affected by an EMP attack on the United States.  While I’m hopeful that the situation would not be as bad as the author supposes, it is a compelling story about how we would react to having most of our technology suddenly stripped away.
  • Lila: An Inquiry into Morals (ad)
    • Interesting, but to me seemed to end without concluding much useful.
  • The Martian: A Novel (ad)
    • The best book I read this year.  Take the premise of Apollo 13 – bad stuff happens, and lots of problems need to be thought out and worked around to stay alive and get home.  The book fully embraces the technical aspects of things, and reminds me a lot of a Michael Crichton novel.
    • (ad)


Comments Off on 2014 Read List more...

cp210x on TH8581GA

on May.06, 2013, under Linux


I have an Android car radio, and this OBD2 to USB adapter (ad).  Unfortunately, the rooted firmware currently available does not provide a cp210x kernel module that is needed to make this adapter work.  This article tries to describe the process of building and installing one.  Much of this article draws on the more general Building a Linux kernel module without the exact kernel headers and adds specifics for this particular purpose.  I strongly suggest reading that article for more of the technical details.  I don’t doubt there may be easier ways of accomplishing this, but these steps (produced through much trial-and-error and false starts) did work for me.


If you don’t need or want the how or the why, install this cp210x.ko in /system/lib/modules and run this update to change the init scripts to load it.  Use at your own risk – if you brick your radio, don’t come blaming me.  This expects you are already running Hal9k_’s rooted software update.

Building the Module

Finding the Parts

Finding Suitable Kernel Source

Since we’re trying to build a binary module for an already compiled kernel, we need to identify a very close copy of kernel source code to work with.  To my knowledge, the exact kernel source used on the Ouku has not been released.  Looking through Freescale’s website, I found a link to Linux kernel source for the SABRE tablet platform that seemed to meet the bill. The SABRE for automotive appeared to be an earlier version.

You need to sign up for a free account with Freescale, and accept their terms and conditions to obtain the download.

Finding Suitable Cross-Compiler

I originally tried compiling with the arm-linux-androideabi-4.4.3 that ships with android-ndk-r8e.  Unfortunately, the resulting modules had compatibility problems.  The solution was to use arm-linux-androideabi-4.4.0 that ships with android-ndk-r5b which can be found at

Obtaining the Kernel Configuration

The kernel provides a copy of its own configuration in the /proc/config.gz file.  Copy this file from the unit so we can use it to configure the kernel source.

Preparing to Compile

Untar the cross-compiler

$ tar jxvf android-ndk-r5b-linux-x86.tar.bz2

Setup cross-compiler environment variables

$ export ARCH=arm
$ export SUBARCH=arm
$ export CROSS_COMPILE="/path/to/android-ndk-r5b/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin/arm-eabi-"

Untar the source

$ tar zxvf L2.6.35_11.05.01_ER_source_bundle.tar.gz
$ tar zxvf L2.6.35_11.05.01_ER_source.tar.gz
$ cd L2.6.35_11.05.01_ER_source/pkgs
$ tar jxvf linux-
$ tar jxvf linux-

Apply provided patches

$ mv patches linux-
$ cd linux-
$ ./patches/

Configure the kernel

$ mkdir build
$ gunzip -c /path/to/config.gz > build/.config
$ make silentoldconfig prepare headers_install scripts O=build KERNELRELEASE=""

Extracting Module Symbols

Even with using this “close enough” kernel and the actual configuration from the running kernel, the module symbols used will not be identical.  We need these symbols to compile our module with for it to load successfully.

Obtain the Kernel Image

We have the uImage file from Hal9k_’s software update, so we’ll use that.  It is contained in a U-Boot image, so we need to strip the header off of it.  We’ll also want mkimage, a utility for making U-Boot images (on Fedora, this is available from the uboot-tools package).

$ mkimage -l uImage
Image Name:   Linux-
Created:      Mon Dec 10 02:34:26 2012
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    2547996 Bytes = 2488.28 kB = 2.43 MB
Load Address: 70008000
Entry Point:  70008000

$ dd if=uImage of=kernel.img bs=1 skip=64 count=70008000

Find the kernel base address

From a shell on the car radio, shortly after boot, capture the output of dmesg and look for the “.init” line. I copied it to my desktop first. The first hex address listed is the base address. In our case, it’s 0xc0008000.

$ grep \.init dmesg.txt
free_area_init_node: node 0, pgdat c04f94b4, node_mem_map c0599000
Kernel command line: console=null init=/init androidboot.console=null video=mxcdi0fb:RGB24,SEIKO-WVGA ldb=off di0_primary pmem=32M,64M fbmem=5M gpu_memory=64M calibration
.init : 0xc0008000 - 0xc0037000 ( 188 kB)

Grab glandium’s extract-symvers script

$ wget

Extract the symbols

$ python -B 0xc0008000 kernel.img > Module.symvers

Compile the Module

Copy the module symbols into kernel build

$ cp /path/to/Module.symvers build/

Create a workspace elsewhere for the cp210x module

$ mkdir cp210x

Copy the cp210x source from the kernel source to your workspace

$ cd /path/to/L2.6.35_11.05.01_ER_source/pkgs/linux-
$ cp cp210x.c /path/to/cp210x

Create a Makefile

$ cd /path/to/cp210x
$ echo "obj-m = cp210x.o"> Makefile

Compile the module

$ cd /path/to/L2.6.35_11.05.01_ER_source/pkgs/linux-
$ make M=/path/to/cp210x O=build modules KERNELRELEASE=""

Testing the module

On the radio, try to install the module to make sure it loads.

# insmod cp210x.ko
# dmesg
<6>USB Serial support registered for cp210x
<6>cp210x 2-1.1:1.0: cp210x converter detected
<6>usb 2-1.1: reset full speed USB device using fsl-ehci and address 3
<6>usb 2-1.1: cp210x converter now attached to ttyUSB0
<6>usbcore: registered new interface driver cp210x
<6>cp210x: v0.09:Silicon Labs CP210x RS232 serial adaptor driver

Try using the serial port as well.

Installing the Module

While it’s great to have a working module, it quickly becomes tiresome to manually install it each time the radio boots.  To make it more permanent, we need to properly install it.

Install to the modules directory

# mount -o rw,remount /dev/block/mmcblk0p2 /system
# cp /path/to/cp210x.ko /system/lib/modules

We also need to edit the /init.rc file to cause the module to load on boot.  Unfortunately, the root file system on which it resides is the kernel’s initial ramdisk, not a file system that we can remount as writeable on the system.  Fortunately, we have this image as part of Hal9k_’s update.

Extract the initrd

Back to the desktop.

$ mkimage -l uramdisk.img
Image Name:   Android Root Filesystem
Created:      Sat Apr  6 08:49:03 2013
Image Type:   ARM Linux RAMDisk Image (gzip compressed)
Data Size:    183417 Bytes = 179.12 kB = 0.17 MB
Load Address: 70308000
Entry Point:  70308000

$ dd if=uramdisk.img of=ramdisk.img.gz bs=1 skip=64
$ gunzip ramdisk.img.gz
$ mkdir ramdisk; cd ramdisk
$ cpio -iv < ../ramdisk.img

Edit init.rc

Edit the extracted init.rc in your favorite text editor, and add the line for our new module, directly below the line for pl2303:

insmod /system/lib/modules/cp210x.ko

Rebuild the initrd

$ find . | cpio --create --format='newc' > ../newramdisk.img
$ cd .. ; gzip newramdisk.img
$ mkimage -A arm -O linux -T ramdisk -C gzip -a 70308000 -e 70308000 -n Linux -d newramdisk.img.gz new-uramdisk.img
Image Name:   Linux
Created:      Mon May  6 22:17:47 2013
Image Type:   ARM Linux RAMDisk Image (gzip compressed)
Data Size:    183159 Bytes = 178.87 kB = 0.17 MB
Load Address: 70308000
Entry Point:  70308000

Install the new initrd

Copy new-uramdisk.img to the root directory of your external microSD card on the radio.  Rename the file to uramdisk.img.  Reboot the radio, holding the volume knob and menu buttons down during the boot.  You should see an indication that the update was successful, and the radio will reboot.  The cp210x module should now be loaded on boot!

That wasn’t such a chore, was it?

Comments Off on cp210x on TH8581GA :, , , , , , more...

May 2022


Content Copyright © 2004 - 2019 Brady Alleman. All Rights Reserved.

As an Amazon Associate I earn from qualifying purchases.