Tuesday, September 9, 2014

Corner cases of Ubuntu 14.04 on Lenovo ThinkPad x201

I've been using Ubuntu 14.04 for a couple months now.


1. CPU got stucked on 1.2GhZ
Recently I installed a handy utility called indicator-cpufreq, which gives a system status bar icon indicating the currently used CPU governor and the current cpu frequency.  I noticed that my CPU always got stucked on 1.2Ghz, no matter what I did. I have tried modifying it manually by echo-ing the sysfs node and using cpufreq-utils, without much luck. I then came across this page:

http://askubuntu.com/questions/340626/permanently-change-maximum-cpu-frequency
This page explains that there is a CPU bios_limit that if set wrongly, may prevent the CPU from going above the frequency threshold that's set there.

cat /sys/devices/system/cpu/cpu0/cpufreq/bios_limit

Turned out it really was the culprit!! For some weird reason it got set to 1.2GHZ!!

This is how you worked around it:

echo 1 > /sys/module/processor/parameters/ignore_ppc

To make workaround permanent, we can edit the kernel command line argument, just like what's explained on the same page:

Modify /etc/default/grub to be like this:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash processor.ignore_ppc=1"

Everything works like a charm afterwards!

I then installed cpufreqd, which is a daemon to customize CPU frequency based on the laptop's realtime battery status (e.g. power level, plug/unplugged, etc). Now my docked x201 is running buttery smooth at 2.67 GHZ :)

I want to check out how long will it take to build AOSP on this laptop now :)

2. Intermittent shutdown due to overheating
Another problem I was facing is that after a couple hours of running docked, my laptop would shut itself off! When this happened, I undocked my laptop and noticed that it's abnormally hot!
I then realized that x201's airflow is located on its bottom, which got blocked by the dock. (sigh.. guess the dock isn't poorly designed.... :( )

Don't fret out though! There's solution!
I found this handy tool to control the fan speed of the laptop's.

http://www.thinkwiki.org/wiki/How_to_control_fan_speed

Basically, x201's fan can be controlled by this node:
/proc/acpi/ibm/fan
There are several levels that can be set, which corresponds to the RPM of the fan.

With this in mind, thinkfan can be used to automate the RPM of the fan depending on the reading of the thermal sensors. This page kindly describes how to set it up. (including how to run thinkfan as a daemon, custom setup for x201, etc)

http://staff.science.uva.nl/~kholshei/thinkfan_guide/

Edit (10/06/2015):
The following steps are how I did it:
1. sudo apt-get install thinkfan
2. sudo echo "options thinkpad_acpi fan_control=1" > /etc/modprobe.d/thinkpad_acpi.conf
3. sudo vim /etc/default/thinkfan, change it to be the following (this is to load thinkfan on boot):
START=yes
4. sudo vim /etc/thinkfan.conf, change it to be the following (this is fan vs. sensor-reading):

# The way the config works is that it picks the highest value among all sysfs nodessensor /sys/devices/virtual/hwmon/hwmon0/temp1_input
sensor /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp4_input
sensor /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp2_input
#sensor /proc/acpi/ibm/thermal

(0, 0, 47)
(1, 46, 50)
(2, 49, 53)
(3, 52, 56)
(4, 55, 59)
(5, 58, 62)
(6, 61, 65)
(7, 64, 75)
#127 is for disengaged
(127, 74, 32767)

And for debugging:
1. To see how a new config file works:
sudo thinkfan -n
2. To check current temperature:
cat /sys/devices/virtual/hwmon/hwmon0/temp1_input && cat /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp4_input && cat /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp2_input
'or'
cat /proc/acpi/ibm/thermal (in ubuntu 14.04, only shows one temperature)
3. To check fan level:
cat /proc/acpi/ibm/fan
(level shouldn't be 'auto' if thinkfan is really running)
4. ps aux | grep thinkfan <- you should see the process running


Wednesday, January 29, 2014

Android Binder, AIDL, Service, and API

Android Binder is an IPC mechanism used in Android. Binder can be accessed through the native code (C++) and also through Java code.

Here are some places where Binder are used:
1. When you use system service through mContext.getSystemService(...)
2. When you start another application through Intent.
3. When you're implementing a public service that uses AIDL file (this is pretty obvious)
4. When you're implementing interacting through different services using Messenger class

To me, what's the most interesting is that Android abstracts it so well such that I didn't realize I've been doing IPC calls so many times! In fact, I began my first Android programming without having any idea what an IPC was.

For the work I've been doing, I need to implement a piece of code that talks to the driver layer. Since I don't want to re-write the tedious JNI code multiple times (in case of it's needed somewhere else), I decided to create a public Service using AIDL convention. This service is the one that interacts with the native layer, and will then be exposed as an API in the SDK.
After that, it will essentially be wrapped one more time, such that user wouldn't have to actually interact with the service directly. Sounds like I'm over-complicating it, huh? Not really.. This is exactly how InputManager is working under the hood. When you do  mContext.getSystemService(INPUT_MANAGER), under the hood, InputManager class is interacting with InputManagerService. On the whole system, there's only a single instance of InputManagerService. This service is interacting with some native piece of codes that are tightly coupled to a lower layer. This way, as an application developer, we can all simply use the handy interface exposed through InputManager :)