平台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);
&nbp; 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, ¶m);
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)