db Documentation

What is “db” ?

简单来说,用此工具集成vim+cscope+ctags,可以把vim作为一个IDE来用,特别是你只有console的时候。用cscope来看20G的Android源代码毫无压力。
db is a wrapper tool to manage cscope and ctags projects.
You will love ctags+cscope+vim with this tool.

Installation

0. Requirements

Installing “db” tool is easy. However, you do need a couple of other things installed first.

  • ctags
  • cscope
  • git
  • gradle

1. fetch code

git clone https://github.com/cfig/utils

2. make and install

$ cd db_tool
$ gradle install

3. let vim load cscope/ctags database automatically

modify .vimrc as follows:

"taglist
if $SELECT_PROJECT_DB != ""
    if filereadable(expand("~/.proj_db/$SELECT_PROJECT_DB/tags"))
        set tags=~/.proj_db/$SELECT_PROJECT_DB/tags;
    endif
    if filereadable(expand("$HOME/.proj_db/$SELECT_PROJECT_DB/cscope.out"))
        " for M$ compatible
        cd $HOME
        cs add .proj_db/$SELECT_PROJECT_DB/cscope.out
        cd -
    endif
else
    set tags=tags; " the ';' is a must!
endif

Getting started

1. create project

$ db init my_project my_project2

This will create empty projects with name “my_project” and “my_project2” in ~/.proj_db/

2. check all projects you just created.

yu@mint ~ $ db list
1 - my_project
2 - my_project2
yu@mint ~ $ 

3. choose a project as “current” active project

$ dbc 1

4. add directories into current project

$ cd <your_source_directory>
$ db +

repeat these steps, until you add them all. You can check which directories are added into current project by “db show”.

5. generate cscope/ctags

$ db make

This may take some time if your project is huge. It takes up to 40 min for my whole Android source tree.

6. once the index is ready, you can open vim, and search anything you wanted.

Don’t know how to search with cscope ?
Check this http://cscope.sourceforge.net/cscope_vim_tutorial.html

Android Testing - Instrumentated Unit Tests

这里讲的Android Testing主要针android packages(application).

1. 测试框架

Testing Framework

1.1 TestCase:

跟其他流行的的Testing Framework一样,测试也分TestSuit,每个Suit有若干TestCase,每个TestCase有若干Method

1.2 TestRunner:

TestCase必须运行在某个testrunner之上。

Android支持多个TestRunner

  • InstrumentationTestRunner 继承自android.app.Instrumentation

    Instrumentation是基类.当instrumentation打开(AndroidManifest.xml有instrumentation条目)后, instrumentation会在app启动之前先实例化,然后可以检测app运行状态。
    比较土, 只支持Junit3,
    支持instrumentation方法(methods).
    Android instrumentation is a set of control methods or “hooks” in the Android system. These hooks control an Android component independently of its normal lifecycle.

  • AndroidJUnitRunner, 继承自android.app.Instrumentation
    支持Junit3, Junit4.

  • Espresso: 单个app的UI 测试

  • UI Automator: 跨app的UI测试
    其中后三个runner在Android SDK的”Android Testing Support Library”中,SDK Mgr中的名字为”Android Support Repository”.

2. 代码结构

  1. 标准方式(使用Intellij Idea / Android Studio)
    如果放到src/main/androidTest, 那么会生成2个apk,一个是<package_name>.apk, 一个是<package_name>.test.apk
    建一个AndroidTest任务,Idea会依次安装两个apk,然后执行test
  2. 直接暴力方式
    如果放到src/main/java, 就可以直接生成apk,直接安装后用am instrument执行;

3. 运行测试用例

3.1 command line运行测试用例

帮助文件for InstrumentationTestRunner and AndroidJUnitRunner

am instrument -w                                  <instrument_name>
am instrument -w -e <k>   <v>                     <instrument_name>
am instrument -w -e class org.cfig.TestSuit       <instrument_name>
am instrument -w -e class org.cfig.TestCase       <instrument_name>
am instrument -w -e class org.cfig.TestCase#test1 <instrument_name>

实例

查看安装好的instrementation:

# pm list instrumentation
instrumentation:com.android.cts.view/android.support.test.runner.AndroidJUnitRunner

可以执行

am instrument -w -e class android.view.animation.cts.AnimatorInflaterTest com.android.cts.view/android.support.test.runner.AndroidJUnitRunner

3.2 IDE运行测试用例(idea)

创建AndroidTest运行任务,可以指定package/class/method.

感谢

Max Walker 2009年写的傻瓜教程https://newcircle.com/s/post/1038/android_junit_test_example_tutorial

Android keys - release keys

Android default keys are located at build/target/product/security/, ROM providers must use OEM keys when building factory images for market products.
There are 5 paris of keys in all: (*.pk8 is private key, *.x509.pem is cert)

testkey (I call it dev key)
shared
platform
media
verity

1. How to specify OEM keys

config release key location in .mk, example:

PRODUCT_DEFAULT_DEV_CERTIFICATE := /home/xx/release_keys/releasekey
PRODUCT_OTA_PUBLIC_KEYS=/home/xx/release_keys/otakey.x509.pem

Then system will search for $(PRODUCT_DEFAULT_DEV_CERTIFICATE).pk8 and $(PRODUCT_DEFAULT_DEV_CERTIFICATE).x509.pem for release key.

$(PRODUCT_OTA_PUBLIC_KEYS) will generate target file META/otakeys.txt with content: “/home/xx/release_keys/otakey.x509.pem”

2. What are the keys used for

2.1 release key

If release key is not specified, it will default to build/target/product/security/testkey
This key will be used to:

- sign normal apk
- The cert will be save to /system/etc/security/otacerts.zip, which will be used to verify OTA pkg signature
- sign OTA pkg

2.2 shared/media/platform keys

These keys will be put into the same folder as PRODUCT_DEFAULT_DEV_CERTIFICATE
These keys will be used to:

- sign specific apk

For example:

LOCAL_CERTIFICATE := shared    eg.: Launcher, Dialer, etc.
LOCAL_CERTIFICATE := platform  eg.: Settings, Nfc, TelephonyProvider, CertInstaller, etc
LOCAL_CERTIFICATE := media     eg.: DownloadProvider,MediaProvider, Gallery etc.

2.3 verity key

In Android Lollipop, verity key is set to build/target/product/security/verity.{pk8,x509.pem} in build/target/product/verity.mk. OEM vendors need to define PRODUCT_VERITY_SIGNING_KEY by themselves.
verity key will be used to:

- sign boot.img, 
  the signature will be verified by bootloader.
  OEM vendors should build verity pub key inside bootloader, or put the pub key in some other secure storage.
- sign verity metadata in system.img,
  the signature will be verified by boot.img,
  boot.img has the pub key /verity_key in ramdisk.

3. Resign flow of Android

Build signing guide from google: https://source.android.com/devices/tech/ota/sign_builds.html

Typical re-signing flow: sign boot.img/system.img with verity_key, sign apks with specified keys, manually change META/otacerts.zip if needed.

./build/tools/releasetools/sign_target_files_apks \
    --replace_ota_keys \
    --default_key_mappings /home/xx/release_keys/  \
    --replace_verity_public_key=/home/xx/release_keys/verity_key \
    --replace_verity_private_key=/home/xx/release_keys/verity \
    orig.zip signed-target.zip

Typical OTA package generation: sign with new ota key

./build/tools/releasetools/ota_from_target_files \
    -k ~/release_keys/otakey \
    signed-target.zip \
    signed-ota_update.zip

‘ota_from_target_files’ needs some scripts in <android_src>/build and some host tools under <android_src>/out/host/linxu-x86, like “SignApk.jar”, “imgdiff” and needed shared libraries.

Health - Heart

摘自杭州马拉松官网 http://www.hzim.org/p/hzim/multimedia/articleview.jsf?article=6281411

据研究发现运动性猝死95%都是心源性猝死,发生的主要原因并不是累死的,基本都是死者的心脏原来就存有有病变,45岁以上的选手发生猝死的原因多数是由冠心病造成的,而常规的心电图检查时发现冠心病最简单的方法,45岁—25岁的人发生了运动性猝死多数是心脏结构发生了变化,心脏彩超是早期发现心脏结构变化和心脏功能下降最直接的手段,25岁以下年轻人发生运动性猝死的主要原因是猝死基因造成的,多数有猝死的家族史。

美国心脏协会AHA文献报道:意大利的威特地区通过,家族史、12导联心电图、心脏B超等3项简单的常规心脏检查对该地区的运动员进行普查,每半年一次,一直坚持了20年,最后统计分析该方法是该地区运动性猝死的发生率下降了89%,取得举世瞩目的成就,所以用:询问有无猝死家族史、12导联心电图、心脏彩超等三项临床手段是早期发现心脏是否存在病变基础,早期预防运动性猝死最有效的手段,而且目前心电图、心脏彩超各级医院都可以检查,如果平时单独去检查的话基本不用自费,项目属医保乙类项目。

心脏的结构的变化、心功能的下降往往都是动态的,有很多时候半年内各项指标就很快发生了变化,尤其是对于经常进行马拉松赛事的选手更是这样,所以对于心脏的检查、评估最好半年一次。

gradle - Android

1. 编译android library

apply plugin: 'com.android.library'
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
    }  

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }  
    }  

    lintOptions {
        abortOnError false
    }  
}

2. 编译android apk

apply plugin: 'android'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }  
        release {
            signingConfig signingConfigs.release
        }  
    }  

    lintOptions {
        abortOnError false
    }   

}

3. 配置apk的key

android {
  signingConfigs {
    release {
      storeFile file("/home/y/.android/platform.jks")
      storePassword "android"
      keyAlias "androiddebugkey"
      keyPassword "android"
    }
  }

  buildTypes {
    release {
      signingConfig signingConfigs.release
    }
  }
}

4. 配置instrumentation apk

4.1 gradle配置

repositories {
    mavenCentral()
    jcenter()
}
dependencies {
    //for pure testing apk
    compile 'com.android.support.test:runner:0.4'
    androidTestCompile 'com.android.support.test:runner:0.4'
    // Set this dependency to use JUnit 4 rules
    androidTestCompile 'com.android.support.test:rules:0.4'
    // Set this dependency to build and run Espresso tests
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    // Set this dependency to build and run UI Automator tests
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
}

4.2 AndroidManifest.xml配置

引入TestRunner

<application>
    <uses-library android:name="android.test.runner"/>
</application>

声明一个instrumentation

<instrumentation android:name="android.test.InstrumentationTestRunner"
                 android:targetPackage="org.cfig.instruments"
                 android:label="Android Self Tests"/>

OTA (2) - diff and patch

(I) boot.img

boot.img is updated in recovery mode

OTA script to update /boot:

package_extract_file("boot.img", "/dev/block/by-name/boot")

the so-called “boot.img” is raw android boot image.

(II) system.img

system.img is updated in recovery mode

OTA script to update /system

block_image_update("/dev/block/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat");

Tools used for system.img

blockimgdiff is google’s diff tool to handle system image in the OTA package, original sparse system.img will be splitted into 3 files: system.new.dat, system.patch.dat, system.transfer.list. This save some space in OTA package.
source location: build/tools/releasetools/blockimgdiff.py

sdat2img is a 3rd party tool to assemble the files (system.new.dat, system.patch.dat, system.transfer.list) into system.img

(III) recovery.img

recovery.img is updated in normal mode by an auto-generated script: /system/bin/install-recovery.sh

Tools used

bsdiff is a general tool to generate binary diff between 2 files.
imgdiff can generate diff between image files, which means source and target file must have same chunk structures.
applypatch is used for android recovery image OTA, it can be used to verify hashcode of an eMMC partition, or apply a patch to a partition. Full partition hash sum is a realiable way to check its integrity.

source code of applypatch & imgdiff is here:
bootable/recovery/applypatch/applypatch.c
bootable/recovery/applypatch/imgdiff.c

source code of bsdiff:
external/bsdiff

Usage

Generate binary patch file:
bsdiff

Generate script to apply patch:
build/tools/releasetools/common.py

Example:

Complete example for updating recovery.img in normal mode:
./build/tools/releasetools/make_recovery_patch <target_file_dir> <patch_file_and_script_dir>
The above command will generate both patch file and updater script.

More detailed usage can be found in private makefiles

security - secure adb

CTS case: testUsbDebugging:
Android: Lollipop

1. What will happen with secure adb

When ro.adb.secure=1 :

For devices w/o USB gadget driver:

(1) vendor key only works for /adb_keys, not for /data/misc/adb/adb_keys
So if you don’t want to see the confirmation dialog:
put ~/.android/adbkey.pub into root directory with name “/adbkeys”.

(2) key verification process will check username/hostname, so other hosts using the same RSA key doesn’t work. (We can hack host machine to workaround)
[ro.build.host]: [my_host]
[ro.build.user]: [my_name]

(3) adb connection via network won’t trigger AUTH confirmation dialog. – This is google bug, we can fix it locally, see EOF.

For devices w/ USB gadget driver:

(1)adb connect will trigger AUTH dialog, then user can decide what to do next.

2. How to enable secure adb

enable secure adb in config:(product.mk)
ifeq ($(TARGET_BUILD_VARIANT),user)
ADDITIONAL_DEFAULT_PROPERTIES += ro.adb.secure=1
endif

or:

ifeq ($(TARGET_BUILD_VARIANT),user)
PRODUCT_PROPERTY_OVERRIDES += ro.adb.secure=1
endif

3. for developers

how to debug adb

/data/adb is used for writing adb debugging information when persist.adb.trace_mask is set.

adb keygen


commit 86c9e5f7e20a3f1712038ce642628c2e1e866434
Author: Nick Kralevich <nnk@google.com>
Date:   Thu Nov 13 15:17:29 2014 -0800

    Introduce "adb keygen"

    Introduce the "adb keygen" command.

      Usage: adb keygen <filename>

    This command creates an adb public/private key pair in a user
    specified file. This can be used to create new adb keys, or rotate
    existing keys.

Attachment: Workaround for network adb

File: frameworks/base/services/usb/java/com/android/server/usb/UsbService.java
Cause: it will check existence of /sys/class/android_usb, if it doesn’t exist, the daemon listener will not start.

Fix:

---
 services/usb/java/com/android/server/usb/UsbDeviceManager.java | 3 ++-
 services/usb/java/com/android/server/usb/UsbService.java       | 4 ++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index f3fa747..42654c7 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -355,7 +355,8 @@ public class UsbDeviceManager {
                 }

                 mCurrentFunctions = getDefaultFunctions();
-                String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
+                //String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
+                String state = "null_state";
                 updateState(state);
                 mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);

diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index fd83f92..919ea90 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -99,9 +99,9 @@ public class UsbService extends IUsbManager.Stub {
         if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
             mHostManager = new UsbHostManager(context);
         }
-        if (new File("/sys/class/android_usb").exists()) {
+        //if (new File("/sys/class/android_usb").exists()) {
             mDeviceManager = new UsbDeviceManager(context);
-        }
+        //}

         setCurrentUser(UserHandle.USER_OWNER);

-- 

jgrep requirement doc

jgrep is obsolete, I use silver searcher now

  1. default with color

like “grep –color”

  1. jgrep a single file

counterpart cmd:
grep -rn “verity” fs_mgr/fs_mgr.c
cmd:
jgrep “verity” fs_mgr/fs_mgr.c
jgrep “verity” -f fs_mgr/fs_mgr.c
options:
-f: specify a file[default]

out:
44:#include “fs_mgr_priv_verity.h”
401: if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
532: if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {

  1. jgrep a single file with groups

options:
-r: show groups

cmd:
jgrep -g “(veri)(ty)” fs_mgr/fs_mgr.c

out:
401:[33,39) if (fs_mgr_setup_verity(&fstab->recs[i]) < verity_kk) {
[0]veri
[1]ty
401:[44,55) if (fs_mgr_setup_verity(&fstab->recs[i]) < verity_kk) {
[0]veri
[1]ty
532:[22,33) if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
[0]veri
[1]ty

  1. jgrep from stdin

cmd:
jgrep “(veri)(ty)” -
“input some text”
“input some text”

<LINE_END>
  1. jgrep recursively

options:
-r

cmd:
jgrep “verity” -r fs_mgr/

out:
fs_mgr/fs_mgr_verity.c:420: if (resume_verity_table(io, mount_point, fd) < 0) {
fs_mgr/fs_mgr_verity.c:424: // assign the new verity block device as the block device
fs_mgr/fs_mgr_verity.c:426: fstab->blk_device = verity_blk_name;
fs_mgr/fs_mgr.c:44:#include “fs_mgr_priv_verity.h”
fs_mgr/fs_mgr.c:401: if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {

  1. jgrep ignore-case option

options:
-i: ignore case

glibc version check

ldd –version

getconf GNU_LIBC_VERSION

dpkg -l libc6

gcc -dumpmachine

gcc -print-file-name=libc.so

/lib/x86_64-linux-gnu/libc.so.6

gnu_get_libc_version()
gnu_get_libc_release()

如果不匹配:
libc.so.6: version 1GLIBC_2.14’ not found”
可以自己编一个libc.so, ln -s libc.so.6 libc.so, 然后用LD_LIBRARY_PATH解决.