The factory test tool I designed is a CS structure. There is a Server on the device side, and a Client on the PC side. The two perform the test through interaction.
Communication Method Selection:
1. stocket: because it is not based on ADB, you can define your own interface, which is relatively stable. Before Android, it seems that most testing tools use this method. You need to run an S program on the device, wait for receiving the command.
2. ADB: Advantages and convenience, directly transplanted to the Android ADBD program can be, and some information transmission D-CODE and P-CODE can be, in Android2.3 ADB gradually stable, I think this method is more convenient.
PC end: the window design needs to be concise, simple, and large buttons to facilitate the operation of factory test workers. interfaces with factory production lines must be open and scalable. (VC development is recommended)
Device: the design must be highly scalable and stable (developed using C)
Let's talk about the design of the device end:
Determine the modules you want to test and determine the functions of the modules you want to test. In this way, separate each module and try to interfere with each other.
Main. h
- #define CMD(cmd) extern int cmd##_main(char**, int, char*);
- #include<DefineCommand.h>
- #undef CMD
- typedef int (*mode_main_func)(char** argv, int argc, char* send_buff);
- typedef struct _MODE
- {
- char* name;
- mode_main_func main_func;
- } MODE;
- MODE g_ModeTable[] = {
- #define CMD(cmd) { #cmd, cmd##_main },
- #include<DefineCommand.h>
- #undef CMD
- };
DefineCommand. h
- CMD(bt)
- CMD(wifi)
- CMD(nfc)
- CMD(fm)
- CMD(audio)
- CMD(headset)
- CMD(mic)
- CMD(speaker)
- CMD(camera)
- CMD(gps)
- CMD(touch)
- CMD(rtc)
- CMD(vibrator)
- CMD(imei)
- CMD(battery)
- CMD(charging)
- CMD(g_sensors)
- CMD(p_sensors)
- CMD(l_sensors)
- CMD(led)
- CMD(lcd)
- CMD(keypad)
- CMD(modem)
- CMD(sd)
- CMD(hdmi)
- CMD(small_camera)
- CMD(lcd_back_light)
- CMD(camera_flash)
Main. c
- MODE * getMode (char * mode );
- Int main (int argc, char ** argv)
- {
- Int ret = 0;
- MODE * tMode = NULL;
- Char * mode_name = (char *) malloc (MODE_SIZE); // Module name
- Char * func_name = (char *) malloc (FUNC_SIZE); // module test function name
- Char * send_buff = (char *) malloc (MAXBUFF );
- Int func_val =-1, func_argc = 0;
- If (argc <ARGC_NUM ){
- // Tpai_loge (mode_name, func_name, COMMAND_ARGC_ERROR );
- Return COMMAND_ARGC_ERROR;
- }
- Stpcpy (mode_name, argv [1]);
- Stpcpy (func_name, argv [2]);
- Func_argc = argc-3;
- TMode = getMode (mode_name );
- If (tMode ){
- Func_val = tMode-> main_func (argv, func_argc, send_buff );
- Switch (func_val)
- {
- Case COMMAND_UNDEFINE_FUNC:
- // Tpai_loge (mode_name, func_name, COMMAND_UNDEFINE_FUNC );
- Ret = COMMAND_UNDEFINE_FUNC;
- Break;
- Case COMMAND_ARGC_ERROR:
- // Tpai_loge (mode_name, func_name, COMMAND_ARGC_ERROR );
- Ret = COMMAND_ARGC_ERROR;
- Break;
- Case COMMAND_EXEC_FAILE:
- // Tpai_loge (mode_name, func_name, COMMAND_EXEC_FAILE );
- Ret = COMMAND_EXEC_FAILE;
- Case COMMAND_EXEC_SUCCESSFUL:
- // TCMD_LOGI (mode_name, func_name, "Successful. \ n ");
- Ret = COMMAND_EXEC_SUCCESSFUL;
- Break;
- Default:
- // Tpai_loge (mode_name, func_name, COMMAND_UNKNOWN_ERROR );
- Ret = COMMAND_UNKNOWN_ERROR;
- Break;
- }
- } Else {
- // Tpai_loge (mode_name, func_name, COMMAND_UNDEFINE_MODE );
- Ret = COMMAND_UNDEFINE_MODE;
- }
- Return ret;
- }
- MODE * getMode (char * name)
- {
- MODE * tMode = NULL;
- Int I = 0;
- Int mode_num = sizeof (g_ModeTable)/sizeof (MODE );
- For (; I <mode_num; ++ I ){
- If (! Strcmp (name, g_ModeTable [I]. name )){
- TMode = & g_ModeTable [I];
- T1__logd ("Mode_table.name = % s", tMode-> name );
- Break;
- }
- }
- Return tMode = NULL? NULL: tMode;
- }
Then, it is executed in the main of each module. The example is battery. c.
- int battery_main(char** argv, int argc, char* send_buff)
- {
- int ret = 0;
- char* func_name = (char *)malloc(FUNC_SIZE);
- stpcpy(func_name, argv[2]);
- if(!strcmp(func_name, "--info"))
- ret = battery_read_info(argv, argc, send_buff);
- else
- ret = COMMAND_UNDEFINE_FUNC;
- return ret;
- }
There are two test methods: one is to directly operate the sys test node provided by the kernel, such as Touch Sensor Battery Rtc, however, large modules such as Audio Camera BT, WIFI, and GPS Modem are not very good for testing, and relevant test modules need to be called, so communication between processes is required, pipefd is the method between the recovery and updater in the recovery.
For example, when testing the modem:
- int modem_read_imsi(char** argv, int argc, char* send_buff)
- {
- int ret = 1;
- const char* binary = MODEM_ADAPTER;
- TCMD_LOGI(argv[1], argv[2], "Test to start...\n");
- if ( argc != MODEM_READ_IMSI_ARGC)
- ret = COMMAND_ARGC_ERROR;
- else {
- int pipefd[2];
- pipe(pipefd);
- const char** args = (const char**)malloc(sizeof(char*) * 4);
- args[0] = binary;
- args[1] = IMSI;
- char* temp = (char*)malloc(10);
- sprintf(temp, "%d", pipefd[1]);
- args[2] = temp;
- args[3] = NULL;
- ret = exec_binary(binary, args, pipefd[0], pipefd[1], send_buff);
- }
- return ret;
- }
- int modem_main(char** argv, int argc, char* send_buff)
- {
- int ret = 0;
- char* func_name = (char *)malloc(FUNC_SIZE);
- stpcpy(func_name, argv[2]);
- if(!strcmp(func_name, "--imei"))
- ret = modem_read_imei(argv, argc, send_buff);
- else if(!strcmp(func_name, "--ue_version"))
- ret = modem_read_uversion(argv, argc, send_buff);
- else if(!strcmp(func_name, "--imsi"))
- ret = modem_read_imsi(argv, argc, send_buff);
- else if(!strcmp(func_name, "--echo"))
- ret = modem_get_status(argv, argc, send_buff);
- else
- ret = COMMAND_UNDEFINE_FUNC;
- return ret;
- }
- int exec_binary(const char* binary, const char** cmd, int fb_p, int fb_c, char* send_buff)
- {
- pid_t pid = fork();
- if (pid == 0) {
- close(fb_p);
- execv(binary, (char* const*)cmd);
- _exit(-1);
- }
- close(fb_c);
- FILE* from_child = fdopen(fb_p, "r");
- int size = fread(send_buff, 1, MAXBUFF, from_child);
- if ( size <= 0)
- return COMMAND_EXEC_FAILE;
- int status;
- waitpid(pid, &status, 0);
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- return COMMAND_EXEC_FAILE;
- return COMMAND_EXEC_SUCCESSFUL;
- }
The advantage of this design is that if there is a problem with the test module, you do not need to modify the test tool to directly update the module's binary.
This is the factory testing tool I designed. It took less than two weeks to design and develop the tool. The integration of related modules was completed in one month, but I still learned a lot from it. Thanks to Song and Daniel, who guided me in thinking!