android_app_Slider

slider view

1. overview

ViewPager provides screen slides,

SliderActivity needs to extend FragmentActivity

SliderActivity needs an adapter(SliderAdapter) to provide fragments

The fragment is really provided by SliderFragment, which extends Fragment

2. class relationship

SliderActivity

  • onCreate()

    activity找到ViewPager, 设置adapter

  • onCreateOptionsMenu

    创建options菜单,显示previous,next

  • onOptionsItemSelected

    配置options menu动作

SliderPagerAdapter

  • getItem()

    使用SliderFragment提供fragment

  • getCount()

    提供总页数

SliderFragment

  • onCreate()

    从bundle获取参数,设置成员变量(请求的页数pageNumber)

  • onCreateView()

    inflate设置好的fragment layout

VPN - pptpd

1. install

apt-get install pptpd

2. enable VPN connection

2.1 /etc/pptpd.conf

vim /etc/pptpd.conf

set localip and remoteip from template like this:

localip 10.0.0.1
remoteip 10.0.0.100-200

this sets local PPP ip and ip pool for VPN clients.

2.2 /etc/ppp/pptpd-options

vim /etc/ppp/pptpd-options

set dns servers:

ms-dns 8.8.8.8
ms-dns 8.8.4.4

please also remember this line:

name pptpd

it is used for authentication.(must match the second field in /etc/ppp/chap-secrets entries)

2.3 /etc/ppp/chap-secrets

vim /etc/ppp/chap-secrets

this file sets auth info for CHAP, edit it like this:

usr pptpd pwd *

'usr' is VPN user name, 'pwd' is VPN password, asterisk means all ip address ranges

2.4 try it out

then this VPN can be successfully connected and client can get IP in range 10.0.0.100-200, but client can not do anything else yet.

logs can be found in /var/log/damon.log, I see this error, but it doesn't matter:

Jan  8 01:46:08 lino88-59 pptpd[3981]: GRE: Bad checksum from pppd.

connection established successfully:

Jan  8 01:46:12 lino88-59 ntpd[3657]: Listen normally on 7 ppp0 192.168.0.1 UDP 123
Jan  8 01:46:12 lino88-59 ntpd[3657]: peers refreshed

3. let client can reach the outside

3.1 sysctl

vim /etc/sysctl.conf

edit it like this to enable ipv4/ipv6 forwading

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

apply the change with

sysctl --system

3.2 iptables

3.2.1 edit

vim /etc/local/vpn_setting

run this command:

iptables -t nat -A POSTROUTING -j SNAT --to-source <Server_Public_IP>

or edit the file like this

*nat
:PREROUTING ACCEPT [29:1779]
:POSTROUTING ACCEPT [8:487]
:OUTPUT ACCEPT [8:487]
-A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
COMMIT
*filter
:INPUT ACCEPT [91:8273]
:FORWARD ACCEPT [6:1886]
:OUTPUT ACCEPT [84:8143]
-A FORWARD -i ppp+ -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j TCPMSS --set-mss 1356
COMMIT

it has 2 rules, 1 will allow 10.0.0.0/24 to access eth0 in MASQUERADE mode, another rule will improve VPN server performance.

3.2.2 apply

vim /etc/rc.local

add the following line into it:

iptables-restore < /etc/local/vpn_setting
exit 0

then

service rc.local restart

this will import the rules to iptables. This setting can be backed up as:

iptables-save > new

3.2.3 try it out

Well done!

OTA (1) - edify

1. edify and flex/bison

a mini OTA script language, implemenation under bootable/recovery/edify/, the README is a good start to study edify.

flex/bison: They are aging unix utils that help to write fast parsers. They are written in C and ouput C code.

Reference: A good turotial on flex/bision

Flex can do the parsing work indepently:

in

sNaZZle 1.3
type foo
type bar
type bas
0 0 10 5        foo
20 10 30 20     foo
7 8 12 13       bas
78 124 100 256  bar
end

snail.l

%{
#include <iostream>
using namespace std;
#define YY_DECL extern "C" int yylex()
%}
%%
[ \t\n]         ;
[0-9]+\.[0-9]+  { cout << "Found a float:" << yytext << endl; }
[0-9]+          { cout << "Found an integer:" << yytext << endl; }
[a-zA-Z0-9]+    { cout << "Found a string: " << yytext << endl; }
%%
int main(int argc, char** argv) {
    yylex();
}

commands to compile and run:

Makefile

t:
    bison -d -v snail.y
    flex -o snail.cpp snail.l
    gcc -x c++ snail.tab.c snail.cpp -lstdc++ -lfl

Run:

$ ./a.out < in

2. sample edify script

2.1 typical flow

(!less_than_int(1470971253, getprop("ro.build.date.utc"))) || abort("Can't install this package (Fri Aug 12 11:07:33 CST 2016) over newer build (" + getprop("ro.build.date") + ").");
getprop("ro.product.device") == "anonymous" || abort("This package is for \"anonymous\" devices; this is a \"" + getprop("ro.product.device") + "\".");
ui_print("Target: google/anonymous/anonymous:6.0.1/MASTER/yzyu08121102:userdebug/test-keys");
show_progress(0.750000, 0);
ui_print("Patching system image unconditionally...");
block_image_update("/dev/block/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat");
ui_print("Verifying the updated system image...");
if range_sha1("/dev/block/by-name/system", "30,0,32770,32825,32827,33281,65535,65536,65538,65992,94567,98304,98306,98361,98363,98817,131071,131072,131074,163840,163842,163897,163899,164353,196607,196608,196610,197064,203177,203178,204788") == "12732a59d40cf97b0374109bdd1971fadfa79124" then
if range_sha1("/dev/block/by-name/system", "32,32770,32825,32827,33281,65535,65536,65538,65992,94567,95079,97792,98304,98306,98361,98363,98817,131071,131072,131074,131586,163328,163840,163842,163897,163899,164353,196607,196608,196610,197064,203177,203178") == "b8c32272d54165b46ba4c727ab8cd062930fab7e" then
ui_print("Verified the updated system image.");
else
  abort("system partition has unexpected non-zero contents after OTA update");
endif;
else
  abort("system partition has unexpected contents after OTA update");
endif;
show_progress(0.050000, 5);
package_extract_file("boot.img", "/dev/block/by-name/boot");
show_progress(0.200000, 10);
sync();
ui_print("Writing fastlogo...");
package_extract_file("fastlogo.img", "/dev/block/by-name/fastlogo");
sync();
ui_print("Writing tzk_normal...");
package_extract_file("tzk_normal.img", "/dev/block/by-name/tzk_normal");
sync();
ui_print("Writing bl_normal...");
package_extract_file("bl_normal.img", "/dev/block/by-name/bl_normal");
sync();
ui_print("Writing bootloader...");
package_extract_file("bootloader.img", "/tmp/bootloader.img");
update_bootloader("/tmp/bootloader.img");
sync();
set_progress(1.000000);

2.2 OTA stages

2.2.1 edify:

ui_print("stage is " + get_stage("/dev/block/mmcblk0p15"));

if (get_stage("/dev/block/mmcblk0p15") == "") then (
    show_progress(0.300000, 5);
    sleep(5);
    set_stage("/dev/block/mmcblk0p15", "2/3");
    reboot_now("/dev/block/mmcblk0p15", "recovery");
) endif;

if (get_stage("/dev/block/mmcblk0p15") == "2/3") then (
    show_progress(0.700000, 5);
    sleep(5);
    set_stage("/dev/block/mmcblk0p15", "3/3");
    reboot_now("/dev/block/mmcblk0p15", "recovery");
) endif;

if (get_stage("/dev/block/mmcblk0p15") == "3/3") then (
    show_progress(0.900000, 3);
    sleep(5);
) endif;

2.2.2 command need to add:

--stages=3

android_app

android app

set up eclipse

  1. Download Android SDK.
    http://developer.android.com/sdk/index.html#ExistingIDE

  2. Insall ADT plugin for Eclipse. http://developer.android.com/sdk/installing/installing-adt.html

First Android app

Add the following into first Android app:

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);

    final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("image/*");
    startActivityForResult(intent, 0);

    return true;
}

This example will demonstrate the usage of Storage Access Framework(SAF).
More details, see https://developer.android.com/guide/topics/providers/document-provider.html#client

PreferenceFragment

Create a java class which extends PreferenceFragment,

String resources: valus/strings.xml

Array resources: values/arrays.xml

<string-array name="list_provinces">
    <item >Shang Hai</item>
    <item >Bei Jing</item>
    <item >Hang Zhou</item>
</string-array>

AndroidManifest.xml

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="org.cfig.a1.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

application has 1 activity, this activity will be started firstly when enter this app.

create preference screen xml: xml/pref.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:holo="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory android:title="Province" >
        <CheckBoxPreference
            android:key="@string/k_province_sh"
            android:summary="City of Magics"
            android:title="Shang Hai" />
        <CheckBoxPreference
            android:key="@string/k_province_bj"
            android:summary="City of Kings"
            android:title="Bei Jing" />

        <SwitchPreference
            android:key="key_switch"
            android:title="Switch" />
    </PreferenceCategory>
    <PreferenceCategory android:title="Select Province" >
        <ListPreference
            android:entries="@array/list_provinces"
            android:entryValues="@array/list_provinces_value"
            android:key="@string/k_province_select"
            android:title="Province" />
    </PreferenceCategory>

    <Preference android:key="k_a" android:title="Start PowerSettings" >
        <intent android:action="org.cfig.powersettings.POWER_SETTING" />
    </Preference>

</PreferenceScreen>

BOOT_COMPLETED receiver

Eclipse for platform development

http://source.android.com/source/using-eclipse.html

Intent fullscreenIntent = new Intent(this, FullscreenActivity.class);
mContext.startActivity(fullscreenIntent);

android_init

android init

boot sequence

early-init, init, early-boot, boot

early-init -> init -> early-boot -> boot

  1. property_get works, but may have random issues. (have not checked yet)
  2. getenv doesn’t work in init itself. Process forked in init also doesn’t work.

system/core/init/property_service.c
load_properties_from_file(PROP_PATH_SYSTEM_BUILD);
property_set()

It will read property file from /system/build.prop and set them.

struts2

1. Prepare struts2 files and setup Eclipse

1.1 Install web server(GlassFish) for Eclipse

Install “GlassFish Tools for Kepler” in “Eclipse Marketplace”. When installation succeed, a “GlassFish” icon will appear in “Menu” -> “Help”.

create “Dynamic Web Project” in Eclipse, “Runtime” -> “New Runtime” -> “GlassFish 4.0”, download GlassFish and install it.

1.2 Download struts2 jar files

Download struts2 jar files from http://struts.apache.org/development/2.x/

Some guides on struts2 http://www.tutorialspoint.com/struts_2/struts_configuration.htm

2. First “Dynamic Web Project” on Glassfish

(1). create project

Project Name: web1:  
default output folder: build\classes  
Context root: web1 (config in WebContent/WEB-INF/glassfish-web.xml  
Content Directory: WebContent  
Generate web.xml depoyment description.  

(2). add simple index.jsp

(3). run on GlassFish

3. First struts2 web project

1. create dynamic web project as in previous chapter

We need struts2 core runtime jars, the core jars can be extracted from struts2-blank.war(in struts-2.x.x-apps.zip).
Add core struts2 jar into build path
Copy core struts2 jar at WEB-INF/lib.

2. add filter into web.xml

web.xml

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

First we create an filter named “struts2”, it’s backed by class org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.
Now we map all /* url to the filter named “struts2”, then all requests to url /* will be feed to class o.a.s.d.n.f.StrutsPrepareAndExecuteFilter.

3. index.jsp

add this into the beginning of the xml, this will support struts2 taglib:

<%@taglib prefix="s" uri="/struts-tags"%>

Then ‘s:form’ can be reconiged in jsp.

add this into <body>, create a simple login form

<H2>System Entry</H2>
<s:form action="loginAction">
    <s:textfield name="theName" label="User"></s:textfield>
    <s:password name="thePwd" label="Password"></s:password>
    <s:submit value="OK"></s:submit>
    <s:reset value="clear"></s:reset>
</s:form>

It creates a simple login webpage. When user click “submit”, the request will be sent to loginAction, with the text fields theName/thePwd passed to the java String variables in action class.
jsp files configure the struts2 actions which can handle web requests.

4. create loginAction

create loginAction(com.LoginAction) which extends ActionSupport, this class will handle requests from index.jsp.

members:

private String theName;
private String thePwd;

theName and thePwd are configured in index.jsp, they will be passed to com.LoginAction when user click “OK” in login screen.

functions:

@Override
public String execute() throws Exception {
    String ret = null;
    if (theName.equals("admin") && thePwd.equals("1")) {
        ActionContext.getContext().getSession().put("login", "true");
        ret = "success";
    } else {
        ret = "fail";
    }

    return ret;
}

execute() will set an ActionContext variable “login” if login success, then return a string to web. The returned string will be used to determine next jsp page.(success->/success.jsp, fail->/fail.jsp, as configured in struts.xml)

5. create struts2 config file: struts.xml

struts.xml configures the jsp files which will be returned to user after action is executed.

Note:
struts.xml should be place at the src/ directory.
PUBLIC ID of DOCTYPE must exactly match the standard struts-2.3.dtd.

Create “struts.xml” from struts-2.3.dtd:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "struts-2.3.dtd" >
<struts>
    <package extends="struts-default" name="struts2">
        <action class="com.LoginAction" name="loginAction">
            <result name="success">/success.jsp</result>
            <result name="fail">/fail.jsp</result>
        </action>
    </package>
</struts>

It creates a package which extends “struts-default”, the package has an actions named “loginAction”(backed by com.LoginAction).
If loginAction returns java String “success”, then the web page will switch to “/success.jsp”, if returns java string “fail”, then “/fail.jsp”.

6. create success.jsp and fail.jsp

The 2 files can be very simple, they only provide some infomation about the status of login(success or fail).

shell_tips

add raw binary payload your shell scripts

1. pack raw binary to sh (stand_alone.raw.sh)

head

#!/bin/sh  
match=$(grep --text --line-number '^PAYLOAD:$' $0 | cut -d ':' -f 1)  
payload_start=$((match + 1))  
tail -n +$payload_start $0 > sepo  
chmod +x sepo  
./sepo  
exit 0  

tail

cat [file] >> stand_alone.raw.sh  

2. run stand_alone.raw.sh

$ ./stand_alone.raw.sh

add uuencoded binary payload your shell scripts

1. pack uuencoded binary to sh (stand_alone.sh)

head

#!/bin/sh
uudecode $0
./sepo
rm sepo
exit 0

tail

uuencode [file] >> stand_alone.sh

2. run stand_alone.sh

$ ./stand_alone.sh

gnu_autotools

autotools

flow

Files used in preparing a software package for distribution, when using just Autoconf:

your source files --> [autoscan*] --> [configure.scan] --> configure.ac

configure.ac --.
               |   .------> autoconf* -----> configure
[aclocal.m4] --+---+
               |   `-----> [autoheader*] --> [config.h.in]
[acsite.m4] ---'

Makefile.in

Additionally, if you use Automake, the following additional productions
come into play:

[acinclude.m4] --.
                 |
[local macros] --+--> aclocal* --> aclocal.m4
                 |
configure.ac ----'

configure.ac --.
               +--> automake* --> Makefile.in
Makefile.am ---'

Files used in configuring a software package:

                       .-------------> [config.cache]
configure* ------------+-------------> config.log
                       |
[config.h.in] -.       v            .-> [config.h] -.
               +--> config.status* -+               +--> make*
Makefile.in ---'                    `-> Makefile ---'

autoconf

autoconf can be seen as a "shell script compiler". It reads some source files, and output portable shell scripts.

tutorial:(autoconf)
1.prepare source files(.c, .h), generate configure.scan with autoscan

(Makefile.am)

2.mv configure.scan configure.ac

3.list all #if,#elif,#ifdef,#ifndef directives with ifnames.

AC_CONFIG_AUX_DIR(build-aux): use auxiliary build tools (eg., install-sh, libtool scripts, automake scripts)

config.status is a hidden slave of configure script. It will take proper actions based on the results of configure.

AC_CONFIG_FILES will create target files from several input files,source files are concatenated.

eg.:
AC_CONFIG_FILES([api.sh:head.sh:body.sh:tail.sh],[chmod +x api.sh])

Spring_framework

intro

Spring framework (homepage)

Spring Release http://spring.io/blog/category/releases

Setup Spring development env in Eclipse

  1. install Spring Tool Suit(STS) for Eclipse.

    http://spring.io/tools/sts/all

  2. download spring jars

Download prebuilt jar files: http://repo.spring.io/release/org/springframework/spring

  1. Enable “ALT + /“: delete “word completion” short key; reassign to “context assist”.

logging

  • commons-logging(JCL): deprecated

  • log4j is nice and all, but no thanks.

  • slf4j

    Need:
    jcl-over-slf4j: redirect commons-logging to slf4j, spring need commons-logging
    slf4j-api: slf4j core api

  • logback

    Need:
    logback-classic.jar: use it to implement real logging
    logback-core.jar

chainsaw is a good online log receiver.

If chainsaw webstart can not run under JDK7/8, need to add “http://logging.apache.org" into java security exception list.

First Spring project

  1. add spring jars to build path

Needed Jars:

expressions
aop
beans
context
core
  1. create spring config xml, then switch to “Spring Config Editor”, a marvellous tool.

  2. create main() class, which loads spring xml.

makefile_in_android

android build system

Preface

On the whole, spending much time on build system is unpromising in my opinion. I even can not find some convenient tools to debug make.
Almost all guys despise those who work on build system. But for too many times, projects met build problems which may live there for years.
In a word, writing makefiles is easy, writing good makefiles is not so.
Android makefiles are beautiful, but it’s tooo slow for small targets. automake is verbose but quick.

This note describes something about the build system in android.

blabla

android make system will use /bin/bash as SHELL, which is more comfortable but low efficiency.
droid is DEFAULT_GOAL.
it has a usefull help goal.
it has a funny out goal.

Android makefiles like eval very much, it uses eval heavily.

Do not override INSTALLED_xxx_TARGET, it may work, but will cause confusions.
Try not to patch android build, use proper VAR to customize, or add extensions. Patch is ugly and hard to maintain.

add projects for ROM companies(vendor)

add /vendorsetup.sh to vendor dir, this will make the product appear in lunch
add BoardConfig as */$(TARGET_DEVICE)/BoardConfig.mk
add AndroidProducts.mk