Monthly Archives: June 2013

Top command on Android

What is top command?

The “top” command from Linux is a very handy tool for getting various info for running processes and available system resources. It gives you process name (Name), priority (PR), State (S), Process ID (PID), Percentage of CPU (CPU%) that this process uses, number of threads in the process (#THR), User ID (UID), Policy (PCY) , VSS and RSS memory.

Usage

Usage: top [ -m max_procs ] [ -n iterations ] [ -d delay ] [ -s sort_column ] [ -t ] [ -h ]
    -m num  Maximum number of processes to display.
    -n num  Updates to show before exiting.
    -d num  Seconds to wait between updates.
    -s col  Column to sort by (cpu,vss,rss,thr).
    -t      Show threads instead of processes.
    -h      Display this help screen.

 

How does it do it?

as in ordinary linux os.

  • general info: /proc/stat
  • process stats (state, utime, stime, vss, rss, priority): /proc/{process}/stat
  • process name:  /proc/{process}/cmdline
  • process uid & gid: /proc/{process}/status
  • process thread info: /proc/{process}/task/{thread}/…

Source code:

https://github.com/android/platform_system_core/blob/master/toolbox/top.c 

get listeners in c#

Here it is an example how to get listeners in c#:

Data d = new Data();
d.OnSave += delegate { Console.WriteLine("onSave event"); };
var handler = typeof(Data).GetField("OnSave", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(d) as Delegate;
var subscribers = handler.GetInvocationList();
if (subscribers.Count() == 0)
{
//no listeners added
}
else
{
//invoke them
foreach (var s in subscribers)
{
s.DynamicInvoke(null, null);
}
}

 

app_process command in Android

What is this app_process

Although not that popular “app_process” command is used heavily in Android, for example the well know “am” script is using it. Everybody knows how to start an application from adb shell:

am start -n yourpackagename/.activityname

However “am” is just a shell script and what stays in the base of the am script is our app_process binary:

root@android:/ # cat /system/bin/am
cat /system/bin/am
# Script to start "am" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/am.jar
exec app_process $base/bin com.android.commands.am.Am "$@"

root@android:/ #

So app_process is the binary used to start java code. All the apps, instrumentations or installations are tarted using this.

Usage … NOT:

Lets see the official usage output:

root@android:/ # app_process
Usage: app_process [java-options] cmd-dir start-class-name [options]

Not quite complete as usual :)

Usage (full):

app_process [vm-options] cmd-dir [options] start-class-name [main-options]

Where:

  • vm-options – the VM options passed.
  • cmd-dir – the parent dir (/system/bin)
  • options – the arguments for this binary :

–zygote
–start-system-server
–application (api>=14)
–nice-name=nice_proc_name (api>=14)

  • start-class-name – the start-up class that contains main()  (com.android.commands.am.Am)
  • main-options – the arguments that are passed to the main() of the start-up class

Note for options:

  1. –start-system-server works only if –zygote
  2. if –zygote, start-class-name = com.android.internal.os.ZygoteInit
  3. and nice-name=zygote
  4. cmd-dir for api>=14 can be after options but always before start-class-name

Source code:

api < 14 : https://android.googlesource.com/platform/frameworks/base/+/54b6cfa9a9e5b861a9930af873580d6dc20f773c/cmds/app_process/app_main.cpp

api >= 14 : https://android.googlesource.com/platform/frameworks/base/+/ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3/cmds/app_process/app_main.cpp

 

android sdk and jdk 1.7

Q: Can you use jdk 1.7 with android SDK?

Yes, you can use Java 1.7 for the android development. The only problem is that default algorithm for jarsigner is changed so you need to:

ant(add): "-verbose -digestalg SHA1 -sigalg MD5withRSA"

maven(in configuration):

<arguments> <argument>-sigalg</argument><argument>MD5withRSA</argument> <argument>-digestalg</argument><argument>SHA1</argument> </arguments>

java byte array related snippets

byte[] int2toByteArray(int value) {
     return  ByteBuffer.allocate(4).putInt(value).array();
}

byte[] int2toByteArray_(int value) {
    return new byte[] {
        (byte) (value >> 24),
        (byte) (value >> 16),
        (byte) (value >> 8),
        (byte) value};
}

int byteArray2Int(byte[] bytes) {
     return ByteBuffer.wrap(bytes).getInt();
//you can use specify the expected byte order
//ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt();
}

int byteArray2Int_(byte[] bytes) {
     return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF)
}

Get launcher activity from installed apk

if you do know the package:

final PackageManager pm = getPackageManager();

        Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

        List appList = pm.queryIntentActivities(mainIntent, 0);
        Collections.sort(appList, new ResolveInfo.DisplayNameComparator(pm));

        for (ResolveInfo temp : appList) {

            Log.v("my logs", "package and activity name = "
                    + temp.activityInfo.packageName + "    "
                    + temp.activityInfo.name);

        }

if you know the package:

PackageManager pm = getPackageManager();
Intent intent=pm.getLaunchIntentForPackage(pacakgeName);
startActivity(intent);

return array from JNI to Java and back

From JNI to Java

more info on http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html#array_operations

JNIEXPORT jintArray JNICALL Java_ArrayTest_initIntArray(JNIEnv *env, jclass cls, int size)
{
 jintArray result;
 result = (*env)->NewIntArray(env, size);
 if (result == NULL) {
     return NULL; /* out of memory error thrown */
 }
 int i;
 // fill a temp structure to use to populate the java int array
 jint fill[256];
 for (i = 0; i < size; i++) {
     fill[i] = 0; // put whatever logic you want to populate the values here.
 }
 // move from the temp structure to the java structure
 (*env)->SetIntArrayRegion(env, result, 0, size, fill);
 return result;
}

 From Java to Jni

jmethodID myMethod = (*env)->GetMethodID(myClass, "myMethod", "()[I");
jintArray retval = (jintArray) (*env)->CallObjectMethod(myObject, myMethod);

 

Screenshot/capture on Android

This article is for everybody – form end users or bloggers that want to share their screen to software engineers that want to build a custom android build.

There are many ways one can get a screenshot or screen capture stream. I will start from the most easy ones going deeper in the Android code.

Easy

      • Manufacturer Shortcuts

Sometimes and especially since Android 4.0 manufacturers build their own shortcuts to easily take a screenshot. For example the key combination for many Samsung devices is [Home]+[Power], for Nexus S it is [Back]+[Power]. Try google for you specific device.

      • Device/Android version Specific Apps

There are many apps on the market but most requires root access simply because they read framebuffer directly or use some system library. However there some that does not require root, but they might depend on the device or the Android version. Some just does not all the features for non rooted devices.

Medium

  • Root Access Apps

There are plenty of apps that do that having that you have already rooted your device. Personally I do not recommend rooting your device.

  • Client-Server Apps

These are apps that you install on the PC(client) and optionally on the device(server), such as AShot . The “client” might also be accessible from a browser(AirDroid). The “server” might also require root access. There as option where there is no need of “server”, but in that case usb/adb connection with the device is needed. some may require Android SDK to be installed as well.

  • Android SDK and Eclipse ATD Gui

 

  • adb shell commands

To use this option you need the device to be accessible via adb.

 

  1. screencap
  2. screenshot
  3. /dev/graphics/fb0

Intermediate

  • adb server request

You can form a adb request “framebuffer:” and send it to adb client server socket (default port is 5037). In return you get RawImage. You cna also include ddmlib.jar and use
com.android.ddmlib.AdbHelper method: static RawImage getFrameBuffer(InetSocketAddress adbSockAddr, Device device) to get the same.

  • using open source

http://code.google.com/p/android-screenshot-library/

http://code.google.com/p/androidscreenshot/

  • DIY on the device

the difference is that screencap is using ScreenshotClient defined in SurfaceComposerClient.h. this means that whenever framebuffer is not used (GS4 & nexus devices android 4.0+), screenshot will give you empty data(black screen), while screencap will work fine.

  • read /dev/graphics/fb0

This is practically what screenshot/screencap* is doing. Note that what I said above for the framebuffer applies here also..

void const* mapbase = MAP_FAILED;
    ssize_t mapsize = -1;

    void const* base = 0;
    uint32_t w, h, f;
    size_t size = 0;

const char* fbpath = "/dev/graphics/fb0";
        int fb = open(fbpath, O_RDONLY);
        if (fb >= 0) {
            struct fb_var_screeninfo vinfo;
            if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) {
                uint32_t bytespp;
                if (vinfoToPixelFormat(vinfo, &bytespp, &f) == NO_ERROR) {
                    size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp;
                    w = vinfo.xres;
                    h = vinfo.yres;
                    size = w*h*bytespp;
                    mapsize = offset + size;
                    mapbase = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fb, 0);
                    if (mapbase != MAP_FAILED) {
                        base = (void const *)((char const *)mapbase + offset);
                    }
                }
            }
            close(fb);

 

  • in native code (lib/executable) include:

/system/lib/libsurfaceflinger_client.so or /system/lib/libgui.so for Android 4.0 and greater.

and use the screenshot client

 void const* base = 0;
    uint32_t w, h, f;
    size_t size = 0;

    ScreenshotClient screenshot;
    sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);
    if (display != NULL && screenshot.update(display) == NO_ERROR) {
        base = screenshot.getPixels();
        w = screenshot.getWidth();
        h = screenshot.getHeight();
        f = screenshot.getFormat();
        size = screenshot.getSize();
    }