Friday, October 27, 2017

Build OpenCV for Android with LLVM C++ Runtime

According to the Android NDK C++ Library Support, LLVM's libc++ will be the only STL:
LLVM's libc++ is the C++ standard library that has been used by the Android OS since Lollipop, and in the future will be the only STL available in the NDK.Until NDK r16, the NDK's libc++ is only of beta quality. Beginning with NDK r16, libc++ will be the preferred STL. A future NDK release will remove the other options.
If you are working with libraries linked with gnustl, you may have big problems.
In this post, I introduce how I compile the OpenCV for Android with LLVM libc++ runtime.

Install the cmake and cmake-gui

1. Dont install by sudo apt-get install (or update) cmake. Depends on the different Ubuntu version, you may not get the latest cmake installed.
2. Uninstall the existing cmake: sudo apt-get purge cmake
3. Download pre-compiled cmake package: Latest Release (3.9.4)
4. Install the cmake (cmake-gui is also included)

Download the OpenCV source

OpenCV is available from github.
git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git (Optional)

Cmake configuration

1. Start cmake-gui
2. Click the "Browse Source" button and give the OpenCV source folder
3. Click the "Browse Build" button and give the build folder (e.g. create a folder: opencv_android_build)
4. Click "Configure" button, select "Specify toolchain file for cross-compiling", in the next prompt window, make sure to select the "android.toolchain.cmake" under HOME_NDK/build/cmake/. Make sure not to use the file under opencv folder!!!
5. Click "Add Entry" button, add ANDROID_PLATFORM as String with value android-21
6. Click "Add Entry" button, add ANDROID_STL as String with value c++_static
7. Change the existing item CMAKE_BUILD_TYPE to Release
8. Change the existing item CMAKE_CXX_STANDARD_LIBRARIES to libc++_static.a from  libgnustl_static.a (under HOME_NDK/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/)
9. Click "Configure" button to configure again
10. Click "Generate" button to generate configuration
11. Go to the build folder (e.g. opencv_android_build), run make -j to make the targets
12. Run make install, the final files will be found under install folder.

Good luck!

Monday, November 30, 2015

Android smart phone with longer battery life (2)

This time, let's start from the healthd battery health monitor service start entrance. It is the healthd.cpp file from https://github.com/android/platform_system_core/blob/master/healthd/healthd.cpp, here is the code snippets of main(...):
int main(int argc, char **argv) {
    int ch;
    int ret;

    klog_set_level(KLOG_LEVEL);  // logging into kernel
    healthd_mode_ops = &android_ops;  // setup the callback

    if (!strcmp(basename(argv[0]), "charger")) {
        healthd_mode_ops = &charger_ops;   // setup the charger only callback
    } else {
        while ((ch = getopt(argc, argv, "cr")) != -1) {
            switch (ch) {
            case 'c':
                healthd_mode_ops = &charger_ops;
                break;
            case 'r':
                healthd_mode_ops = &recovery_ops; // setup recovery mode callback
The global variable healthd_mode_ops is an instance of struct healthd_mode_ops. It is to register the callbacks of battery monitor initialization and operations of update. The service has three different callbacks for normal bootup, recovery mode, and charger only mode respectively.
struct healthd_mode_ops {
    void (*init)(struct healthd_config *config);
    int (*preparetowait)(void);
    void (*heartbeat)(void);
    void (*battery_update)(struct android::BatteryProperties *props);
};
Here is the normal mode callbacks:
static struct healthd_mode_ops android_ops = {
    .init = healthd_mode_android_init,
    .preparetowait = healthd_mode_android_preparetowait,
    .heartbeat = healthd_mode_nop_heartbeat,
    .battery_update = healthd_mode_android_battery_update,
};
The callback functions are implemented in file: https://github.com/android/platform_system_core/blob/2655256570b7c1c5af6d886735835eecb99f45f2/healthd/healthd_mode_android.cpp. We will re-visit the file in details a little later.
After the callback installation, healthd_init() and an endless loop healthd_mainloop() is followed.
    ret = healthd_init();
    if (ret) {
        KLOG_ERROR("Initialization failed, exiting\n");
        exit(2);
    }

    healthd_mainloop();
And here is the healthd_init(), which finishes the following:
  • create an epoll instance, it is a very scalable I/O event notification mechanism which is in here to monitor the kernel uevent updates, binder object, wakeup alarm timer etc.
  • call the registered init callback of healthd_mode_ops. We will re-visit later.
  • healthd_board_init(...), which actually does nothing here.
  • setup a wakeup alarm timer, add the timer file descriptor to be monitored by the epoll object. By default the fast timer internal is set.
  • setup a uevent, and add the uevent file descriptor to be monitored by the epoll object. This is here to get the battery subsystem updates from kernel.
  • create the BatteryMonitor object, and get BatteryMonitor initialized. The BatteryMonitor initialization has been visited in part I.
static int healthd_init() {
    epollfd = epoll_create(MAX_EPOLL_EVENTS);
    if (epollfd == -1) {
        KLOG_ERROR(LOG_TAG,
                   "epoll_create failed; errno=%d\n",
                   errno);
        return -1;
    }

    healthd_mode_ops->init(&healthd_config);
    healthd_board_init(&healthd_config);
    wakealarm_init();
    uevent_init();
    gBatteryMonitor = new BatteryMonitor();
    gBatteryMonitor->init(&healthd_config);
Then it is an endless loop healthd_mainloop(). That is how the battery health state is get monitored continuously and endlessly. It waits on the epoll object, once any event happens the event callback will be called, which could be one or several of the registered events.
static void healthd_mainloop(void) {
    while (1) {
        struct epoll_event events[eventct];
        int nevents;
        int timeout = awake_poll_interval;
        int mode_timeout;

        mode_timeout = healthd_mode_ops->preparetowait();
        if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout))
            timeout = mode_timeout;
        nevents = epoll_wait(epollfd, events, eventct, timeout);

        if (nevents == -1) {
            if (errno == EINTR)
                continue;
            KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");
            break;
        }

        for (int n = 0; n < nevents; ++n) {
            if (events[n].data.ptr)
                (*(void (*)(int))events[n].data.ptr)(events[n].events);
        }

        if (!nevents)
            periodic_chores();

        healthd_mode_ops->heartbeat();
    }

More details about callbacks of healthd_mode_android.cpp

Let's look into more details about the callbacks of file: https://github.com/android/platform_system_core/blob/2655256570b7c1c5af6d886735835eecb99f45f2/healthd/healthd_mode_android.cpp.
void healthd_mode_android_init(struct healthd_config* /*config*/) is the initialize function, it creates a binder object, add the binder object into the epoll polling list and install the callback for the operation when the binder object is polled by the epoll.
void healthd_mode_android_init(struct healthd_config* /*config*/) {
    ProcessState::self()->setThreadPoolMaxThreadCount(0);
    IPCThreadState::self()->disableBackgroundScheduling(true);
    IPCThreadState::self()->setupPolling(&gBinderFd);

    if (gBinderFd >= 0) {
        if (healthd_register_event(gBinderFd, binder_event))
            KLOG_ERROR(LOG_TAG,
                       "Register for binder events failed\n");
    }
The installed epoll event callback for the binder is to process the binder commands:
static void binder_event(uint32_t /*epevents*/) {
    IPCThreadState::self()->handlePolledCommands();
}
Finally the initialize register self as a service called "batteryproperties" to the android service manager. The android Java space can listen to the service to get the battery health state updates. Use the command: service list, you shall see the service "batteryproperties" listed.
    gBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();
    gBatteryPropertiesRegistrar->publish();
}
void healthd_mode_android_battery_update(...) is the update callback. It is to notify all the registered service clients when the battery health state gets updated. It is the service listener's implementation of how to handle the battery state updates.
void healthd_mode_android_battery_update(
    struct android::BatteryProperties *props) {
    if (gBatteryPropertiesRegistrar != NULL)
        gBatteryPropertiesRegistrar->notifyListeners(*props);

    return;
}

Callbacks of other two epoll objects

The uevent callback receives the kernel uevent updates, then parse the power_supply events, and reads the sysfs power_supply updates.
static void uevent_event(uint32_t /*epevents*/) {
    char msg[UEVENT_MSG_LEN+2];
    char *cp;
    int n;

    n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
    if (n <= 0)
        return;
    if (n >= UEVENT_MSG_LEN)   /* overflow -- discard */
        return;

    msg[n] = '\0';
    msg[n+1] = '\0';
    cp = msg;

    while (*cp) {
        if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) { // power_supply only
            healthd_battery_update(); // reads the power_supply sysfs into memory
            break;
        }

        /* advance to after the next \0 */
        while (*cp++)
            ;
    }
}
The wakeup timer object setup the timer to wakeup from kernel sleep and gets the power_supply updates.
static void wakealarm_event(uint32_t /*epevents*/) {
    ... ...
    periodic_chores();
}

static void periodic_chores() {
    healthd_battery_update(); // reads the power_supply sysfs into memory
}
Will illustrate how to get the battery state updates from Java with an sample app in the next article.

Android smart phone with longer battery life

Smart phones have been developed a lot with more cpu cores, more computation capabilities, with larger and brighter screens, with higher resolution cameras and etc. But battery is one of the areas have no breakthrough. Talking to the battery life, because of the faster cpu/gpu, bigger screen, it even gets worse. Do you still remember the last time you got so mad to find a power supply outlet?
Smart phones use Li-ion batteries. Before Li-ion batteries improve the capacity with the technology breakthrough, how to save the battery life becomes very important as we dont have too much to waste. To save the battery life keeping closely monitoring the battery life is the first step.
Start from Android KK (Kitkat) Android adds the system/core/healthd, which is built into part of Android system image as /sbin/healthd, to monitor the battery state. In this article let's take a close look into healthd to understand how can we monitor the battery state.

What does healthd monitor and tell?

First let's take a look at the healthd logs:
<14>[21867.192464] healthd: battery l=78 v=4024 t=18.8 h=2 st=4 c=-239 chg=a
<14>[21867.421852] healthd: battery l=78 v=4067 t=18.8 h=2 st=2 c=5 chg=a
<14>[21867.448320] healthd: battery l=78 v=4067 t=18.8 h=2 st=2 c=5 chg=a
The healthd monitors the battery state of charge and reports 7 outputs. They are battery level (l=78), voltage (v=4024), battery temperature (t=18.8), health state (h=2), battery status (st=4), charging/discharging current (c=-239), and charging status/charger type (chg=a).

  • Battery level: values in 0 ~ 100, means no battery to full battery.
  • Battery voltage: voltage in mV, lower battery level, less voltage.
  • Battery temperature: temperature in Celsius (°C).
  • Health state: values in 1 ~ 7. It is a enumeration with following health state:
    • 1 -> Unknown
    • 2 -> Good
    • 3 -> Overheat
    • 4 -> Dead
    • 5 -> Over voltage
    • 6 -> Unspecified failure
    • 7 -> Cold
  • Battery status: values in 1 ~ 5. It is a enumeration with following battery status:
    • 1 -> Unknown
    • 2 -> Charging
    • 3 -> Discharging
    • 4 -> Not charging
    • 5 -> Full
  • Charging/discharging current: positive value means discharging current in mV, negative value means charging current in mV.
  • Charging status: empty if not on charging. a/u/w otherwise:
    • a: charger AC online
    • u: charger USB online
    • w: charger wireless online

How does healthd read the battery health data?

The battery driver exports the virtual sysfs under /sys/class/power_supply for upper layer to get the battery health data. Let's review the code https://github.com/android/platform_system_core/blob/master/healthd/BatteryMonitor.cpp to understand how healthd gets the battery health data.

BatteryMonitor::init(...) function: open /sys/class/power_supply directory, read and traverse
void BatteryMonitor::init(struct healthd_config *hc) {
    String8 path;
    char pval[PROPERTY_VALUE_MAX];

    mHealthdConfig = hc;
    DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH); /* open folder /sys/class/power_supply */
    if (dir == NULL) {
        KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
    } else {
        struct dirent* entry;

        while ((entry = readdir(dir))) { /* loop and read files in /sys/class/power_supply */
In sysfs folder /sys/class/power_supply, there is a list of power_supply supported by the given smart phone. In each power_supply folder, there are some attributes. One of the attributes every power_supply shall have is the type. Following code snippets check the type of each power_supply to determine the next things to check:
394            // Look for "type" file in each subdirectory
395            path.clear();
396            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
397            switch(readPowerSupplyType(path)) {
398            case ANDROID_POWER_SUPPLY_TYPE_AC:
399            case ANDROID_POWER_SUPPLY_TYPE_USB:
400            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
... ...
407            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
... ...
506            case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
... ...
If power_supply type is other than Battery or Unknown, then power_supply type should be one of the following:
  • ANDROID_POWER_SUPPLY_TYPE_AC
  • ANDROID_POWER_SUPPLY_TYPE_USB
  • ANDROID_POWER_SUPPLY_TYPE_WIRELESS
and /sys/class/power_supply/%power_supply_type%/online will be further checked to see if such power_supply is plugged to charge the given smart phone.
401                path.clear();
402                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
403                if (access(path.string(), R_OK) == 0)
404                    mChargerNames.add(String8(name));
405                break;
... ...
215    for (i = 0; i < mChargerNames.size(); i++) {
216        String8 path;
217        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
218                          mChargerNames[i].string());
219
220        if (readFromFile(path, buf, SIZE) > 0) { /* online */
221            if (buf[0] != '0') {
222                path.clear();
223                path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
224                                  mChargerNames[i].string());
225                switch(readPowerSupplyType(path)) {
226                case ANDROID_POWER_SUPPLY_TYPE_AC:
227                    props.chargerAcOnline = true;
228                    break;
229                case ANDROID_POWER_SUPPLY_TYPE_USB:
230                    props.chargerUsbOnline = true;
231                    break;
232                case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
233                    props.chargerWirelessOnline = true;
234                    break;
235                default:
236                    KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
237                                 mChargerNames[i].string());
238                }
239            }
240        }
241    }
If power_supply is Battery, it checks more attributes under sysfs folder /sys/class/power_supply/battery, such as status, health, present, capacity, voltage_now/batt_vol, current_now, current_avg, charge_counter, temp/batt_temp, technology.
Read battery level in percentages and battery voltage in mV:
191    props.batteryLevel = mBatteryFixedCapacity ?
192        mBatteryFixedCapacity :
193        getIntField(mHealthdConfig->batteryCapacityPath);
194    props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
Read battery temperature in Celsius (°C):
196    props.batteryTemperature = mBatteryFixedTemperature ?
197        mBatteryFixedTemperature :
198        getIntField(mHealthdConfig->batteryTemperaturePath);
Read battery status:
204    if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)
205        props.batteryStatus = getBatteryStatus(buf);
57int BatteryMonitor::getBatteryStatus(const char* status) {
58    int ret;
59    struct sysfsStringEnumMap batteryStatusMap[] = {
60        { "Unknown", BATTERY_STATUS_UNKNOWN },
61        { "Charging", BATTERY_STATUS_CHARGING },
62        { "Discharging", BATTERY_STATUS_DISCHARGING },
63        { "Not charging", BATTERY_STATUS_NOT_CHARGING },
64        { "Full", BATTERY_STATUS_FULL },
65        { NULL, 0 },
66    };
67
68    ret = mapSysfsString(status, batteryStatusMap);
Read battery health state:
207    if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)
208        props.batteryHealth = getBatteryHealth(buf);
77int BatteryMonitor::getBatteryHealth(const char* status) {
78    int ret;
79    struct sysfsStringEnumMap batteryHealthMap[] = {
80        { "Unknown", BATTERY_HEALTH_UNKNOWN },
81        { "Good", BATTERY_HEALTH_GOOD },
82        { "Overheat", BATTERY_HEALTH_OVERHEAT },
83        { "Dead", BATTERY_HEALTH_DEAD },
84        { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE },
85        { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE },
86        { "Cold", BATTERY_HEALTH_COLD },
87        { NULL, 0 },
88    };
89
90    ret = mapSysfsString(status, batteryHealthMap);
After BatteryMonitor.cpp traverse the sysfs folder /sys/class/power_supply and update the attributes, the following code snippets is to notify the applications who concern the battery health state.
275    healthd_mode_ops->battery_update(&props);
It is a callback function registered at the beginning of the health monitoring service. Have to cut here. Will continue with a new article.

Wednesday, March 28, 2012

memory leak tracking on android, cont

You have Android version >= 2.2.
Make sure you have libc_malloc_debug_leak.so:
  • > adb shell ls /system/lib/libc_malloc_debug_leak.so
Enable the memory leak check:
  • > adb shell setprop libc.debug.malloc 1
Restart the Android framework, make sure the memory leak check is functional:
  • > adb shell stop
  • > adb shell start
  • > adb logcat -b main -v threadtime (you see this line in the printed log: 03-29 03:10:52.942 4200 4200 I libc : /system/bin/logcat using MALLOC_DEBUG = 1 (leak checker))
In your DDMS configuration file (e.g. ~/.android/ddms.cfg on Linux), add "native=true". This enables the Native Heap tab. Now you can use the "Native Heap" tab features to grab snapshots of the heap memory usage. Group by library to view the memory usage in libraries. Show new allocations comparing to the previous snapshot to monitor the memory allocation increments. If you are using the images built by your own, fill the "Symbol Search Path" to get more details information.

More options:
  • > adb shell setprop libc.debug.malloc 5
# For filling allocated /freed memory with patterns defined by CHK_SENTINEL_VALUE, and CHK_FILL_FREE macros.
  • > adb shell setprop libc.debug.malloc 10
# For adding pre-, and post- allocation stubs in order to detect buffer overruns.

Monday, September 26, 2011

Android sh script, why failed with [ not found

A simple sh script, but run failure with error: [ not found.
#!/system/bin/sh
if [ $? eq 0 ]; then
    echo "Command run successful"
fi
The same script can run well on Linux.
I dont know why, but I finally got a solution.
Upload a busybox, change it to executable permissions, create a soft link "[" to busybox. Like the following:
-rwxr-xr-x 500      500       1877260 2011-09-22 02:42 busybox
lrwxrwxrwx root     root              2011-09-26 08:15 [ -> /sbin/busybox
Run the sh script again, which shall give no error any more.
Finally, make sure the searching path $PATH can find command "busybox", and "[".

Thursday, July 14, 2011

Disable Linux kernel version magic check

Linux kernel will refuse to load kernel module if the version magic is not match. It can be easily disabled for some ease.
Find linux kernel kernel/module.c, find "check_modinfo" function, comment out "return -ENOEXEC;" for same_magic(...) check function.

How to get a console with root if Motorola XOOM is working as USB Host and connected with USB devices

If Motorola XOOM is connected with USB devices and working as USB Host mode, you will not be able to have adb shell work on PC. The only USB connection is used for other purpose. Here is a tip to have a console with root even the USB connection is used for USB device.
  • Motorola XOOM is rooted
  • Push a busybox to Motorola XOOM, make it executable
  • Connect Motorola XOOM with PC, in a PC cmd window, adb shell to the device, the shell must be a root shell.
  • Start telnetd: busybox telnetd -l /system/bin/sh
  • Download a telnet APP for Motorola XOOM, e.g. BlowTorch. Launch telnet client (BlowTorch), telnet to device, a root console is served.