Android 5.1.1
1. Android 網路連線機制並不允許同時有兩個device連外, Ethernet > wifi > mobile network. 會有一個評分機制在連線時決定哪個interface可以連線, 其他的連線則會被斷掉. 但是如果在user space使用command方式連線, 是可以看到一個以上的interface 拿到ip, 但是推測從android端連線出去時, 仍只會從priority高的device連出去.
frameworks/base/services/Java/com/android/server/ConnectivityService.java 將以下選項打開
private static final boolean DBG = true;
private static final boolean VDBG = true;
private static final boolean LOGD_RULES = true;
在log中就可以看到相關評分以及切換網路的動作, 可再往下追code.
參考以下網站將相關的code mark掉的話, 先連上wifi 再接上ethernet, 那wifi並不會強制斷線.但是若先接ethernet再接wifi, 那wifi也還是無法連上, 因為這邊只能將已連上的連線不斷線, 並不能搶走舊的連線.
https://stackoverflow.com/questions/37715525/use-multiple-network-interfaces-in-an-app
https://github.com/CyanogenMod/android_frameworks_base/blob/e49d5ea0858a765c22d8aa96cc660d4708a413fb/services/core/java/com/android/server/ConnectivityService.java#L4264
評分機制ethernet固定是150, wifi則根據RSSI來決定分數, 最高不超過100. 若兩者同分, 則以先連線的interface為主.
通過ConnectivityService之後, 如果是wifi連線, 接著會到WifiStatemachine
wifi state machine就會在各個state中切換, 來完成連線的各個動作, 這部份尚待研究.
接著往下會到JNI部份 frameworks/base/core/jni/android_net_wifi_Wifi.cpp
再往下就到wifi hardware部份 hardware/libhardware_legacy/wifi/wifi.c
在wifi.c時會根據傳入的參數來知道是要sta mode, ap mode or p2p mode. 根據知道是什麼mode之後會去reload相對應的fw.
以下是別人寫的ap mode啟動流程.
Setting->WifiManger->WifiService->WifiController->NetworkManagementService(wifiFirmwareReload)->NativeDaemonConnector(execute)->CommandListener->SoftapController(fwReloadSoftap)->wifi_get_fw_path
接著則會根據是什麼mode來決定要使用什麼tool以及讀取或create相關的conf檔案.
如果是sta mode的話, 就使用wpa_supplicant, ap mode則使用hostapd.
參考資料:
http://blog.csdn.net/kangear/article/details/14446527
http://blog.csdn.net/u010961631/article/details/48629601
http://blog.csdn.net/tankai19880619/article/details/42146287
http://blog.csdn.net/myarrow/article/details/8129607
http://blog.csdn.net/xusiwei1236/article/details/48495485
http://blog.sina.com.cn/s/blog_67e1c5cc0101ttqd.html
2017年7月24日 星期一
2017年7月18日 星期二
Uboot passes arguments to kernel
u-boot 要傳參數到kernel可使用 setenv bootargs
cmd line sample
# setenv bootargs androidboot.selinux=disable
# saveenv
code sample
setenv("bootargs", "androidboot.selinux=disable");
但是在android時, 會在image-android.c中的android_image_get_kernel讀取boot.img中的bootargs
boot.img的bootargs放在 BOARD_KERNEL_CMDLINE
BOARD_KERNEL_CMDLINE := console=ttymxc4,115200 init=/init
需注意的是如果code當中有設bootargs的話, 那在android_image_get_kernel就不會使用BOARD_KERNEL_CMDLINE設定的bootargs
接著bootargs會傳到proc/cmdline, 可使用cat來確認傳入的parameter.
若要再交給android做為properties使用, 那可以在bootargs增加androidboot.xxx=xxx
在system/core/init/init.c當中會去處理bootargs.
在import_kernel_nv當中會將androidboot.xxx都換成ro.boot.xxx
所以如果一開始有設置androidboot.selinux=disable的話, 在經過這邊之後會被換成ro.boot.selinux=disable, boot進android之後使用getprop就可以看到了.
另外一些特定的properties則會經過export_kernel_boot_props再parsing一次.
cmd line sample
# setenv bootargs androidboot.selinux=disable
# saveenv
code sample
setenv("bootargs", "androidboot.selinux=disable");
但是在android時, 會在image-android.c中的android_image_get_kernel讀取boot.img中的bootargs
boot.img的bootargs放在 BOARD_KERNEL_CMDLINE
BOARD_KERNEL_CMDLINE := console=ttymxc4,115200 init=/init
需注意的是如果code當中有設bootargs的話, 那在android_image_get_kernel就不會使用BOARD_KERNEL_CMDLINE設定的bootargs
int len = 0; if (*hdr->cmdline) { len += strlen(hdr->cmdline); } char *bootargs = getenv("bootargs"); if (bootargs) len += strlen(bootargs); char *newbootargs = malloc(len + 2); if (!newbootargs) { puts("Error: malloc in android_image_get_kernel failed!\n"); return -ENOMEM; } *newbootargs = '\0'; if (bootargs) { strcpy(newbootargs, bootargs); } else if (*hdr->cmdline) { strcat(newbootargs, hdr->cmdline); }
接著bootargs會傳到proc/cmdline, 可使用cat來確認傳入的parameter.
若要再交給android做為properties使用, 那可以在bootargs增加androidboot.xxx=xxx
在system/core/init/init.c當中會去處理bootargs.
static void process_kernel_cmdline(void) { /* don't expose the raw commandline to nonpriv processes */ chmod("/proc/cmdline", 0440); /* first pass does the common stuff, and finds if we are in qemu. * second pass is only necessary for qemu to export all kernel params * as props. */ import_kernel_cmdline(0, import_kernel_nv); //read kernel parameter here if (qemu[0]) import_kernel_cmdline(1, import_kernel_nv); /* now propogate the info given on command line to internal variables * used by init as well as the current required properties */ export_kernel_boot_props(); } void import_kernel_cmdline(int in_qemu, void (*import_kernel_nv)(char *name, int in_qemu)) { char cmdline[2048]; char *ptr; int fd; fd = open("/proc/cmdline", O_RDONLY); if (fd >= 0) { int n = read(fd, cmdline, sizeof(cmdline) - 1); if (n < 0) n = 0; /* get rid of trailing newline, it happens */ if (n > 0 && cmdline[n-1] == '\n') n--; cmdline[n] = 0; close(fd); } else { cmdline[0] = 0; } ptr = cmdline; while (ptr && *ptr) { char *x = strchr(ptr, ' '); if (x != 0) *x++ = 0; import_kernel_nv(ptr, in_qemu); ptr = x; } }
在import_kernel_nv當中會將androidboot.xxx都換成ro.boot.xxx
static void import_kernel_nv(char *name, int for_emulator) { char *value = strchr(name, '='); int name_len = strlen(name); if (value == 0) return; *value++ = 0; if (name_len == 0) return; if (for_emulator) { /* in the emulator, export any kernel option with the * ro.kernel. prefix */ char buff[PROP_NAME_MAX]; int len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name ); if (len < (int)sizeof(buff)) property_set( buff, value ); return; } if (!strcmp(name,"qemu")) { strlcpy(qemu, value, sizeof(qemu)); } else if (!strncmp(name, "androidboot.", 12) && name_len > 12) { const char *boot_prop_name = name + 12; char prop[PROP_NAME_MAX]; int cnt; cnt = snprintf(prop, sizeof(prop), "ro.boot.%s", boot_prop_name); //change to ro.boot.xxx here if (cnt < PROP_NAME_MAX) property_set(prop, value); } }
所以如果一開始有設置androidboot.selinux=disable的話, 在經過這邊之後會被換成ro.boot.selinux=disable, boot進android之後使用getprop就可以看到了.
另外一些特定的properties則會經過export_kernel_boot_props再parsing一次.
struct { const char *src_prop; const char *dest_prop; const char *def_val; } prop_map[] = { { "ro.boot.serialno", "ro.serialno", "", }, { "ro.boot.mode", "ro.bootmode", "unknown", }, { "ro.boot.baseband", "ro.baseband", "unknown", }, { "ro.boot.bootloader", "ro.bootloader", "unknown", }, };
訂閱:
文章 (Atom)