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)

