C代码
int AppEmvAppSelect(int Slot, unsigned long TransNo)
{
unsigned char aucPDOL[256] = {0}, ucTransType = 0;
int InmputAmt=0;
unsigned int nPDOLLen = 0, nLen=0;
int nRet =0 ;
EMV_CANDLIST atCandAppList[MAX_APP_ITEMS];
EMV_CANDLIST atCandAppList_old[MAX_APP_ITEMS];
int nAppNum = 0, i=0;
int nSelTryCnt=0;
int nAppSelNo=0;
unsigned char buf[20] = {0}, buff[100] = {0};
DBG1(cDebugPortStr("%s %s %d -------- AppEmvAppSelect" , __FILE__ , __FUNCTION__, __LINE__););
gl_nEnableConfirmAmt = 0;
DEV_SetIccSlot((unsigned char)Slot);
nRet = DEV_IccReset();
if (nRet)
{
return ICC_RESET_ERR;
}
AppLoadALLtoKernel();
memset(atCandAppList, 0, sizeof(atCandAppList));
nAppNum = 0;
DBG1(cDebugPortStr("%s %s %d -------- EMV_AppSelect" , __FILE__ , __FUNCTION__, __LINE__););
if (gl_ucSkipCreCandiListFlg == 0) //Skip creating candidate list for AppEmvAppSelect
{
nRet = EMV_AppSelect(atCandAppList,&nAppNum);
}
else
{
nRet = EMV_GetCandList(atCandAppList,&nAppNum);// use the Candidate list set by application
}
if(nRet)
{
return nRet;
}
DBG1(cDebugPortStr("%s %s %d -------- nRet = %d" , __FILE__ , __FUNCTION__, __LINE__, nRet););
nSelTryCnt=0;
while(1)
{
if ((nAppNum == 1) && (!nSelTryCnt) && !(atCandAppList[0].ucPriority & 0x80)&& (gl_ucAppConfimMethod == 0))
{
nAppSelNo=0;
nRet=EMV_FinalSelect(0,atCandAppList, &nAppNum);
DBG1(cDebugPortStr("%s %d -------- nRet = %d" , __FUNCTION__, __LINE__, nRet););
}
else while(2)
{
memset(atCandAppList_old, 0, sizeof(atCandAppList_old));
for (i=0;i<nAppNum;i++)
{
ConvCandList_emv(atCandAppList[i], &atCandAppList_old[i]);
}
//Automatically select the candidate application if the candlist contains only one application
if((nAppNum == 1) && !(atCandAppList[0].ucPriority & 0x80)&& (gl_ucAppConfimMethod == 0))
{
nAppSelNo=0;
nRet= EMV_FinalSelect(0,atCandAppList, &nAppNum);
DBG1(cDebugPortStr("%s %d -------- nRet = %d" , __FUNCTION__, __LINE__, nRet););
break;
}
nRet = AppCandAppSel(nSelTryCnt, atCandAppList_old, nAppNum);
DBG1(cDebugPortStr("%s %d -------- nRet = %d" , __FUNCTION__, __LINE__, nRet););
nSelTryCnt++;
if(nRet<0)
{
return nRet;
}
nAppSelNo=nRet;
nRet= EMV_FinalSelect((unsigned char)nAppSelNo,atCandAppList, &nAppNum);
DBG1(cDebugPortStr("%s %d -------- nRet = %d" , __FUNCTION__, __LINE__, nRet););
if (nRet != EMV_SELECT_NEXT)
{
break;
}
}
DBG1(cDebugPortStr("%s %s %d -------- EMV_FinalSelect = %d" , __FILE__ , __FUNCTION__, __LINE__, nRet););
if (nRet)
{
return nRet;
}
DBG1(cDebugPortStr("%s %s %d -------- EMV_SetAidParam = %d" , __FILE__ , __FUNCTION__, __LINE__, nRet););
nRet = AppEmvSetParam();
DBG1(cDebugPortStr("%s %d -------- nRet = %d" , __FUNCTION__, __LINE__, nRet););
if (nRet)
{
return nRet;
}
DBG1(cDebugPortStr("%s %s %d -------- AppEmvSetParam = %d" , __FILE__ , __FUNCTION__, __LINE__, nRet););
while (3)
{
InmputAmt = 1;
memset(aucPDOL, 0, sizeof(aucPDOL));
AppGetTLVData(0x9F38, aucPDOL, &nPDOLLen);
if (SearchTLV_emv(1, 0x81, aucPDOL, aucPDOL+nPDOLLen, NULL) != NULL)
{
break;
}
if (SearchTLV_emv(1, 0x9F02, aucPDOL, aucPDOL+nPDOLLen, NULL) != NULL)
{
break;
}
AppGetTLVData(0x9C, &ucTransType, &nLen);
DBG1(cDebugPortStr("%s %d -------- ucTransType = %d" , __FUNCTION__, __LINE__, ucTransType););
if (ucTransType == 0x09
&& (SearchTLV_emv(1, 0x9F03, aucPDOL, aucPDOL+nPDOLLen, NULL) == NULL
|| SearchTLV_emv(1, 0x9F04, aucPDOL, aucPDOL+nPDOLLen, NULL) == NULL))
{
break;
}
InmputAmt = 0;
break;
}//while (3)
DBG1(cDebugPortStr("%s %d -------- InmputAmt = %d" , __FUNCTION__, __LINE__, InmputAmt););
gl_nInputAmtFlag=0;
if (InmputAmt)
{
nRet = AppInputAmt();
if(nRet)
{
return nRet;
}
}
sprintf((char *)buf, "%08lu", TransNo);
memset(buff, 0, sizeof(buff));
APP_DEV_vTwoOne(buf, 8, buff);
nRet = AppSetTLVData(0x9F41, buff, 4);
if (!AppEMVUnknowTLVData(0x9F37, buff, 4))//get UN
{
AppSetTLVData(0x9F37, buff, 4);
}
if (!AppEMVUnknowTLVData(0x9A, buff, 3))//Get transaction date
{
AppSetTLVData(0x9A, buff, 3);
}
if (!AppEMVUnknowTLVData(0x9F21, buff, 3))//Get transaction time
{
AppSetTLVData(0x9F21, buff, 3);
}
if (!AppEMVUnknowTLVData(0x9F1E, buff, 8))//Get terminal SN
{
AppSetTLVData(0x9F1E, buff, 8);
}
CheckDOLRelatedData_emv(aucPDOL, nPDOLLen);
DBG1(cDebugPortStr("%s %d -------- InmputAmt = %d" , __FUNCTION__, __LINE__, InmputAmt););
nRet = EMV_InitApp(atCandAppList, &nAppNum);
DBG1(cDebugPortStr("%s %d -------- nRet = %d" , __FUNCTION__, __LINE__, nRet););
if(( nRet == EMV_APP_BLOCK )||(nRet == ICC_RSP_6985 ))
{
if(nAppNum == 0)
return nRet;
continue;
}
break;
}
return nRet;
}
整个逻辑来看,三个while()循环,细看其实就是一个continue.
1.上下文类,用于存储数据结构。
2.一个抽象状态类,
3.实现抽象类的类
4.调用这个状态模式
public class ContextAppSelete {
public ContextAppSelete(){
MAX_APP_ITEMS = 22;
nSelTryCnt = 0;
nAppNum = 0;
nAppSelNo = 0;
candListArray = new EMV_CANDLIST[MAX_APP_ITEMS];
for (int i = 0; i < candListArray.length; i++) {
candListArray[i] = new EMV_CANDLIST();
}
appNum = new int[1];
}
private AppSelectState state; //维持一个对抽象状态对象的引用
public int MAX_APP_ITEMS;
private int nSelTryCnt;
private int[] appNum;
private EMV_CANDLIST[] candListArray;
private int nAppNum ;
private int nAppSelNo ;
public int getnAppSelNo() {
return nAppSelNo;
}
public void setnAppSelNo(int nAppSelNo) {
this.nAppSelNo = nAppSelNo;
}
public void executeSelectFinalApp() {
state.executeAppSelete();
}
public AppSelectState getState() {
return state;
}
public int getnSelTryCnt() {
return nSelTryCnt;
}
public void setnSelTryCnt(int nSelTryCnt) {
this.nSelTryCnt = nSelTryCnt;
}
public int[] getAppNum() {
return appNum;
}
public void setAppNum(int[] appNum) {
this.appNum = appNum;
}
public int getMAX_APP_ITEMS() {
return MAX_APP_ITEMS;
}
public void setState(AppSelectState state) {
this.state = state;
}
public EMV_CANDLIST[] getCandListArray() {
return candListArray;
}
public void setCandListArray(EMV_CANDLIST[] candListArray) {
this.candListArray = candListArray;
}
public int getnAppNum() {
return nAppNum;
}
public void setnAppNum(int nAppNum) {
this.nAppNum = nAppNum;
}
}
public abstract class AppSelectState {
protected ContextAppSelete contextAppSelete;
public AppSelectState(ContextAppSelete contextAppSelete) {
this.contextAppSelete = contextAppSelete;
}
public abstract void executeAppSelete();
}
public class FinalAppState extends AppSelectState {
static final String TAG = FinalAppState.class.getSimpleName();
private int ret = -1;
private int nSelTryCnt =0;
public FinalAppState(ContextAppSelete contextAppSelete) {
super(contextAppSelete);
}
@Override
public void executeAppSelete() {
if ((contextAppSelete.getnAppNum() == 1) &&
(contextAppSelete.getnSelTryCnt()!=0) &&
((contextAppSelete.getCandListArray()[0].priority & 0x80) == 0x00)) {
ret = EMV_FinalSelect((byte)0,contextAppSelete.getCandListArray(),
contextAppSelete.getAppNum());
if(ret !=0){
contextAppSelete.setState(new QuitFinalAppState(contextAppSelete));
}else {
contextAppSelete.setState(new InitializeAppState(contextAppSelete));
}
} else {
if ((contextAppSelete.getnAppNum() == 1) &&
((contextAppSelete.getCandListArray()[0].priority & 0x80) == 0x00)) {
contextAppSelete.setnAppNum(0);
ret = EMV_FinalSelect((byte)contextAppSelete.getnAppNum(),
contextAppSelete.getCandListArray(),contextAppSelete.getAppNum());
Logs.d(TAG,"ret" + ret);
if( ret !=0 ){
contextAppSelete.setState(new QuitFinalAppState(contextAppSelete));
}else {
contextAppSelete.setState(new InitializeAppState(contextAppSelete));
}
//contextAppSelete.setState(new QuitFinalAppState(contextAppSelete));
}
InitializeAppState(contextAppSelete));
}
}
}
public boolean Appselect() {
ContextAppSelete contextAppSelete = new ContextAppSelete();
contextAppSelete.setState(new SelectAppState(contextAppSelete));
try {
while (true) {
contextAppSelete.executeSelectFinalApp();
if (contextAppSelete.getState() instanceof QuitFinalAppState) {
// Logic for quitting CVM
Logs.d(TAG, "QuitFinalAppState");
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}