自动测试移植

平台mtk6739o1




1.工厂模式下权限配置及禁用串口
device/mediatek/mt6739/factory_init.rc


        chown system system dev/ttyGS0
        chmod 0777 dev/ttyGS0
        chmod 0666 dev/kmsg


        chown system system /dev/ttyMT0
        chmod 0777 /dev/ttyMT0
        chown system system dev/ttyGS0
        chmod 0777 dev/ttyGS0
        exec /system/bin/setenforce 0
        stop console
        write /proc/sys/kernel/printk "0 4 0 7"


on property:ro.debuggable=3




2.工厂模式支持自动测试宏
vendor/mediatek/proprietary/bootable/bootloader/preloader/Android.mk


ifeq ($(strip $(CONFIG_TOP_FACTORY)), yes)
PRELOADER_MAKE_OPTION += CONFIG_TOP_FACTORY=y
endif


vendor/mediatek/proprietary/bootable/bootloader/lk/ Android.mk


LK_MAKE_OPTION += CONFIG_TOP_FACTORY=$(CONFIG_TOP_FACTORY)
LK_MAKE_OPTION += CONFIG_BSP_TW_HWINFO=$(CONFIG_BSP_TW_HWINFO)


更改所有TOP_FACTORY宏
vendor/mediatek/proprietary/bootable/bootloader/lk/app/mt_boot/mt_boot.c
vendor/mediatek/proprietary/bootable/bootloader/lk/dev/lcm/lcm_common_topwise/lcm_common_topwise.c
vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6739/boot_mode.c
vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6739/platform.c


vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6739/rules.mk


ifeq ($(strip $(CONFIG_TOP_FACTORY)),yes)
DEFINES += CONFIG_TOP_FACTORY
endif


kernel-4.4 /Android.mk


ifeq ($(wildcard $(TARGET_PREBUILT_KERNEL)),)
    $(info kernel CONFIG_TOP_FACTORY=$(CONFIG_TOP_FACTORY))
        KERNEL_MAKE_OPTION += CONFIG_TOP_FACTORY=$(CONFIG_TOP_FACTORY)


kernel-4.4/Kconfig


config TOP_FACTORY
     bool "topwise modify support"
     default n
     help
       topwise custome macro


kernel-4.4/Makefile


ifeq ($(CONFIG_TOP_FACTORY),yes)
KBUILD_CFLAGS +=  -DCONFIG_TOP_FACTORY
endif




3.添加工厂模式读取proc_tpwmemshow的SELinux权限
device/mediatek/sepolicy/basic/non_plat/factory.te


allow factory proc_tpwmemshow:file {open read write};
//allow factory sysfs_power_supply:dir search;
//allow factory sysfs_power_supply:file rw_file_perms;
//allow factory preloader_block_device:blk_file rw_file_perms;
//allow factory tmpfs:lnk_file read;




4.工厂模式自动测试TP
kernel-4.4/drivers/input/touchscreen/mediatek/mstar_drv/ilitek_drv_main.c


#ifdef CONFIG_TOP_FACTORY
#define GPIO_OUT_ZERO    0
#define GPIO_OUT_ONE     1
#endif


#ifdef CONFIG_TOP_FACTORY
//xieqinghua add for autodiag begin
{
        void e2prom_probe(struct i2c_client *client);
        e2prom_probe(pClient);
}
//xieqinghua add for autodiag end
#endif


#ifdef CONFIG_TOP_FACTORY
//xieqinghua add for autodiag begin
static const struct file_operations virtualtp_proc_fops = {
    .read =  NULL,
    .write = NULL,
};
 void e2prom_probe(struct i2c_client *client)
{
        extern char *saved_command_line;
        printk("CMDLINE:%s\n",saved_command_line);
        if(strstr(saved_command_line,"autodiag_enable=1"))
        {
        union i2c_smbus_data dummy;


        printk("AT24C32D:GTP_INT_PORT=%d,GTP_RST_PORT=%d\n",GTP_INT_PORT,GTP_RST_PORT);
//      mt_set_gpio_dir(GTP_RST_PORT, GPIO_DIR_OUT);
//      mt_set_gpio_dir(GTP_INT_PORT, GPIO_DIR_OUT);


        //gpio_set_value(ts_gpio_irq_pin, 0);
        //gpio_set_value(ts_gpio_wakeup_pin, 0);         
        tpd_gpio_output(GTP_INT_PORT, GPIO_OUT_ZERO);
        tpd_gpio_output(GTP_RST_PORT, GPIO_OUT_ZERO);


        mdelay(10);
        if(0>i2c_smbus_xfer(client->adapter, 0x50, 0, I2C_SMBUS_READ, 0,I2C_SMBUS_BYTE, &dummy))goto AT24C32D_DECT_END;
        printk("AT24C32D:0x50!\n");


        //gpio_set_value(ts_gpio_irq_pin, 1);
        //gpio_set_value(ts_gpio_wakeup_pin, 0);
        tpd_gpio_output(GTP_INT_PORT, GPIO_OUT_ONE);
        tpd_gpio_output(GTP_RST_PORT, GPIO_OUT_ZERO);
        mdelay(10);
        if(0>i2c_smbus_xfer(client->adapter, 0x51, 0, I2C_SMBUS_READ, 0,I2C_SMBUS_BYTE, &dummy))goto AT24C32D_DECT_END;
        printk("AT24C32D:0x51!\n");


        //gpio_set_value(ts_gpio_irq_pin, 0);
        //gpio_set_value(ts_gpio_wakeup_pin, 1);
        tpd_gpio_output(GTP_INT_PORT, GPIO_OUT_ZERO);
        tpd_gpio_output(GTP_RST_PORT, GPIO_OUT_ONE);
        mdelay(10);
        if(0>i2c_smbus_xfer(client->adapter, 0x52, 0, I2C_SMBUS_READ, 0,I2C_SMBUS_BYTE, &dummy))goto AT24C32D_DECT_END;
        printk("AT24C32D:0x52!\n");


        //gpio_set_value(ts_gpio_irq_pin, 1);
        //gpio_set_value(ts_gpio_wakeup_pin, 1);
        tpd_gpio_output(GTP_INT_PORT, GPIO_OUT_ONE);
        tpd_gpio_output(GTP_RST_PORT, GPIO_OUT_ONE);
        mdelay(10);
        if(0>i2c_smbus_xfer(client->adapter, 0x53, 0, I2C_SMBUS_READ, 0,I2C_SMBUS_BYTE, &dummy))goto AT24C32D_DECT_END;
        printk("AT24C32D:0x53!\n");


                proc_create("virtual_tp",0,NULL,&virtualtp_proc_fops);


        AT24C32D_DECT_END:
                printk("AT24C32D:end!\n");
                //gpio_direction_input(ts_gpio_irq_pin);        
//              mt_set_gpio_dir(GTP_INT_PORT, GPIO_DIR_OUT);


        }
}
//xieqinghua add for autodiag begin
#endif


                                                                                                                         
5.支持工厂模式自动测试读取ddr大小
kernel-4.4/fs/proc/meminfo.c


#ifdef CONFIG_TOP_FACTORY
static int mem_ddr_info_proc_show(struct seq_file *m, void *v)
{
        struct sysinfo i;
    unsigned long current_total_ram;


#define K(x) ((x) << (PAGE_SHIFT - 10))
        si_meminfo(&i);
        si_swapinfo(&i);
        current_total_ram = K(i.totalram);
#if 1
    current_total_ram = current_total_ram / 1024;       // to M
    current_total_ram = (current_total_ram + 512) / 512;    // to G/2
    current_total_ram = current_total_ram * 4;    // to Gb.
#else
        current_total_ram = current_total_ram / 1024 * 4;       // to 2Mb
        current_total_ram = (current_total_ram + 200 + 512) / 1024;    // to 2Gb
        current_total_ram = current_total_ram * 2;    // to Gb.
#endif
//      seq_printf(m, "%8lu.\n",  current_total_ram);


        seq_printf(m,
                "MemTotal:       %8lu Gb\n",
                current_total_ram
    );


        return 0;
}
static int mem_ddr_info_proc_open(struct inode *inode, struct file *file)
{
        return single_open(file, mem_ddr_info_proc_show, NULL);
}


static const struct file_operations proc_mem_ddr_info_opts = {
        .owner          = THIS_MODULE,
        .open           = mem_ddr_info_proc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = single_release,
};
#endif


static int __init proc_meminfo_init(void)
#ifdef CONFIG_TOP_FACTORY
        proc_create("tpwmemshow", 0644, NULL, &proc_mem_ddr_info_opts);//add topwise.
#endif




6.合入代码
vendor/mediatek/proprietary/custom/k39tv1_bsp/factory/factory.chn.ini


vendor/mediatek/proprietary/custom/k39tv1_bsp/factory/inc/cust.h
#define FEATURE_FTM_THERMAL 


vendor/mediatek/proprietary/custom/k39tv1_bsp/factory/inc/cust_keys.h
#define KEYS_NUM_COLS 2


#define DEFINE_KEYS_KEYMAP(x) \
struct key x[] = { \
KEYS_PWRKEY_MAP, \
{ KEY_MENU,       "Menu" }, \
{ KEY_HOME,       "Home" }, \
{ KEY_BACK,       "Back" }, \
{ KEY_UP,         "Up" }, \
{ KEY_DOWN,       "Down" }, \
{ KEY_VOLUMEUP,   "VLUp" }, \
{ KEY_VOLUMEDOWN, "VLDown" }, \


#define CUST_KEY_UP KEY_UP
#define CUST_KEY_VOLUP KEY_BACK
#define CUST_KEY_DOWN KEY_DOWN
#define CUST_KEY_VOLDOWN                KEY_VOLUMEDOWN
#define CUST_KEY_LEFT KEY_MENU
#define CUST_KEY_CENTER KEY_HOME
#define CUST_KEY_RIGHT KEY_BACK


#define CUST_KEY_CONFIRM                KEY_POWER
#define CUST_KEY_BACK KEY_VOLUMEUP




7.工厂模式自动测试听筒喇叭音源文件copy
device/mediatek/mt6739/device.mk
PRODUCT_COPY_FILES += vendor/mediatek/proprietary/factory/res/sound/xie.wav:$(TARGET_COPY_OUT_VENDOR)/res/sound/xie.wav




8.合入主要代码


8.1
vendor/mediatek/proprietary/factory/Android.mk


CORE_SRC_FILES := \
src/diag.cpp \


TEST_SRC_FILES := \
src/test/ftm_thermal.cpp \


LOCAL_C_INCLUDES += \
   $(MTK_ROOT)/external/AudioComponentEngine \
hardware/libhardware/include/hardware \


8.2
vendor/mediatek/proprietary/factory/inc/common.h


#define USE_FACTORY_EX  
#define TAG_FACTORY_EX "[FACTORY_EX] "


enum {
#ifdef MTK_SUBALS
    ITEM_SUBALS,
#endif


#ifdef USE_FACTORY_EX
    ITEM_AUTOTEST_REPORT, 
#endif


     ITEM_THERMAL, 
     ITEM_FINGER,
}


8.3
vendor/mediatek/proprietary/factory/inc/events.h


void del_event_ex();
void clear_event_ex();
struct input_event get_event_ex();


8.4
vendor/mediatek/proprietary/factory/inc/ftm.h


#define NO_PREFIX_LOG (-1)
#define FATAL_LOG 0
#define ERROR_LOG 1
#define WARNING_LOG 2
#define INFO_LOG 3
#define DEBUG_LOG 4
#define VERBOSE_LOG 5


#define FTM_MODULE_LOG_LEN 1024


enum {
    FTM_TEST_ERROR = -1,  
... 
    FTM_TEST_BACK,        
...
};


typedef struct {
char log[FTM_MODULE_LOG_LEN+1];
...
} ftm_ata_wifi;


#ifdef USE_FACTORY_EX
typedef struct
{
int read_count;
char barcode[128];
char s_version[256];  //for diag version
}ftm_diag;
#endif


typedef struct{
#ifdef USE_FACTORY_EX
    ftm_diag diag_version;
#endif
} sp_ata_data;


struct ftm_module {
  int           id;
bool          visible;
void         *priv;
ftm_entry_fn  entry;
int           test_result;

bool b_get_result;       
time_t testtime;
long timeout;
struct touch_area t_input ;
struct touch_area t_ref_pass;
struct touch_area t_ref_fail;
bool is_auto_test;
char log[FTM_MODULE_LOG_LEN];
struct timeval tvstart; 
struct timeval tvend;
pthread_t auto_test_thd;
bool is_support_run_in_background;
bool is_need_diag;
int mutex_type;
int (*fun_set_gid)(int);
int (*fun_theradCount)(int id, bool add);
int (*fun_time_elapsed_ms)(struct ftm_module * mod);
};


#ifdef USE_FACTORY_EX
extern item_t *  get_item(int id);
extern int time_elapsed_ms(struct ftm_module * mod);
extern bool get_is_support_run_in_background(int id);
extern bool get_is_need_diag(int id);
extern int get_items_mutex_type(int id);
extern int ftm_view_controller_get_theradCount();
extern int ftm_view_controller_theradCount(int id, bool add);
extern int ftm_view_controller_add_theradCount(int id);
extern int ftm_view_controller_reduce_theradCount(int id);
#endif


8.5
vendor/mediatek/proprietary/factory/inc/miniui.h


#ifdef USE_FACTORY_EX
#define WIEW_DEBUG 0
#define UNKNOWN_ID (-100)
#define MANUAL_TEST_ENTER (-2)
#define MANUAL_TEST_EXIT (-1)
extern int view_controller_set_gid(int id);
extern int view_controller_get_gid();


#define IF_I_CANNOT_REDRAW_THAN_RETURN(view) \
do{ \
  if(!view){ \
   LOGE(TAG_FACTORY_EX"%s view is NULL\n", __FUNCTION__); \
   break; \
  } \
  if(!view->get_gid){ \
     LOGE(TAG_FACTORY_EX"%s view->get_gid is NULL\n", __FUNCTION__); \
   break; \
  } \
  if(!view->set_gid){ \
     LOGE(TAG_FACTORY_EX"%s view->set_gid is NULL\n", __FUNCTION__); \
   break; \
  } \
  if(view->m_id != UNKNOWN_ID){ \
   if(view->get_gid() == MANUAL_TEST_EXIT){ \
LOGD(TAG_FACTORY_EX"%s set_gid id=%d gid=%d\n", __FUNCTION__, view->m_id, view->get_gid()); \
view->set_gid(view->m_id); \
   } \
   if( (view->get_gid() != view->m_id) && (view->m_is_support_run_in_background || view->m_is_need_diag)){ \
if(WIEW_DEBUG){ \
       LOGD(TAG_FACTORY_EX"%s id=%02d gid=%02d background=%s need diag=%s do not redraw!\n", \
             __FUNCTION__, view->m_id, view->get_gid(), \
             view->m_is_support_run_in_background?"true":"false",\
             view->m_is_need_diag?"true":"false"); \
}\
return 0; \
   } \
  } else { \
          LOGW(TAG_FACTORY_EX"%s m_id=%d\n", __FUNCTION__, view->m_id); \
  } \
 }while(0); \




/**
do use this MACRO after 
call ui_init_textview/ui_init_itemview/ui_init_imageview/ui_init_paintview/ui_new_itemview
*/
#define SET_REDRAW_CONFIG(view, priv) \
do{ \
if(!view){ \
LOGE(TAG_FACTORY_EX"%s SET_REDRAW_CONFIG view is NULL\n", __FUNCTION__); \
break; \
} \
if(!(view)->set_redraw_config){ \
LOGE(TAG_FACTORY_EX"%s SET_REDRAW_CONFIG view->set_redraw_config is NULL \
please do it after ui_init_textview/ui_init_itemview/ui_init_imageview/ui_init_paintview/ui_new_itemview\n", __FUNCTION__); \
                     break; \
} \
if(!priv){ \
LOGE(TAG_FACTORY_EX"%s SET_REDRAW_CONFIG priv is NULL\n", __FUNCTION__); \
break; \
} \
  if (!(priv)->mod){ \
LOGE(TAG_FACTORY_EX"%s SET_REDRAW_CONFIG mod is NULL\n", __FUNCTION__); \
break; \
} \
(view)->set_redraw_config((view), (priv)->mod->id, (priv)->mod->is_support_run_in_background, (priv)->mod->is_need_diag);  \
LOGD(TAG_FACTORY_EX"%s SET_REDRAW_CONFIG id=%d background=%s need diag=%s mutex_type=%d\n",  \
        __FUNCTION__, (priv)->mod->id, \
        (priv)->mod->is_support_run_in_background ? "true":"false",  \
        (priv)->mod->is_need_diag ? "true":"false", \
        (priv)->mod->mutex_type); \
       }while(0); \


typedef enum {
MUTEX_TYPE_MODEN = 0,
MUTEX_TYPE_AUDIO,
MUTEX_TYPE_CAMERA,
MUTEX_TYPE_USB,
MUTEX_TYPE_BT_WIFI,

MUTEX_TYPE_NO_MUTEX
}MUTEX_TYPE;
#define item(i, n) { .id = (i), .name = (n) , .background =0 ,.mode =0, .color =0 , .is_support_run_in_background=0, .mutex_type=MUTEX_TYPE_NO_MUTEX, .is_need_diag=0}   
#define item_m(i, n, m) { .id = (i), .name = (n) , .background =0 ,.mode =0, .color =0, .is_support_run_in_background=0, .mutex_type=m, .is_need_diag=0} 
#define item_need_diag(i, n) { .id = (i), .name = (n) , .background =0 ,.mode =0, .color =0 , .is_support_run_in_background=0, .mutex_type=MUTEX_TYPE_NO_MUTEX, .is_need_diag=1}   
#define item_m_need_diag(i, n, m) { .id = (i), .name = (n) , .background =0 ,.mode =0, .color =0, .is_support_run_in_background=0, .mutex_type=m, .is_need_diag=1} 
#define item_b(i, n) { .id = (i), .name = (n) , .background =0 ,.mode =0, .color =0, .is_support_run_in_background=1, .mutex_type=MUTEX_TYPE_NO_MUTEX, .is_need_diag=0} 
#define item_b_m(i, n, m) { .id = (i), .name = (n) , .background =0 ,.mode =0, .color =0, .is_support_run_in_background=1, .mutex_type=m, .is_need_diag=0} 
#define item_b_need_diag(i, n) { .id = (i), .name = (n) , .background =0 ,.mode =0, .color =0, .is_support_run_in_background=1, .mutex_type=MUTEX_TYPE_NO_MUTEX, .is_need_diag=1} 
#define item_b_m_need_diag(i, n, m) { .id = (i), .name = (n) , .background =0 ,.mode =0, .color =0, .is_support_run_in_background=1, .mutex_type=m, .is_need_diag=1}
#else
#define item(i, n) { .id = (i), .name = (n) , .background =0 ,.mode =0 , .color =0}
#endif


struct touch_area{
int x;
int x_end;
int y;
int y_end;
};
extern struct touch_area ftm_get_touch_area(  );
extern int ftm_get_touch_menu_select();
extern int ftm_match_touch(struct touch_area a_input, const struct touch_area a_reference); // 0:match -1: not match
extern int ftm_match_touch_pass();// 0:match -1: not match
extern int ftm_match_touch_back();// 0:match -1: not match
extern int ftm_match_touch_fail();// 0:match -1: not match
extern int ftm_match_touch_result();// FTM_TEST_UNKNOWN / FTM_TEST_PASS / FTM_TEST_FAIL


typedef struct {
    int         id;
    const char *name;
    color_t     background;
int mode;
    color_t     color;
#ifdef USE_FACTORY_EX
    bool is_support_run_in_background;
    //get_items_mutex_type(id);会更安全点
    //请尽量使用mod->mutex_type,这里的mutex_type有可能并没有设置
    //目前只在ftm_test_items有设置mutex_type
    MUTEX_TYPE mutex_type;
    bool is_need_diag;
#endif
} item_t;


struct itemview {
    char menu[MAX_ROWS][MAX_COLS*2];
    char text[MAX_ROWS][MAX_COLS*2];
    int  text_col;
    int  text_row;
    int  text_top;
    int  menu_top;
    int  menu_from;
    int  menu_items;
    int  menu_sel;
    int  m_redraw;
    text_t *m_title;
    item_t *m_items;
    text_t *m_text;
    item_t *m_left_btn;
    item_t *m_right_btn;
    item_t *m_center_btn;
#ifdef USE_FACTORY_EX
    int    m_id; // whitch TESTITEM id i belong to
    int m_is_support_run_in_background;
    int m_is_need_diag;
    int (*get_gid)();
    int (*set_gid)(int);
    int (*set_redraw_config)(struct itemview *iv, int item_id, bool background, bool diag);
#endif
    int m_selected;
    int page_index;
    int round_flag;
    int (*set_title)(struct itemview *iv, text_t *title); 
    int (*set_text)(struct itemview *iv, text_t *text);
    int (*set_items)(struct itemview *iv, item_t *items, int selected);
    int (*set_btn)(struct itemview *tv, item_t *left, item_t *center, item_t *right);
    int (*run)(struct itemview *iv, bool *exit);
    int (*redraw)(struct itemview *iv);
    int (*exit)(struct itemview *iv);
    void (*start_menu)(struct itemview *iv, int item_sel);
};


struct textview {
    int  m_redraw;
    int  m_exit;
    void *m_priv;
    char **m_pstr;
    khandler m_khandler;


    text_t *m_title;
    text_t *m_text;
    text_t *m_left_btn;
    text_t *m_right_btn;
    text_t *m_center_btn;
    ctext_t *m_ctexts;
    int  m_nr_ctexts;
    int  m_nr_lines;
    int  m_start;
    int  m_end;
#ifdef USE_FACTORY_EX
    int    m_id;
    bool m_is_support_run_in_background;
    bool m_is_need_diag;
    int (*get_gid)();
    int (*set_gid)(int);
    int (*set_redraw_config)(struct textview *tv, int item_id, bool background, bool diag);
#endif


    int (*set_title)(struct textview *tv, text_t *title);
    int (*set_text)(struct textview *tv, text_t *text);
    int (*set_ctext)(struct textview *tv, ctext_t *ctexts, int nr_ctext);
    int (*set_btn)(struct textview *tv, text_t *left, text_t *center, text_t *right);
    int (*run)(struct textview *tv);
    int (*redraw)(struct textview *tv);
    int (*exit)(struct textview *tv);
};


struct imageview {
    int m_redraw;
    int  m_exit;
    void *m_priv;
    khandler m_khandler;


    image_t m_image;
    color_t m_background;


    text_t *m_title;
    text_t *m_left_btn;
    text_t *m_right_btn;
    text_t *m_center_btn;
#ifdef USE_FACTORY_EX
    int    m_id;
    bool m_is_support_run_in_background;
    bool m_is_need_diag;
    int (*get_gid)();
    int (*set_gid)(int);
    int (*set_redraw_config)(struct imageview *iv, int item_id, bool background, bool diag);
#endif


    int (*set_title)(struct imageview *imv, text_t *title);
    int (*set_image)(struct imageview *imv, char *filename, int x, int y);
    int (*set_background)(struct imageview *imv, color_t background);
    int (*set_btn)(struct imageview *imv, text_t *left, text_t *center, text_t *right);
    int (*redraw)(struct imageview *imv);
    int (*run)(struct imageview *imv);
    int (*exit)(struct imageview *imv);
};


struct paintview {
    int        m_redraw;
    int        m_exit;
    void        *m_priv;
    text_t      *m_title;
   
    khandler    m_khandler;
    
    text_t      *m_left_btn;
    text_t      *m_right_btn;
    text_t      *m_center_btn;


    point_t     *m_points;
    line_t      *m_lines;
    circle_t    *m_circles;


    int         m_nr_points;    
    int         m_nr_lines;
    int         m_nr_circles;
    image_t *m_img; 
#ifdef USE_FACTORY_EX
    int    m_id;
    bool m_is_support_run_in_background;
    bool m_is_need_diag;
    int (*get_gid)();
    int (*set_gid)(int);
    int (*set_redraw_config)(struct paintview *pv, int item_id, bool background, bool diag);
#endif


    int (*set_title)(struct paintview *pv, text_t *title);
    int (*set_btn)(struct paintview *pv, text_t *left, text_t *center, text_t *right);
    int (*set_point)(struct paintview *pv, point_t *my_point, int nr_points);
    int (*set_line)(struct paintview *pv, line_t *my_line, int nr_lines);
    int (*set_circle)(struct paintview *pv, circle_t *my_circle, int nr_circles);    
    int (*set_img) (struct paintview *pv, image_t *my_img);
    int (*run)(struct paintview *pv);
    int (*redraw)(struct paintview *pv);
    int (*drawpoint)(struct paintview *pv);
    int (*drawline)(struct paintview *pv);
    int (*drawcircle)(struct paintview *pv);        
    int (*drawimg)(struct paintview *pv);
    int (*flip)(void);
    int (*exit)(struct paintview *pv);
};


extern int ui_wait_all_key(); // for ui


#ifdef USE_FACTORY_EX
extern int set_redraw_config_textview(struct textview *tv, int item_id, bool background, bool diag);
extern int set_redraw_config_itemview(struct itemview *iv, int item_id, bool background, bool diag);
extern int set_redraw_config_imageview(struct imageview *iv, int item_id, bool background, bool diag);
extern int set_redraw_config_paintview(struct paintview *pv, int item_id, bool background, bool diag);
#endif


8.6
vendor/mediatek/proprietary/factory/inc/uistrings_chn.h


#define uistr_autotest_report "测试报告(自动测试)"
#define uistr_test_report_diag "测试报告(主控盒)"
#define uistr_ps_far            "距离传感器远离"
#define uistr_ps_far_tips       "请远离距离传感器"
#define uistr_ps_near           "距离传感器接近"
#define uistr_ps_near_tips      "请遮挡距离传感器"
#define uistr_info_audio_loopback_phone_submic_speaker "手机副麦克扬声器回路"
#define uistr_info_audio_loopback_phone_submic_receiver               "副麦听筒回路"
#define uistr_info_cd_gpio_status "热插拔中断脚检测"
#define uistr_info_cd_gpio_unset "项目支持热插拔但是驱动未配置支持热插拔"
#define uistr_info_cd_gpio_unsupport "不支持热插拔"
#define uistr_info_wifi_rssi_fail   "指定的热点信号强度不足"
#define uistr_info_otg_status_host "主机(已经连接OTG)"
#define uistr_info_otg_total_size  "容量:"
#define uistr_info_otg_pass "OTG存储设备已连接,测试通过"
#define uistr_info_otg_waitting "OTG等待设备连接"
#define uistr_info_otg_no_storage "OTG线已连接,未插U盘"
#define uistr_info_g_sensor_tips                                              "测试时请水平放置,如果测试不通过请尝试加速度传感器校准"
#define uistr_info_back                     "返回"
#define uistr_info_retry                    "重试"
#define uistr_fingerprint_test "指纹"
#define uistr_fingerprint "指纹测试"
/*Thermal Sensors*/
#define uistr_info_thermal "温度传感器"


8.7
vendor/mediatek/proprietary/factory/inc/uistrings_eng.h


#define uistr_autotest_report         "Test Report(Autotest)"
#define uistr_test_report_diag        "Test Report(diag)"
#define uistr_info_audio_loopback_phone_submic_speaker                "Loopback-PhoneSubMic_SpeakerLR" 
#define uistr_info_audio_loopback_phone_submic_receiver               "Loopback-PhoneSubMic_ReceiverLR"
#define uistr_ps                "PS"
#define uistr_ps_far            "PS FAR"
#define uistr_ps_far_tips       "Please move away"
#define uistr_ps_near           "PS NEAR"
#define uistr_ps_near_tips      "Please close to ps"
#define uistr_info_cd_gpio_status "Card detection"
#define uistr_info_cd_gpio_unset "project support memory card hotplug, but driver have not set hotplug support!"
#define uistr_info_cd_gpio_unsupport "Unsupport hotplug"
#define uistr_info_wifi_rssi_fail   "Signal shortage"
#define uistr_info_otg_total_size  "Total Size:"
#define uistr_info_otg_pass "OTG devices plugged in PASS"
#define uistr_info_otg_waitting "OTG Waitting"
#define uistr_info_otg_no_storage "OTG cable plugged in, but no storage"
#define uistr_info_g_sensor_tips                                              "Horizontal placement when testing, if failed try G-Sensor cali."
#define uistr_info_back                    "Back"
#define uistr_info_retry                    "Retry"
#define uistr_fingerprint_test "Fingerprint"
#define uistr_fingerprint "Fingerprint test"
/*Thermal Sensors*/
#define uistr_info_thermal "Thermal Sensors"


8.8
vendor/mediatek/proprietary/factory/inc/utils.h


#define BUFSZ           4096 


int readFile(const char * path, char * outString, int outStringLen); 


bool is_efuse_enabled(); 


int64_t get_curr_time_ms(void);


8.9自动测试代码
vendor/mediatek/proprietary/factory/src/diag.cpp


8.10
vendor/mediatek/proprietary/factory/src/factory.cpp


#ifdef USE_FACTORY_EX
#undef LOG_TAG
#define LOG_TAG "FTM"
#endif


#ifdef USE_FACTORY_EX
extern pthread_mutex_t auto_test_mutex_array[MUTEX_TYPE_NO_MUTEX] = {PTHREAD_MUTEX_INITIALIZER};
extern sp_ata_data return_data;
class CFunctionTracer
{
public:
CFunctionTracer(const char * fun)
{
memset(m_info, 0, ARRAY_SIZE(m_info) );
if(fun){
strncpy(m_info, fun, strlen(fun) < 1024 ? strlen(fun) : 1024);
}else{
LOGE(m_info, "%s", "unknown function");
}
LOGD(TAG"%s %s <---Enter\n", m_info, __FUNCTION__);
}
~CFunctionTracer()
{
LOGD(TAG"%s %s --->Exit\n", m_info, __FUNCTION__);
}
private:
char m_info[1024];
CFunctionTracer();
CFunctionTracer(const CFunctionTracer & other);
CFunctionTracer & operator = (const CFunctionTracer & other);
};
#endif
extern int maxrows;
char test_report[32] = "/data/testreport.log";
char ftm_cust_file1[32] = "/sdcard/factory.ini";
char ftm_cust_file2[32] = "/vendor/etc/factory.ini";


static item_t ftm_menu_items[] = {
#ifdef USE_FACTORY_EX
    item(ITEM_REPORT,    uistr_test_report_diag),                    //"测试报告(主控盒)"
    item(ITEM_AUTOTEST_REPORT, uistr_autotest_report),      //"测试报告(自动测试)"
#else
    item(ITEM_REPORT,    uistr_test_report),                           //"测试报告"
#endif
};


#ifdef USE_FACTORY_EX
extern "C" int restore_test_report_eng()
#else
int restore_test_report_eng()
#endif
{
    int item_id;
    struct ftm_module *mod;
    uint16_t flags[64];
    char *auto_flags = (char *)flags;


    if (get_manual_test_flags((char *)flags, sizeof(flags))) {
        if (flags[0] != 0) {
            for (int i = 0; (i < ARRAY_SIZE(flags)) && (flags[i] != 0); i++) {
                item_id = (flags[i] >> 2) & 0x3FFF;
                mod = ftm_get_module(item_id);
                if (mod && mod->visible) {
                    switch (flags[i] & 0x3) {
                    case 0:
                    case 1:
                        mod->test_result = FTM_TEST_UNKNOWN;
                        break;


                    case 2:
                        mod->test_result = FTM_TEST_FAIL;
                        break;


                    case 3:
                        mod->test_result = FTM_TEST_PASS;
                        break;
                    }
                }
            }
            return 1;
        }
    }


    if (get_auto_test_flags((char *)flags, sizeof(flags))) {
        if (auto_flags[0] == 'P') {
            for (int i = 0; i < sizeof(flags) && i < ARRAY_SIZE(auto_test_item_ids); i++) {
                item_id = auto_test_item_ids[i];
                if (item_id == -1)
                    continue;
                mod = ftm_get_module(item_id);
                if (mod && mod->visible) {
                    switch (auto_flags[i]) {
                    case 'P':
                        mod->test_result = FTM_TEST_PASS;
                        break;
                    case 'F':
                        mod->test_result = FTM_TEST_FAIL;
                        break;
                    default:
                        mod->test_result = FTM_TEST_UNKNOWN;
                        break;
                    }
                }
            }


            item_id = ITEM_BACKLIGHT;
            mod = ftm_get_module(item_id);
            if (mod && mod->visible) {
                if (auto_flags[1] == 'F' || auto_flags[27] == 'F') {
                    mod->test_result = FTM_TEST_FAIL;
                } else if (auto_flags[1] == 'U' && auto_flags[27] == 'U') {
                    mod->test_result = FTM_TEST_UNKNOWN;
                } else {
                    mod->test_result = FTM_TEST_PASS;
                }
            }


            item_id = ITEM_HEADSET;
            mod = ftm_get_module(item_id);
            if (mod && mod->visible) {
                if (auto_flags[3] == 'P' && auto_flags[10] == 'P') {
                    mod->test_result = FTM_TEST_PASS;
                } else if (auto_flags[3] == 'F' || auto_flags[10] == 'F') {
                    mod->test_result = FTM_TEST_FAIL;
                } else {
                    mod->test_result = FTM_TEST_UNKNOWN;
                }
            }


            item_id = ITEM_ALS;
    mod = ftm_get_module(item_id);
            if (mod && mod->visible) 
            {
if (auto_flags[23] == 'P') mod->test_result = FTM_TEST_PASS;
else if (auto_flags[23] == 'F') mod->test_result = FTM_TEST_FAIL;
else mod->test_result = FTM_TEST_UNKNOWN;
            }

            item_id = ITEM_PS;
            mod = ftm_get_module(item_id);
            if (mod && mod->visible) 
            {
if (auto_flags[23] == 'P') mod->test_result = FTM_TEST_PASS;
else if (auto_flags[23] == 'F') mod->test_result = FTM_TEST_FAIL;
else mod->test_result = FTM_TEST_UNKNOWN;
            }


            #ifdef MTK_SUBALS
    item_id = ITEM_SUBALS;
    mod = ftm_get_module(item_id);
    if (mod && mod->visible) 
            {
if (auto_flags[23] == 'P') mod->test_result = FTM_TEST_PASS;
else if (auto_flags[23] == 'F') mod->test_result = FTM_TEST_FAIL;
else mod->test_result = FTM_TEST_UNKNOWN;
            }
            #endif


            //add for bug 22261
            #ifdef CONFIG_BREATH_LIGHT
            item_id = ITEM_LED;  // in the Autotest_TP test check led i2c
    mod = ftm_get_module(item_id);
    if (mod && mod->visible) 
            {
if (auto_flags[4] == 'P') mod->test_result = FTM_TEST_PASS;
else if (auto_flags[4] == 'F') mod->test_result = FTM_TEST_FAIL;
else mod->test_result = FTM_TEST_UNKNOWN;
            }
    #endif
 
            item_id = ITEM_GS_CALI;
    mod = ftm_get_module(item_id);
    if (mod && mod->visible) 
            {
if (auto_flags[21] == 'P') mod->test_result = FTM_TEST_PASS;
else if (auto_flags[21] == 'F') mod->test_result = FTM_TEST_FAIL;
else mod->test_result = FTM_TEST_UNKNOWN;
            }
 
            item_id = ITEM_THERMAL;
    mod = ftm_get_module(item_id);
    if (mod && mod->visible) 
            {
if (auto_flags[0] == 'P') mod->test_result = FTM_TEST_PASS;
else if (auto_flags[0] == 'F') mod->test_result = FTM_TEST_FAIL;
else mod->test_result = FTM_TEST_UNKNOWN;
            }


    item_id = ITEM_SIM;
    mod = ftm_get_module(item_id);
    if (mod && mod->visible) 
            {
            #if defined(GEMINI) || defined(MTK_GEMINI_3SIM_SUPPORT)|| defined(EVDO_DT_VIA_SUPPORT) || defined(EVDO_DT_SUPPORT) || defined(MTK_C2K_SUPPORT) || defined(FTM_SIM_USE_USIMSMT)
if(auto_flags[26] == 'P' && auto_flags[48] == 'P') mod->test_result = FTM_TEST_PASS;
else if (auto_flags[26] == 'F' || auto_flags[48] == 'F') mod->test_result = FTM_TEST_FAIL;
else mod->test_result = FTM_TEST_UNKNOWN;
    #else
if (auto_flags[26] == 'P') mod->test_result = FTM_TEST_PASS;
else if (auto_flags[26] == 'F') mod->test_result = FTM_TEST_FAIL;
else mod->test_result = FTM_TEST_UNKNOWN;
    #endif
            }  
            return 1;
        }
    }


    return 0;
}


int create_report(item_t *item, item_t *rpt_items, int maxitems, char *buf, int size)
{
#ifdef USE_FACTORY_EX
    item_t * itemtemp = item; 
    int iend = 0;
#endif


#ifdef USE_FACTORY_EX
    //sort the test result
    while (i < maxitems && item->name) 
    {
        mod = ftm_get_module(item->id);
        if (mod && mod->visible && len < size && mod->test_result != FTM_TEST_PASS) 
        {
            ptr = buf + len;
            len += sprintf(ptr, "[%c] %s",
                (mod->test_result >= FTM_TEST_MAX) ?
                result[FTM_TEST_UNKNOWN] : result[mod->test_result], item->name);
            ptr[len++] = '\0';
            rpt_items[i].id = mod->id;
            rpt_items[i].name = ptr;
            rpt_items[i].color = (mod->test_result >= FTM_TEST_MAX) ?
                0 : bgc[mod->test_result];


            if (i < ARRAY_SIZE(flags)) {
                switch (mod->test_result) {
                case FTM_TEST_PASS:
                    flags[i] = (mod->id << 2) | 0x3;
                    break;
                case FTM_TEST_FAIL:
                    flags[i] = (mod->id << 2) | 0x2;
                    break;
                default:
                    flags[i] = (mod->id << 2) | 0x1;
                    break;
                }
            }


            i++;
        }
        item++;
    } 

    item = itemtemp;
    iend = i;
    i = 0;
    while (i < maxitems && item->name) 
    {
        mod = ftm_get_module(item->id);
        if (mod && mod->visible && len < size && mod->test_result == FTM_TEST_PASS) 
        {
            ptr = buf + len;
            len += sprintf(ptr, "[%c] %s",
                (mod->test_result >= FTM_TEST_MAX) ?
                result[FTM_TEST_UNKNOWN] : result[mod->test_result], item->name);
            ptr[len++] = '\0';
            rpt_items[iend].id = mod->id;
            rpt_items[iend].name = ptr;
            rpt_items[iend].color = (mod->test_result >= FTM_TEST_MAX) ?
                0 : bgc[mod->test_result];


            if (iend < ARRAY_SIZE(flags)) {
                switch (mod->test_result) {
                case FTM_TEST_PASS:
                    flags[iend] = (mod->id << 2) | 0x3;
                    break;
                case FTM_TEST_FAIL:
                    flags[iend] = (mod->id << 2) | 0x2;
                    break;
                default:
                    flags[iend] = (mod->id << 2) | 0x1;
                    break;
                }
            }


            i++;
    iend++;
        }
        item++;
    } 
#else
    while (i < maxitems && item->name) 
    {
        mod = ftm_get_module(item->id);
        if (mod && mod->visible && len < size) 
        {
            ptr = buf + len;
            len += sprintf(ptr, "[%c] %s",
                (mod->test_result >= FTM_TEST_MAX) ?
                result[FTM_TEST_UNKNOWN] : result[mod->test_result], item->name);
            ptr[len++] = '\0';
            rpt_items[i].id = mod->id;
            rpt_items[i].name = ptr;
            rpt_items[i].color = (mod->test_result >= FTM_TEST_MAX) ?
                0 : bgc[mod->test_result];


            if (i < ARRAY_SIZE(flags)) {
                switch (mod->test_result) {
                case FTM_TEST_PASS:
                    flags[i] = (mod->id << 2) | 0x3;
                    break;
                case FTM_TEST_FAIL:
                    flags[i] = (mod->id << 2) | 0x2;
                    break;
                default:
                    flags[i] = (mod->id << 2) | 0x1;
                    break;
                }
            }


            i++;
        }
        item++;
    }
#endif


#ifdef USE_FACTORY_EX
    set_manual_test_flags((char *)flags, sizeof(flags));
#else
    //add for saving test report
    fp = open_file(test_report);


if(fp == NULL)
{
   LOGD(TAG "TEST_REPORT_SAVE_FILE is null");
}
else
{
   LOGD(TAG "TEST_REPORT_SAVE_FILE is not null");
        write_test_report(rpt_items, fp);
fclose(fp);
        fp = NULL;
}
#endif


#ifdef USE_FACTORY_EX
    if (iend < maxitems - 1) {
        rpt_items[iend].id   = ITEM_MAX_IDS; 
        rpt_items[iend].name = uistr_info_test_report_back;
    }    
    return ++iend;
#else
#ifndef FEATURE_FTM_TOUCH_MODE
    if (i < maxitems - 1)
    {
        rpt_items[i].id   = ITEM_MAX_IDS;
        rpt_items[i].name = uistr_info_test_report_back;
    }
    #endif
    return ++i;
#endif
}


#ifdef USE_FACTORY_EX
extern "C" int my_item_test_report(item_t *items, const char *title, char *buf, int bufsz)
#else
static int my_item_test_report(item_t *items, const char *title, char *buf, int bufsz)
#endif


static int item_test_report(item_t *items, char *buf, int bufsz)
{
#ifdef USE_FACTORY_EX
    return my_item_test_report(items, uistr_test_report_diag, buf, bufsz);
#else
    return my_item_test_report(items, uistr_test_report, buf, bufsz);
#endif
}


#ifdef USE_FACTORY_EX
extern "C" bool check_autodiag_mode(void);
static void *auto_test_thread(void *priv) {
    int i= (int)(long)(priv);
    item_t *items;
    static bool bHaveGetPara = false;
    static int nThreadLimit = 0;
    char *pThreadLimit;
    struct ftm_module *mod;
    struct ftm_param param;
    items=get_auto_item_list();
    mod= ftm_get_module(items[i].id);

    char temp[1024] = {0};
    sprintf(temp, "%s name=%s id=%d background=%s diag=%s\n", __FUNCTION__, items[i].name, items[i].id,
mod->is_support_run_in_background?"true":"false", mod->is_need_diag?"true":"false");
    CFunctionTracer tracer(temp);
    if(0 == nThreadLimit)
    {    
       pThreadLimit = ftm_get_prop("FTM.THREADLIMIT");
   if(pThreadLimit)
   {
       nThreadLimit = atoi(pThreadLimit);
if(nThreadLimit<=0)
       {
nThreadLimit = 1000;
       }
   }
   else
   {
nThreadLimit = 1000;
   }
   LOGD("FTM.THREADLIMIT=%s\n", pThreadLimit);
    }
    
    while(ftm_view_controller_get_theradCount()>= nThreadLimit)
    {
           LOGD(TAG"nThreadCount(%d) >= nThreadLimit(%d) waitting other thread exit!\n", ftm_view_controller_get_theradCount() , nThreadLimit);
       usleep(1000*1000);
    }
    
    if (mod && mod->visible) {
        param.name = items[i].name;
param.test_type = get_item_test_type(items, param.name);


//test order: CFT SIM GPS begin
if(ITEM_GPS == items[i].id || ITEM_SIM == items[i].id){
int j = 0;
int tick = 0;
int timeout = 30;
struct ftm_module *modcft = NULL;
struct ftm_module *modsim = NULL;
while(items[j].name){
if(ITEM_CFT == items[j].id){
modcft = ftm_get_module(items[j].id);
} else if(ITEM_SIM == items[j].id){
modsim = ftm_get_module(items[j].id);
}


if(modcft && modsim){
break;
}
j++;
}


while(modcft && (modcft->test_result == FTM_TEST_UNKNOWN) && (tick<timeout)){
LOGD(TAG"%s waitting for CFT\n", __FUNCTION__);
usleep(1000*1000);
tick++;
}


              if(ITEM_GPS == items[i].id){
while(modsim && (modsim->test_result == FTM_TEST_UNKNOWN) && (tick<timeout)){
LOGD(TAG"%s waitting for SIM\n", __FUNCTION__);
usleep(1000*1000);
tick++;
}
              }
}
//test order: CFT SIM GPS end
 
if(mod->mutex_type != MUTEX_TYPE_NO_MUTEX){
LOGD(TAG"%s lock %p type=%d\n", __FUNCTION__, &auto_test_mutex_array[mod->mutex_type], mod->mutex_type);
pthread_mutex_lock(&auto_test_mutex_array[mod->mutex_type]);
LOGD(TAG "AUTOTEST Start ---> %s pthread_mutex_lock(mutex type=%d)\n", param.name, mod->mutex_type);
}


mod->is_auto_test = true;
        ftm_entry(items[i].id, &param); 
mod->is_auto_test = false;
if(mod->mutex_type != MUTEX_TYPE_NO_MUTEX){
LOGD(TAG "AUTOTEST Exit <--- %s pthread_mutex_unlock(mutex type=%d)\n", param.name, mod->mutex_type);
LOGD(TAG"%s unlock %p type=%d\n", __FUNCTION__, &auto_test_mutex_array[mod->mutex_type], mod->mutex_type);
pthread_mutex_unlock(&auto_test_mutex_array[mod->mutex_type]);
}
    }


    LOGD(TAG"%s exit thread items[%02d] id=%2d name=%s test_result=%s\n", 
param.name, i, items[i].id, param.name, (mod->test_result==FTM_TEST_PASS)?"PASS":"FAIL");
    pthread_exit(NULL);
    return NULL;
}
static int auto_test_mode(char *buf, int bufsz)
{
    CFunctionTracer tracer(__FUNCTION__);

    int i = 0;
    item_t *items, *cust_items;
    struct ftm_module *mod;
    struct ftm_param param;


    //add for saving test report
    item_t rpt_items[ITEM_MAX_IDS + 1];
    int stopmode = 0;
    char *stopprop = ftm_get_prop("FTM.FailStop");


    if(buf == NULL)
    {
        return -1;
    }


    if (stopprop && !strncasecmp(stopprop, "yes", strlen("yes")))
        stopmode = 1;


    LOGD(TAG "auto_test_mode: %d", stopmode);


    items = get_auto_item_list(); //get_item_list();
    //add for saving test report
    cust_items = get_auto_item_list(); //get_item_list();
    memset(rpt_items, 0, sizeof(item_t) * (ITEM_MAX_IDS + 1));


    // run autotest first
    while (items[i].name) 
    {
        mod = ftm_get_module(items[i].id);
if(mod){
LOGD(TAG"%s %s id:%d mode:%d background:%s diag:%s\n",__FUNCTION__, items[i].name, items[i].id, items[i].mode, 
mod->is_support_run_in_background?"true":"false", mod->is_need_diag?"true":"false");
if((mod->is_support_run_in_background && !check_autodiag_mode())
|| (mod->is_need_diag && check_autodiag_mode())){
if(mod->visible){
#if 1
pthread_attr_t thread_attr;
struct sched_param schedule_param;
pthread_attr_init(&thread_attr);
if(ITEM_GPS == items[i].id){
   schedule_param.sched_priority = 0;
}else{
   schedule_param.sched_priority = 99;
}
pthread_attr_setschedpolicy(&thread_attr,SCHED_RR);
pthread_attr_setschedparam(&thread_attr, &schedule_param); 


pthread_create(&(mod->auto_test_thd), &thread_attr, auto_test_thread, reinterpret_cast<void*>(i)); 
#else
pthread_create(&(mod->auto_test_thd), NULL, auto_test_thread, reinterpret_cast<void*>(i)); 
#endif
}else{
      LOGE(TAG"%s name=%s id=%d mod->visible=false not create thread.\n",__FUNCTION__, items[i].name, items[i].id);
}
}
}else{
      LOGE(TAG "%s name=%s id=%d mod is NULL not create thread.\n",__FUNCTION__, items[i].name, items[i].id);
}
        i++;
    }


    if(!check_autodiag_mode()){
   LOGD(TAG "%s run the manul test items begin\n", __FUNCTION__);
   i = 0;
   while (items[i].name) 
   {
       LOGD(TAG "%s now run the manul test %s:%d:%d",__FUNCTION__, items[i].name, items[i].id, items[i].mode);
       switch (items[i].id) 
       {
           case ITEM_IDLE: /* skip items */
               break;
           case ITEM_REPORT:
               item_test_report(items, buf, bufsz);
               break;
           default:
               mod = ftm_get_module(items[i].id);
 if(mod && !mod->is_support_run_in_background){
   if (mod && mod->visible) 
               {
                   param.name = items[i].name;
     param.test_type = get_item_test_type(items, param.name);
     LOGD(TAG "%s, param.type = %d\n", __FUNCTION__ , param.test_type);

                   if(mod->mutex_type != MUTEX_TYPE_NO_MUTEX){
pthread_mutex_lock(&auto_test_mutex_array[mod->mutex_type]);
LOGD(TAG "%s %s pthread_mutex_lock(mutex type=%d)\n",__FUNCTION__, param.name, mod->mutex_type);
                   }


     mod->is_auto_test = true;
                   ftm_entry(items[i].id, &param);
     mod->is_auto_test = false;

     if(mod->mutex_type != MUTEX_TYPE_NO_MUTEX){
pthread_mutex_unlock(&auto_test_mutex_array[mod->mutex_type]);
LOGD(TAG "%s %s pthread_mutex_unlock(mutex type=%d)\n",__FUNCTION__, param.name, mod->mutex_type);
     }


                   if (stopmode && mod->test_result != FTM_TEST_PASS)
                       continue;
               }
 }
               break;
       }
       i++;
   }
LOGD(TAG "%s run the manul test items end\n", __FUNCTION__);


for(i=0; items[i].name!=NULL; i++){
mod = ftm_get_module(items[i].id);
if(mod && mod->is_support_run_in_background){
LOGD(TAG"%s pthread_join items[%d] id=%02d name=%s\n",__FUNCTION__, i, items[i].id, items[i].name);
pthread_join(mod->auto_test_thd, NULL);
}
}

   //add for saving testreport.log
   create_report(cust_items, rpt_items, ITEM_MAX_IDS , buf, bufsz);
   //add for saving testreport.log
    }


    return 0;
}
#else


static int auto_test_mode(char *buf, int bufsz)
{
    int i = 0;
    item_t *items, *cust_items;
    struct ftm_module *mod;
    struct ftm_param param;


    //add for saving test report
    item_t rpt_items[ITEM_MAX_IDS + 1];
    int stopmode = 0;
    char *stopprop = ftm_get_prop("FTM.FailStop");


    if(buf == NULL)
    {
        return -1;
    }


    if (stopprop && !strncasecmp(stopprop, "yes", strlen("yes")))
        stopmode = 1;


    LOGD(TAG "auto_test_mode: %d", stopmode);


    items = get_item_list();
    //add for saving test report
    cust_items = get_item_list();
    memset(rpt_items, 0, sizeof(item_t) * (ITEM_MAX_IDS + 1));


    while (items[i].name) 
    {
        LOGD(TAG "%s:%d:%d", items[i].name, items[i].id, items[i].mode);
        switch (items[i].id) 
        {
            case ITEM_IDLE: /* skip items */
                break;
            case ITEM_REPORT:
                item_test_report(items, buf, bufsz);
                break;
            default:
                mod = ftm_get_module(items[i].id);
                if (mod && mod->visible) 
                {
                    param.name = items[i].name;
                    param.test_type = get_item_test_type(items, param.name); 
                    LOGD(TAG "%s, param.type = %d\n", __FUNCTION__ , param.test_type);
                    ftm_entry(items[i].id, &param);
                    if (stopmode && mod->test_result != FTM_TEST_PASS)
                        continue;
                }
                break;
        }
        i++;
    }


    //add for saving testreport.log
    create_report(cust_items, rpt_items, ITEM_MAX_IDS , buf, bufsz);
    //add for saving testreport.log


    return 0;
}
#endif


//xieqinghua add autodiag begin
extern "C" bool check_autodiag_mode(void);
extern  "C" void RunAutoDiag(void);
extern   "C" int AutotestExecCmd(const char* cmd,char* result_buf, int result_len);
#ifdef USE_FACTORY_EX
extern   "C" bool auto_diag_item_impl(int id, const char* name,int type)
{
struct ftm_module *mod = ftm_get_module(id);
struct ftm_param param;
item_t * item = get_item(id);
if(item == NULL){
LOGE(TAG"%s can not find id %d", __FUNCTION__, id);
return false;
}

param.name = name;
param.test_type = type;

if(item->mutex_type != MUTEX_TYPE_NO_MUTEX){
LOGD(TAG"%s lock %p\n", __FUNCTION__, &auto_test_mutex_array[mod->mutex_type]);
pthread_mutex_lock(&auto_test_mutex_array[mod->mutex_type]);
}

mod->is_auto_test = true;
ftm_entry(id, &param);
mod->is_auto_test = false;

if(item->mutex_type != MUTEX_TYPE_NO_MUTEX){
LOGD(TAG"%s unlock %p\n", __FUNCTION__, &auto_test_mutex_array[mod->mutex_type]);
pthread_mutex_unlock(&auto_test_mutex_array[mod->mutex_type]);
}


LOGD(TAG "%s, %s test result:%d\n", __FUNCTION__ , param.name, mod->test_result);

return (mod->test_result == FTM_TEST_PASS);
}


extern "C" bool auto_diag_item(int id, const char* name,int type)
{
item_t * item = get_item(id);
struct ftm_param param;
if(!name){
param.name = item->name;
} else {
      param.name = name;
}
param.test_type = type;

char temp[1024] = {0};
sprintf(temp, "%s %s id=%d test_type=%d", __FUNCTION__, param.name, id, param.test_type);
CFunctionTracer tracer(temp);

struct ftm_module *mod = ftm_get_module(id);
if(mod && mod->is_need_diag){
LOGD(TAG"%s waitting for %s id=%d test_type=%d test thread\n", __FUNCTION__, param.name, id, param.test_type);
pthread_join(mod->auto_test_thd, NULL);
LOGD(TAG"%s waitting for %s id=%d test_type=%d test thread finished test_result:%d\n", __FUNCTION__,  param.name, id, param.test_type, mod->test_result);
if(mod->test_result == FTM_TEST_PASS){
return true;
}else{
return auto_diag_item_impl(id, param.name, param.test_type);
}
}else{
return auto_diag_item_impl(id, param.name, param.test_type);
}

return false;
}
#else
extern   "C" bool auto_diag_item(int id, const char* name,int type)
{
struct ftm_module *mod;
struct ftm_param param;


mod=ftm_get_module(id);
param.name = name;
param.test_type = type;//FTM_AUTO_ITEM;
LOGD(TAG "%s, param.type = %d\n", __FUNCTION__ , param.test_type);
ftm_entry(id, &param);
return (mod->test_result == FTM_TEST_PASS);
}
#endif
static int auto_diag_mode(char *buf, int bufsz)
{
    int chosen_item = 0;
    int exit = 0;
    struct itemview itv;  /* item test menu */
    struct ftm_param param;
    text_t  title;
    item_t *items;


    //add for saving test report
item_t rpt_items[ITEM_MAX_IDS + 1];


    if(buf == NULL)
    {
        return -1;
    }


    LOGD(TAG "item_test_mode");


    items = get_item_list();


    ui_init_itemview(&itv);
    init_text(&title, uistr_item_test, COLOR_YELLOW);


    itv.set_title(&itv, &title);
    itv.set_items(&itv, items, 0);


    return 0;
}
//xieqinghua add autodiag end




//extern void StartUsbThread(void);


/*static bool is_efuse_enabled()
{
char  val[128] = {0};
property_get("ro.boot.efuse",val,NULL);
if (!strcmp(val, "yes"))
return true;
else
return false;
}*/


int main(int argc, char **argv)
{
    /* CHECKME! should add this fuctnion to avoid UI not displayed */
    show_slash_screen(uistr_factory_mode);
    bootMode = getBootMode();
    maxrows = item_rows-UNAVAIL_ROW;
#ifdef USE_FACTORY_EX
   int chosen_item = 0;
   memset(&return_data.diag_version, 0, sizeof(return_data.diag_version));
#endif


......


        if (!check_autodiag_mode()) {
            bool cft_ok = false;
            bool efuse_enabled = true;
            //property_get("ro.check.efuse", val, "true");
            //if (strcmp(val, "false")) {
            #ifdef MTK_EFUSE_WRITER_SUPPORT
                efuse_enabled = is_efuse_enabled();
 LOGD(TAG"%s is_efuse_enabled:%s\n", __FUNCTION__, efuse_enabled ? "true" : "false");
    #endif
            //}
            
/*
*Billy: change the routine to this place,
*      to avoid sometimes would cft_check fail,
*      But I do not know why.
*/
cft_ok = is_cft_pass();
//END


......


//xieqinghua added for autodiag begin
if(check_autodiag_mode())
{
ui_print("check_autodiag_mode...\n");
auto_diag_mode(buf, BUFSZ);
#ifdef USE_FACTORY_EX
LOGD(TAG"%s is_cft_pass begin \n", __FUNCTION__);
bool cft_ok = is_cft_pass();
LOGD(TAG"%s is_cft_pass end cft:%s\n", __FUNCTION__, cft_ok ? "PASS":"FAIL");


        //add by liudongming begih
        property_get("ro.device.support.gsensorcali", val, "unknown");
if (0 == strcmp(val, "true")) {
   ui_print("G-Sensor cali...\n");
LOGD(TAG"G-Sensor cali...");
   auto_diag_item(ITEM_GS_CALI, "G-Sensor cali", FTM_AUTODIAG_ITEM);
        }
   //add by liudongming end

ui_print("run autotest threads...\n");
auto_test_mode(buf, BUFSZ);
#endif
ui_print("RunAutoDiag...\n");
RunAutoDiag();
#ifdef USE_FACTORY_EX
chosen_item = -1;
#else
return EXIT_SUCCESS;
#endif
}
//xieqinghua added for autodiag end
        if(first_entry)
        {
            restore_test_report_eng();
            first_entry = 0;
        }
   while (!exit)
   {
#ifdef USE_FACTORY_EX
            if(-1 == chosen_item){
   chosen_item = ITEM_REPORT;
            }else{
               chosen_item = fiv.run(&fiv, NULL);
            }
#else
            int chosen_item = fiv.run(&fiv, NULL);
#endif
       switch (chosen_item)
       {
                  case ITEM_FULL_TEST:
                my_item_test_report(get_item_list(), uistr_full_test, buf, BUFSZ);
                      break;
               case ITEM_AUTO_TEST:
                      auto_test_mode(buf, BUFSZ);
#ifdef USE_FACTORY_EX
                my_item_test_report(get_auto_item_list(), uistr_test_report, buf, BUFSZ);
#else
                item_test_report(get_item_list(), buf, BUFSZ);
#endif
                break;
            case ITEM_ITEM_TEST:
                my_item_test_report(get_item_list(), uistr_item_test, buf, BUFSZ);
                break;
            case ITEM_DEBUG_TEST:
                debug_test_mode(buf, BUFSZ);
                break;
#ifdef USE_FACTORY_EX
            case ITEM_AUTOTEST_REPORT: 
                my_item_test_report(get_auto_item_list(), uistr_test_report, buf, BUFSZ);
                break;
#endif
            case ITEM_REPORT:
                item_test_report(get_item_list(), buf, BUFSZ);
                break;
            case ITEM_VERSION:
                display_version(0, NULL, false);
                break;
            case ITEM_REBOOT:
                exit = 1;
                fiv.exit(&fiv);
                break;
            default:
                param.name = get_item_name(items, chosen_item);
                ftm_entry(chosen_item, &param);
                break;
            }
        }//end while


    if (buf)
        {   
       free(buf);
            buf = NULL;
        }


    ui_title(uistr_reboot);
    ui_printf("\n\nRebooting ...\n");
sleep(1);
    //sync();
    property_set("sys.powerctl","reboot");


    return EXIT_SUCCESS;


    }
    else
    {
        LOGD(TAG "Unsupported Factory mode\n");
    }

    return EXIT_SUCCESS;
}


//add by liudongming for bug 22914
int get_ADBSerialNo_from_nvram(char *serial_no)
{


int read_nvram_ready_retry = 0;
F_ID fid;
int rec_size = 0;
int rec_num = 0;
int barcode_lid = AP_CFG_REEB_PRODUCT_INFO_LID;
PRODUCT_INFO *barcode_struct;
bool isread = true;
char nvram_init_val[128] = {0};
LOGD(TAG "Entry get_barcode_from_nvram");
    if(serial_no == NULL)
    {
        return 0;
    }
while(read_nvram_ready_retry < MAX_RETRY_COUNT)
{
read_nvram_ready_retry++;
property_get("service.nvram_init", nvram_init_val, NULL);
if(strcmp(nvram_init_val, "Ready") == 0 || strcmp(nvram_init_val, "Pre_Ready") == 0)
{
break;
}
else
{
usleep(500*1000);
}
}


if(read_nvram_ready_retry >= MAX_RETRY_COUNT)
{
LOGD(TAG "Get nvram restore ready failed!");
return 0;
}


barcode_struct= (PRODUCT_INFO *)malloc(sizeof(PRODUCT_INFO));
if(barcode_struct == NULL)
{
return 0;
}


fid = NVM_GetFileDesc(barcode_lid, &rec_size, &rec_num, isread);


if(fid.iFileDesc < 0)
{
LOGD(TAG "fid.iFileDesc < 0");
                free(barcode_struct);
return 0;
}


if(rec_size != read(fid.iFileDesc, barcode_struct, rec_size))
{
free(barcode_struct);
return 0;
}
if(strlen((const char *)&barcode_struct->target_info.ADBSeriaNo) > 0)
{
strncpy(serial_no, (const char *)&barcode_struct->target_info.ADBSeriaNo, 20);
}
    else
{
strcpy(serial_no, "unknown");
}


free(barcode_struct);
if(!NVM_CloseFileDesc(fid))
{
return 0;
}
LOGD(TAG "The size of barcode_struct:%d\n", sizeof(barcode_struct));
LOGD(TAG "Serial No is %s\n", serial_no);
return 1;
}


8.11
vendor/mediatek/proprietary/factory/src/item.cpp


item_t ftm_auto_test_items[] = 
{
#ifdef FEATURE_FTM_LED
    item(ITEM_LED,     uistr_led),
#endif


#ifndef FINGERPRINT_NOT_SUPPORT_IN_AUTO_TEST
#ifdef FEATURE_FTM_FINGERPRINT
    //item(ITEM_FINGERPRINT_TEST, uistr_fingerprint_test),
    item(ITEM_FINGER, uistr_fingerprint_test),
#endif
#endif


//add by liudongming
#ifdef FEATURE_FTM_THERMAL
    item(ITEM_THERMAL, uistr_info_thermal),
#endif


//add by liudongming
#if defined(CUSTOM_KERNEL_ALSPS) || defined(CUSTOM_KERNEL_ALS) || defined(CUSTOM_KERNEL_PS)
    item(ITEM_ALSPS, uistr_als_ps),
    item(ITEM_ALS, uistr_als),
    item(ITEM_PS, uistr_ps),
#ifdef MTK_SUBALS
    item(ITEM_SUBALS, uistr_subals),
#endif
#endif


#ifdef USE_FACTORY_EX
item_b_m(ITEM_CFT,   uistr_cft, MUTEX_TYPE_MODEN),
#ifdef FEATURE_FTM_HEADSET
    item_b_m(ITEM_HEADSET, uistr_info_headset, MUTEX_TYPE_AUDIO),
#endif
#ifdef FEATURE_FTM_OTG
    item_b(ITEM_OTG, "OTG"),
#endif
#ifdef FEATURE_FTM_KEYS
    item_need_diag(ITEM_KEYS,    uistr_keys),
#endif
#ifdef FEATURE_FTM_TOUCH
    item_need_diag(ITEM_TOUCH,   uistr_touch),
    item_need_diag(ITEM_TOUCH_AUTO, uistr_touch_auto),
#endif
#ifdef FEATURE_FTM_VIBRATOR
    item_need_diag(ITEM_VIBRATOR, uistr_vibrator),
#endif
#ifdef FEATURE_FTM_STROBE
    item_m_need_diag(ITEM_STROBE, uistr_strobe, MUTEX_TYPE_CAMERA),
#endif
//Billy
#ifdef MTK_SUB_STROBE_SUPPORT
    item_m(ITEM_SUBSTROBE, uistr_substrobe, MUTEX_TYPE_CAMERA),
#endif
#ifdef CUSTOM_KERNEL_ACCELEROMETER
    item(ITEM_GSENSOR, uistr_g_sensor),
#endif
};




item_t ftm_test_items[] = 
{
#ifdef FEATURE_FTM_FINGERPRINT
    //item(ITEM_FINGERPRINT_TEST, uistr_fingerprint_test),
    item_b(ITEM_FINGER, uistr_fingerprint_test),
#endif


//add by liudongming
#ifdef FEATURE_FTM_THERMAL
    item_b_need_diag(ITEM_THERMAL, uistr_info_thermal),
#endif
}


8.12
vendor/mediatek/proprietary/factory/src/miniui/events.c


static int ev_tail_num = 0; // add by liudongming


// add by liudongming begin
void del_event_ex() {
     pthread_mutex_lock(&event_mutex);
     ev_tail_num++; 
     if (ev_tail_num == 2048) ev_tail_num = 0;
     pthread_mutex_unlock(&event_mutex);
}


void clear_event_ex()
{
while(ev_tail_num != ev_head_num)
del_event_ex();
}
struct input_event get_event_ex()
{
struct input_event ev = ev_queue[ev_tail_num];
 
if (ev_head_num == ev_tail_num){
//LOGD(TAG"%s ev_head_num=%d ev_tail_num=%d\n", __FUNCTION__, ev_head_num, ev_tail_num);
ev.type = 0xff;
return ev;
}else{
del_event_ex();
return ev;
}
}
// add by liudongming end


8.13
vendor/mediatek/proprietary/factory/src/miniui/font.mk


ifeq ($(LCM_WIDTH),1080)
LOCAL_CFLAGS += -DFEATURE_FTM_FONT_32x32  //改变字体大小
endif


ifeq ($(LCM_WIDTH),480)
LOCAL_CFLAGS += -DFEATURE_FTM_FONT_28x28
endif


8.14
vendor/mediatek/proprietary/factory/src/miniui/miniui.c
改动庞大,对照原文件修改。


8.15添加所有test目录下测试文件
vendor/mediatek/proprietary/factory/src/test/


8.16
vendor/mediatek/proprietary/factory/src/util/iniconfig.cpp


int read_config(char *filename)
{
        if (strcasestr(name, "menuitem") && num < limit) 
        {
            if (val && ((id = get_item_id(&ftm_test_items[0], val)) >= 0)) 
            {
if(id == ITEM_FINGER){
property_get("ro.device.support.fingerprint", pval, "true");
if (strcmp(pval, "true"))
continue;
}
#ifdef USE_FACTORY_EX
                items[num].mode =(*test_type == 'A') ? FTM_AUTO_ITEM : FTM_MANUAL_ITEM;
 if( (auto_id = get_item_id(&ftm_auto_test_items[0],val)) >= 0)
                {
                    auto_items[auto_num].id = auto_id;
                    auto_items[auto_num].name = strdup(val);
                    auto_items[auto_num].mode = (*test_type == 'A') ? FTM_AUTO_ITEM : FTM_MANUAL_ITEM;
                    auto_num++;
                }
#else
                if(*test_type == 'A')
                {
                    auto_items[auto_num].id = id;
                    auto_items[auto_num].name = strdup(val);
                    auto_items[auto_num].mode = FTM_AUTO_ITEM;
                    items[num].mode = FTM_AUTO_ITEM;
                    auto_num++;
                }
                else
                {
                    items[num].mode = FTM_MANUAL_ITEM;
                }
#endif
}


8.17
vendor/mediatek/proprietary/factory/src/util/utils.cpp


//add by liudongming
int readFile(const char * path, char * outString, int outStringLen)
{
    int fd;
    
    if (path == NULL)
        return -1;


    fd = open(path, O_RDONLY);
    if (fd >= 0) {
        int amt = read(fd, outString, outStringLen);          
        close(fd);
        return amt == -1 ? -errno : amt;
    }
    LOGE(TAG "readFile failed to open %s\n", path);
    return -1;  
}


//add by liudongming for 360 platform
bool is_efuse_enabled()
{
char buf[256] = {0};
char efuse[256] = {0};
bool benabled = false;
property_get("ro.build.tpw.ver", buf, "") ;
LOGD(TAG"%s ro.build.tpw.ver:%s\n", __FUNCTION__, buf);
property_get("ro.boot.efuse", efuse, "");
LOGD(TAG"%s ro.boot.efuse:%s\n", __FUNCTION__, efuse);
if(strstr(buf, "QH") != NULL && strstr(buf,"SHICHAN") == NULL && (strcmp(efuse, "yes") == 0)) {
benabled = true;
} else if(strstr(buf,"SHICHAN") != NULL) {
benabled = true;
} else {
      benabled = false;
}


LOGD(TAG"%s return:%d\n", __FUNCTION__, benabled);
return benabled;
}


int64_t get_curr_time_ms(void) {
    struct timespec tm;


    clock_gettime(CLOCK_REALTIME, &tm);
    return tm.tv_sec * 1000LL + (tm.tv_nsec / 1000000LL);
}


8.18
vendor/mediatek/proprietary/factory / src/util/version.cpp


//add by liudongming for bug 22914
extern int get_ADBSerialNo_from_nvram(char *serial_no);


#ifdef USE_FACTORY_EX
extern"C" void AUTOTEST_Trace(const char* strFormat, ...);
extern"C" int AutotestExecCmd(const char* cmd,char* result_buf, int result_len);
extern "C" const char* Diag_GetSwVersion(void)
{
    char retbuf[1024];
    char buf[256]={0};
    char* ptr,i;
    memset(return_data.diag_version.s_version,0,sizeof(return_data.diag_version.s_version));
#ifdef ATA_PRODUCT_NAME
   LOGD(TAG"ATA_PRODUCT_NAME:%s\n", ATA_PRODUCT_NAME);
   strcpy(return_data.diag_version.s_version, ATA_PRODUCT_NAME);
#else
   AutotestExecCmd("getprop ro.build.tpw.ver",buf,256);  //modify zenghaiqi
    for(i=0;i<strlen(buf);i++)
    {
    if(buf[i]>='a' && buf[i]<='z')buf[i]=buf[i]-'a'+'A';
    else if(buf[i]<=' ')
    {
    buf[i]=0;
    break;
    }
else if(buf[i]=='_')
    {
    buf[i]=0;
    break;
    }
    }
    strcat(return_data.diag_version.s_version,buf);
//    strcat(s_version,"N8571_M8_ENG");
    printf("Autotest_GetSwVersion:%s\n",return_data.diag_version.s_version);
#endif
    strcat(return_data.diag_version.s_version," S/N:");
#if 0
    AutotestExecCmd("getprop ro.serialno",buf,256);
    if(5>strlen(buf))strcat(s_version,"123456789");
    else strcat(s_version,buf);
#else
bool cftpass = is_cft_pass();//ftm_check_cft();
for(i=0;i<60;i++)
{
if(barcode[i]>='a' && barcode[i]<='z')buf[i]=barcode[i];
else if(barcode[i]>='A' && barcode[i]<='Z')buf[i]=barcode[i];
else if(barcode[i]>='0' && barcode[i]<='9')buf[i]=barcode[i];
else  break;
}
buf[i]=0;
strcat(return_data.diag_version.s_version,buf);
#endif
    strcat(return_data.diag_version.s_version," brcm");


//#ifdef NEW_TEST
strcat(return_data.diag_version.s_version," new_autotest");
//#endif


/*
 * @Brief: DDR&CPU fool-proofing
 */
{
char* tmp_info=NULL;
char  cpu_type[16]={0};
char  ddr_type[16]={0};
long emmc_num = 0;
//char tmp_cmdl[1024] = {0};
char tmp_str[32] = {0};
int  tmp_res = 0;
#if 0 //mod by liudongming
AutotestExecCmd("cat /proc/cmdline",retbuf,sizeof(retbuf));
if(strstr(retbuf,"cpu=")){
tmp_info = strstr(retbuf,"cpu=");
tmp_info += 4;
sscanf(tmp_info,"%s",cpu_type);
tmp_res++;
}
#else
        AutotestExecCmd("cat /proc/cmdline",retbuf,sizeof(retbuf));
if(strstr(retbuf,"androidboot.hardware=")){
tmp_info = strstr(retbuf,"androidboot.hardware=");
tmp_info += strlen("androidboot.hardware=");
sscanf(tmp_info,"%s",cpu_type);
for(int i=0; i<sizeof(cpu_type); i++){
if(isalpha(cpu_type[i])){
cpu_type[i] = toupper(cpu_type[i]);
}
}
tmp_res++;
LOGD(TAG"get CPU info OK tmp_res++ %s\n", cpu_type);
}
LOGD(TAG"cat /proc/cmdline=%s\n", retbuf);
#endif


memset(buf, 0, sizeof(buf));
AutotestExecCmd("cat /proc/tpwmemshow",buf,sizeof(buf));
   //AUTOTEST_Trace("sp--> %s", buf);
if(strstr(buf,"MemTotal:")){
tmp_info = strstr(buf,"MemTotal:");
tmp_info += 9;
sscanf(tmp_info," %s",ddr_type);
tmp_res++;
LOGD(TAG"get MemTotal info OK tmp_res++ %s\n", tmp_info);
} else {
   LOGE(TAG"get MemTotal info FAIL Please check SELinux %s\n", buf);
}
memset(buf, 0, sizeof(buf));
AutotestExecCmd("cat /sys/class/block/mmcblk0/size",buf,sizeof(buf));
   AUTOTEST_Trace("sp -> %s", buf);
if(0 != strlen(buf)){
//sscanf(tmp_buf,"%l",emmc_num);
emmc_num = atol(buf);
emmc_num = emmc_num /1000 *512 /1000;
emmc_num = (emmc_num + (emmc_num/40) + 500)/1000;
tmp_res++;
LOGD(TAG"get emmc_num OK tmp_res++ %d\n", emmc_num);
}


if(3 == tmp_res){
snprintf(tmp_str, 31," cpu_info:%s %s %d", cpu_type, ddr_type, (int)emmc_num);
//AUTOTEST_Trace("sp--> %s", tmp_str);
ui_print("cpu_info:%s %s %d\n",cpu_type, ddr_type, (int)emmc_num);
LOGD("cpu_info:%s %s %d\n",cpu_type, ddr_type, (int)emmc_num);
strcat(return_data.diag_version.s_version, tmp_str);
}else{
AUTOTEST_Trace("sp--> cpu_info is not found. ");
}
}
    LOGD(TAG"Autotest_GetSwVersion:%s\n",return_data.diag_version.s_version);
    AutotestExecCmd("setprop persist.sys.topwise.root 1",0,0);
    return return_data.diag_version.s_version;
}
#endif
//还有很多细节,需对照原文件进行修改


9.耳机自动测试发出中断
kernel-4.4 / drivers/misc/mediatek/accdet/mt6739/accdet.c


#ifdef CONFIG_ACCDET_EINT
 extern char *saved_command_line;
#endif


static inline void headset_plug_out(void)
{
send_accdet_status_event(s_cable_type, 0);
s_accdet_status = PLUG_OUT;
s_cable_type = NO_DEVICE;
/* update the cable_type */
if (g_cur_key != 0) {
send_key_event(g_cur_key, 0);
ACCDET_INFO("[accdet]plug_out send key = %d release\n", g_cur_key);
g_cur_key = 0;
}
ACCDET_DEBUG("[accdet]set state in cable_type = NO_DEVICE\n");
}


static inline void check_cable_type(void)
{


/**
* Billy
* @Brief:
*     when interrupt-type is CONFIG_ACCDET_EINT,
*     need to add this routine to solve the problem of can't pluged out,
*     in auto-test mode.
*/
#ifdef CONFIG_ACCDET_EINT
    if(strstr(saved_command_line,"autodiag_enable=1")){
headset_plug_out();
ACCDET_DEBUG("[Accdet] In auto-test-mode  need to  send plug out event to switch-state\n");
  }
#endif
// add-END
}


10.添加生产零件宏配置
customize/res/M9719/M9719_ENG/proj.cfg
CONFIG_TOP_FACTORY=yes
CONFIG_TOP_FACTORY=y


11工厂模式触摸测试有概率无响应触摸问题修改
vendor/mediatek/proprietary/factory/src/miniui/events.c
int ev_init(void)
{
            //mod by liudongming sometime mistakenly identified mtk-tpd-kpd as mtk-tpd 
            //if (!strncmp(name, "mtk-tpd", 7)) {
            if (!strcmp(name, "mtk-tpd")) {
}


12工厂模式添加充电相关驱动结点读取权限
device/mediatek/sepolicy/basic/non_plat/factory.te
allow factory sysfs_power_supply:dir search;
allow factory sysfs_power_supply:file rw_file_perms;

猜你喜欢

转载自blog.csdn.net/qq_38500662/article/details/80881329