开机之后,初始化时,在InitializeAll()中call mmi_phb_init_protocol(),设置如下几个PS消息CBack函数:
SetProtocolEventHandler(mmi_phb_ind_startup_finish, PRT_PHB_STARTUP_FINISH_IND);
SetProtocolEventHandler(mmi_phb_ind_startup_begin, PRT_PHB_STARTUP_BEGIN_IND);
SetProtocolEventHandler(mmi_phb_ind_startup_read, PRT_PHB_STARTUP_READ_IND);
 
 
1.L4在到NVRAM读取data之前,发送消息到MMI:PRT_PHB_STARTUP_BEGIN_IND,进入:
mmi_phb_ind_startup_begin()
       初始化一些变量,准备重新reload entries.
 
2.L4每读取一个AND entry,都有发送消息到MMI:PRT_PHB_STARTUP_READ_IND,进入:
       L4返回消息的结构:       typedef struct
       {
              LOCAL_PARA_HDR
              l4c_phb_entries_struct phb_entries[1];
              kal_uint8       access_id;
       } mmi_phb_startup_read_ind_struct;
       typedef struct
       {
              kal_uint16 num_of_entry;
              l4c_phb_bcd_entry_struct  phb_entry[2000/NVRAM_PHB_SIZE];
       } l4c_phb_entries_struct;
       typedef struct {
           kal_uint8 storage;
           kal_uint8 type;
           kal_uint16 index;
           kal_uint16 record_index;
           l4_addr_bcd_struct tel;
           l4_name_struct alpha_id;
       } l4c_phb_bcd_entry_struct;
 
       MMI中,保存电话entries的全局变量PhoneBook结构如下:
       MMI_PHB_ENTRY_BCD_STRUCT PhoneBook[MAX_PB_ENTRIES];
       typedef struct
       {
          //U8         storage;
         //U8         type;
          //U16                index;
          //U16                record_index;
          MMI_PHB_NUMBER_BCD_STRUCT tel;
          MMI_PHB_NAME_STRUCT alpha_id;
          U8 field;   /* Indicate if an entry has the field */
          U8 dummy;   /* Make sure each phb structure is two-bytes aligned. */
       } MMI_PHB_ENTRY_BCD_STRUCT;
 
       typedef struct
       {
          U8 type;                                    /* 129-default; 145-international, begin with '+' */
          U8 length;
          U8 number[(MAX_PB_NUMBER_LENGTH + 1) / 2];  /* half space to store BCD format. */
       } MMI_PHB_NUMBER_BCD_STRUCT;
 
       typedef struct
       {
          U8 name_length; /* Name Length */
          U8 name_dcs;    /* Name Data Coding Scheme */
          U8 name[(MAX_PB_NAME_LENGTH + 1) *ENCODING_LENGTH];
       } MMI_PHB_NAME_STRUCT;
 
 
       mmi_phb_ind_startup_read()
               mmi_phb_ind_startup_read_next_req(LocalPtr->access_id);
                     MMI发消息到PRT_PHB_STARTUP_READ_NEXT_REQL4,请求read next。
               //假定是读取NVRAM中的entry
               for (i = 0; i < LocalPtr->phb_entries[0].num_of_entry; i++)
        {
            g_phb_cntx.phone_used++;
            store_index = LocalPtr->phb_entries[0].phb_entry[i].record_index - 1;       /* Storage Location in array. */
            MMI_ASSERT((g_phb_cntx.phone_used <= MAX_PB_PHONE_ENTRIES) && (store_index < MAX_PB_PHONE_ENTRIES));
            mmi_phb_startup_read_entry(LocalPtr->phb_entries[0].phb_entry[i], store_index);
        }
 
       mmi_phb_startup_read_entry()    把消息保存到全局变量PhoneBook中。这个变量的结构:
              信息保存在PhoneBook[store_index]中。可见:PhoneBook[]中的存储顺序就是L4中的存储顺序。
              PhoneBook[store_index].tel.number中保存的是ASCII码。
 
              //根据号码的第一个文章来设置是SIM entry还是NVRAM entry.
              PhoneBook[store_index].field = 0;
         if (PhoneBook[store_index].tel.number[0] != 0xff)
          {
             PhoneBook[store_index].field |= MMI_PHB_ENTRY_FIELD_NUMBER;
          }
                            g_phb_name_index[PhoneBookEntryCount] = store_index;        姓名列表,保存的是PhoneBook中entry的位置
          PhoneBookEntryCount++;
 
3.当L4从NVRAM中读取完之后,发送消息PRT_PHB_STARTUP_FINISH_IND到MMI,表示L4已经读完了。MMI接收到这个消息之后,开始load all entries from L4。
返回的消息结构:
       typedef struct
       {
              LOCAL_PARA_HDR
              kal_uint16     sim_max_num;
              kal_uint16     phb_max_num;
              kal_uint8       phb_len;
              kal_uint8       fdn_len;
              kal_uint8       bdn_len;
              kal_uint8       owner_len;
       } mmi_phb_startup_finish_ind_struct;
 
       mi_phb_ind_startup_finish()
              //初始化g_phb_cntx中的结构
               g_phb_cntx.sim_name_len = localPtr->phb_len;
        g_phb_cntx.fdn_name_len = localPtr->fdn_len;
        g_phb_cntx.bdn_name_len = localPtr->bdn_len;
        g_phb_cntx.owner_name_len = localPtr->owner_len;
        g_phb_cntx.sim_total = localPtr->sim_max_num;
        g_phb_cntx.phone_total = localPtr->phb_max_num;
 
               if (!g_phb_cntx.nvram_data_init)
        {
            mmi_phb_init_get_data_from_nvram(); //从NVRAM中读取电话簿的一些信息。比如:群组,栏位设置,存储选择等等。
                                   g_phb_cntx.view_field
                                   g_phb_cntx.prefer_storage
                                   g_phb_cntx.name_list_filter
                                   g_phb_cntx.caller_group
 
            g_phb_cntx.nvram_data_init = TRUE;
        }
 
              mmi_phb_sort_build_name_index();         //sort name list g_phb_name_index。这个函数完成后,PoneBook中所有entries,如果按照g_phb_name_index[]中                                                                       //的值作为顺序来排列的话,将是按照姓名中字母从小到大的顺序。
                     mmi_phb_sort_name_fast_quicksort(0, (U16) (PhoneBookEntryCount - 1), mmi_phb_sort_compare_name_index_by_pinyin_cache);
                     mmi_phb_sort_name_insertionsort(left, right, compare);
 
              //当FDN启动之后,AND就不能从SIM卡中读取出来了。就是为了防止非法为授权拨号
              //当获取到FDN list之后,一定要获取speed dial number。
               if (gSecuritySetupContext.FdlStatus)
        {
            mmi_phb_fdn_get_list_to_ram();    //把FND list拷贝到AND的存储区。
                                   if (g_phb_cntx.sim_used == 0)
                               {
                                  g_phb_fdn_count = 0;
                                  mmi_phb_fdn_get_list_to_ram_req();       
                                                 发送消息PRT_PHB_GET_ENTRY_BY_INDEX_REQ到L4,去读取FDN。
                                                 返回消息PRT_PHB_GET_ENTRY_BY_INDEX_RSP,进入CBack函数:
                                                 mmi_phb_fdn_get_list_to_ram_rsp()
                                                        store_index = g_phb_fdn_count + MAX_PB_PHONE_ENTRIES;   
                                                        把读取的信息保存到PhoneBook[store_index]中。可见:PhoneBook是先保存NVRAM号码,然后是SIM号码。
                                      
                                          /* Retrieve Speed Dial List after retrieve FDN list, because they all use same message. */
                                      PhbGetSpeedDialInfo();
                                   }
                               else
                               {
                                  PhbGetSpeedDialInfo();  /* Retrieve Speed Dial List after retrieve FDN list, because they all use same message. */
                                                 PhbReadSpeedDialNVRAM();        //从NVRAM中读取速拨信息
                                                g_phb_cntx.phb_ready = TRUE;
                                         mmi_phb_init_build_lookup_table(); // builds the lookup table for cross-referencing during MO/MT calls.
                               }
        }
        else
        {
            if (gInsertSimAppFlag == 1)
            {
                g_phb_cntx.phb_ready = TRUE;
                mmi_phb_init_build_lookup_table();
                                          mmi_phb_util_read_compare_length()//获取g_phb_compare_length,即需要比较的号码最后几位
                                          把PhoneBook中以g_phb_name_index[]中的内容为索引的entry的号码,转换成ASCII码,然后转换成32为int型数据,并保存                                                                                          在全局变量LookUpTable[]中。注意:一并保存的还有store_index也就是该entry在PhoneBook中存储位置。
                                          StartTimer(PHB_READ_OPT_FILED_TIMER, 500, mmi_phb_init_populate_lookup_table);
            }
            else
            {
                PhbGetSpeedDialInfo();
            }
        }
 
500ms之后,定时器溢出,进入:
mmi_phb_init_populate_lookup_table()
       //This function populates the lookup table with home/fax/mobile/office numbers after converting the last 7(or 9) characters of the phone number into digits.
       以g_phb_name_index[]中的内容为索引,到NVRAM中读取option fields数据ReadMultiRecord()。然后把读取的数据保存在LookUpTable[]中。包括:       传真号码,家庭号码,公司号码。每读取10次,就暂停250ms,然后继续读取。
       全部读完之后,进入:mmi_phb_lookup_table_sort( )    All entries populated, begin to sort it。因为在装载电话号码的时候,LookUpTable[]中的内容是按照字母顺装载的,但是在装载NVRAM中的传真,家庭,公司号码时,是按照存储顺序装载的。而这里的排序,是根据电话号码的大小来排序的。
即:按照电话号码的大小,从小到大排列。 当来电的时候,采取对半查找效率就很高了。
 
小结:到这里,就完成了电话簿的初始化。即:
(1)从NVRAM,SIM卡中读取了数据,并保存在L4中了;
(2)MMI中的全局变量PhoneBook[]与L4中的电话簿已经同步了;
(3)g_phb_name_index[]中按照字母的大小顺序,存储了每一个entry在PhoneBook[]中的存储位置;
(4)所有的号码,包括SIM卡,NVRAM,移动电话,家庭,公司,传真号码,都按照大小顺序,存储在LookUpTable[]中了,并且存储在PhoneBook中的存储位置索引。