OSDN Git Service

Reduce the overhead of the PRC compatibility package feature during system bootup
[android-x86/frameworks-base.git] / core / jni / abipicker / ABIPicker.cpp
1 #define LOG_TAG "ABIPicker"
2
3 #include "ABIPicker.h"
4 #include "ELFLite.h"
5
6 #include <androidfw/ZipFileRO.h>
7 #include <androidfw/ZipUtils.h>
8
9 namespace android {
10 #define ARR_SIZE(x)     (sizeof(x)/sizeof(x[0]))
11
12 #define SO_NAME_MAX (4096)
13 #define IMPOSSIBLE_LIB_NAME    "/mixed/"
14 #define IMPOSSIBLE_LIB_LEN  (sizeof(IMPOSSIBLE_LIB_NAME)-1)
15 #define ARMABI      "armeabi"
16 #define ARMV7ABI    "armeabi-v7a"
17 #define ARM64ABI    "arm64-v8a"
18 #define X86ABI      "x86"
19 #define X8664ABI    "x86_64"
20 #define ARMABI_NAME_PREFIX        "arm"
21
22 #define APK_LIB "lib/"
23 #define APK_LIB_LEN (sizeof(APK_LIB) - 1)
24 //#define PICK_LOGGER //flag to debug
25 #ifdef PICK_LOGGER
26 #define P_LOG(...) ALOGI(__VA_ARGS__)
27 #else
28 #define P_LOG(...)
29 #endif
30
31 #define OEMWHITE  "/system/vendor/etc/misc/.OEMWhiteList"
32 #define OEMBLACK  "/system/vendor/etc/misc/.OEMBlackList"
33 #define THIRDPARTY "/system/vendor/etc/misc/.ThirdPartySO"
34
35 // load once, hold until poweroff
36 static Vector <char*> thirdPartySO;
37 static Vector <char*> cfgWhite;
38 static Vector <char*> cfgBlack;
39 static bool thirdload = false;
40 static bool whiteload = false;
41 static bool blackload = false;
42
43 static const char* iaRelated[] = {"intel", "intl", "atom", "x86", "x64"};
44
45 //////////////////////////////////////////////////////////////////////
46 void getConfig(const char* cfgFile , Vector<char*>& cfgVec) {
47     FILE* fp = fopen(cfgFile, "r");
48     assert(fp != NULL);
49     int read = -1;
50     char *line = NULL;
51     size_t len = 0;
52
53     while ((read = getline(&line, &len, fp)) != -1) {
54         int i = 0 , j = 0;
55         char *cfgline = (char*)malloc(len);
56         if (!cfgline) {
57            P_LOG("malloc error");
58            break;
59         }
60         for (i = 0; i < read; i++) {
61            if (!isspace(line[i])) {
62               cfgline[j++] = line[i];
63            }
64         }
65         cfgline[j] = '\0';
66         cfgVec.push_back(cfgline);
67         P_LOG("orignal %s , vec: %s ", line, cfgline);
68     }
69     if (line != NULL)
70        free(line);
71     fclose(fp);
72 }
73
74 //////////////////////////////////////////////////////////////////////
75 void freeAllString(Vector<char*>& list) {
76     Vector<char*>::iterator it = list.begin();
77     while (it != list.end()) {
78         if (*it != NULL) {
79            P_LOG("freeAllSring  %p , %s", it, *it);
80            free(*it);
81            *it = NULL;
82         }
83         it++;
84     }
85 }
86
87 //////////////////////////////////////////////////////////////////////
88 bool isInOEMWhiteList(const char* pkgName) {
89     bool result = false;
90     if (!pkgName) return result;
91
92     if (!whiteload) {
93        getConfig(OEMWHITE, cfgWhite);
94        whiteload = true;
95     }
96
97     Vector<char*>::iterator it = cfgWhite.begin();
98     for (; it != cfgWhite.end(); it++) {
99        P_LOG("whitelist : %s", *it);
100        if (0 == strcmp(pkgName, *it)) {
101           ALOGI("found %s in whitelist", pkgName);
102           result = true;
103           break;
104        }
105     }
106     return result;
107 }
108
109 //////////////////////////////////////////////////////////////////////
110 bool isInOEMBlackList(const char* pkgName) {
111     bool result = false;
112     if (!pkgName) return result;
113
114     if (!blackload) {
115        getConfig(OEMBLACK,  cfgBlack);
116        blackload = true;
117     }
118
119     Vector<char*>::iterator it = cfgBlack.begin();
120     for (; it != cfgBlack.end(); it++) {
121        if (0 == strcmp(pkgName, *it)) {
122           ALOGI("found %s in blacklist", pkgName);
123           result = true;
124           break;
125        }
126     }
127     return result;
128 }
129
130
131 //////////////////////////////////////////////////////////////////////
132 bool isReliableLib(Vector<char*>& libList) {
133     unsigned sz = libList.size();
134     int len = ARR_SIZE(iaRelated);
135     for (unsigned i = 0; i < sz; i++) {
136         for (int j=0; j < len; j++) {
137             char* p = NULL;
138             if (NULL != (p = strcasestr(libList[i], iaRelated[j]))) {
139                 int lenIA = strlen(iaRelated[j]);
140                 if (!isalpha(*(p+lenIA))) {
141                     if (!isalpha(*(p-1)) || (p == (libList[i] + 3))) {
142                         return true;
143                     }
144                 }
145             }
146         }
147     }
148
149     return false;
150 }
151
152
153 //////////////////////////////////////////////////////////////////////
154 static bool isValidELF(char* buffer) {
155     if (buffer[EI_MAG0] != ELFMAG0 &&
156         buffer[EI_MAG1] != ELFMAG1 &&
157         buffer[EI_MAG2] != ELFMAG2 &&
158         buffer[EI_MAG3] != ELFMAG3) {
159         return false;
160     }
161     return true;
162 }
163
164 // assume that x86 has the only machine-code 3, and x86_64 62
165 static bool isMixedLib(char* libCur, char* buffer) {
166     bool isX86_64 = (0 == strcmp(libCur, X8664ABI)) ? true: false;
167     uint16_t machine_code = *((uint16_t*)(&buffer[ELF_MACHINE_OFFSET]));
168     bool mixed = false;
169     if (isX86_64) {
170         if (machine_code != EM_X86_64)
171             mixed = true;
172     } else {
173         if (machine_code != EM_386)
174             mixed = true;
175     }
176     return mixed;
177 }
178
179 // compare the given string with the length, igonre upper and lower
180 // len must be less than the length of two string
181 static bool ignoreCmp(const char* str1, const char* str2, int len){
182     assert (str1 != NULL && str2 != NULL);
183     assert ((len <= strlen(str1)) && (len <= strlen(str2)));
184     for (int i = 0 ; i < len; i++) {
185         if (str1[i] != str2[i]) {
186             if(isalpha(str1[i]) && isalpha(str2[i])
187                     && (abs((str1[i]-str2[i])) == 32)) {
188                 continue;
189             }
190             return false;
191         }
192     }
193     return true;
194 }
195
196 static bool isInThirdPartySOList(char* libName) {
197     assert (libName != NULL);
198     size_t libLen = strlen(libName);
199     size_t sz = thirdPartySO.size();
200     for (size_t i = 0; i < sz; i++) {
201         // thirdPartySO[i] won't be NULL
202         size_t n = strlen(thirdPartySO[i]);
203         // three char for ".so"
204         int j = libLen - 4;
205         // now only '-' '-' and '.'found
206         while((j >= 0) && (isdigit(libName[j]) || (libName[j] == '-')
207               || (libName[j] == '_') || (libName[j] == '.'))) {
208             j--;
209         }
210         // three char for "lib" and include the name with no letters
211         if ((j == 2) || ((size_t)j == (n+2))) {
212             if (ignoreCmp(libName+3, thirdPartySO[i], n)) {
213                 P_LOG("ABIpicker libName %s,In Third", libName);
214                 return true;
215             }
216         }
217
218     }
219     return false;
220 }
221
222 static void insertionSort(Vector<char*>& list) {
223     P_LOG("in insertionSort, list size = %d\n", list.size());
224
225     for (size_t i = 1; i < list.size(); i++) {
226         char* x = list[i];
227
228         int j = i - 1;
229         P_LOG("sort 1. x=%s, i=%d, j=%d\n", x, i, j);
230         while (j >= 0 && (strcmp(list[j], x) > 0)) {
231             list.replaceAt(list[j], j + 1);
232             j--;
233         }
234         list.replaceAt(x, j + 1);
235     }
236 }
237
238
239
240 //////////////////////////////////////////////////////////////////////
241 // Use armRef as a reference, compare all libraries of iaRef with all
242 // libraries of armRef.If the two are match or iaRef is more, iaRef
243 // will be returned with *result and true is return value. Or else,
244 // *result is rawResult and false is return value
245 bool ABIPicker::compare(char* armRef, char* iaRef,
246                         char* rawResult, char** result) {
247     bool ret = true;
248     *result = rawResult;
249
250     do {
251         assert(armRef != NULL);
252         if (0 == strlen(armRef)) {
253             *result = strlen(iaRef) > 0 ? iaRef : rawResult;
254             ret = strlen(iaRef) > 0 ? true : false;
255             break;
256         }
257         assert(iaRef != NULL);
258         if (0 == strlen(iaRef)) {
259             *result = armRef;
260             ret = false;
261             break;
262         }
263
264         Vector<char*>* iaRefList = getLibList(iaRef);
265         Vector<char*>* armRefList = getLibList(armRef);
266
267         // if contains the key words in iaRelated, just return true
268         assert(iaRefList != NULL);
269         assert(armRefList != NULL);
270         if (isReliableLib(*iaRefList)) {
271             *result = iaRef;
272             break;
273         }
274
275         if (compareLibList(*iaRefList, *armRefList)) {
276             *result = iaRef;
277             break;
278         }
279
280         size_t iaIsvLibCount = 0;
281         size_t armIsvLibCount = 0;
282         if (!compare3rdPartyLibList(iaRef, armRef,
283                     &iaIsvLibCount, &armIsvLibCount)) {
284             *result = armRef;
285             ret = false;
286             break;
287         }
288
289         if (iaIsvLibCount > 0) {
290             *result = iaRef;
291             break;
292         }
293
294         *result = armRef;
295         ret = false;
296     } while (0);
297
298     ALOGV("%s Vs. %s, return %s\n",
299             iaRef ? iaRef : "NULL",
300             armRef ? armRef : "NULL", *result);
301     return ret;
302 }
303
304 bool ABIPicker::compareLibList(Vector<char*>& iaRefList,
305         Vector<char*>& armRefList) {
306
307     unsigned iaSize = iaRefList.size();
308     unsigned armSize = armRefList.size();
309     if (iaSize < armSize) {
310         return false;
311     } else if (iaSize == 0 && armSize == 0) {
312         return true;
313     }
314
315     int iaNum = 0;
316     int armNum = 0;
317     Vector<char*>::iterator itIa = iaRefList.begin();
318     Vector<char*>::iterator itArm = armRefList.begin();
319     bool isEqual = false;
320     while (itIa != iaRefList.end() && itArm != armRefList.end()) {
321         if ((iaSize-iaNum) < (armSize-armNum)) {
322             return false;
323         }
324         isEqual = false ;
325         char* armLibName = *itArm;
326         int armLen = strlen (armLibName);
327         armNum++;
328
329         while (itIa != iaRefList.end() && !isEqual) {
330             char* iaLibName = *itIa;
331             iaNum++;
332             int iaLen = strlen (iaLibName);
333             if (iaLen == armLen) {
334                 if (ignoreCmp(iaLibName, armLibName, iaLen)) {
335                     isEqual = true;
336                 }
337             }
338             itIa++;
339         }
340         itArm++;
341     }
342     // till the end, and the last result is equal
343     if (itArm == armRefList.end() && isEqual){
344         return true;
345     } else {
346         return false;
347     }
348 }
349
350 bool ABIPicker::compare3rdPartyLibList(
351                 char* iaRef, char* armRef,
352                 size_t* iaIsvLibCount, size_t* armIsvLibCount) {
353     Vector<char*>* iaRefList = getLibList(iaRef);
354     Vector<char*>* armRefList = getLibList(armRef);
355     assert(iaRefList != NULL);
356     assert(armRefList != NULL);
357
358     Vector<char*>* armRef3rdPartyLibList = new Vector<char*>();
359     Vector<char*>::iterator itArm = armRefList->begin();
360
361     // Load thirdPartyso
362     if (!thirdload) {
363         getConfig(THIRDPARTY, thirdPartySO);
364         thirdload = true;
365     }
366     while (itArm != armRefList->end()) {
367         char* armLibName = *itArm;
368         if (isInThirdPartySOList(armLibName)) {
369             armRef3rdPartyLibList->push_back(armLibName);
370         } else {
371             (*armIsvLibCount)++;
372         }
373
374         itArm++;
375     }
376
377     Vector<char*>::iterator itIa = iaRefList->begin();
378     Vector<char*>* iaRef3rdPartyLibList = new Vector<char*>();
379     while (itIa != iaRefList->end()) {
380         char* iaLibName = *itIa;
381         if (isInThirdPartySOList(iaLibName)) {
382             iaRef3rdPartyLibList->push_back(iaLibName);
383         } else {
384             (*iaIsvLibCount)++;
385         }
386
387         itIa++;
388     }
389     bool result = compareLibList(*iaRef3rdPartyLibList, *armRef3rdPartyLibList);
390
391     //release the memory
392     free(armRef3rdPartyLibList);
393     free(iaRef3rdPartyLibList);
394     return result;
395 }
396
397 char* ABIPicker::getAbiName(int abi) {
398     if (abi <  0 || (unsigned)abi >= mLibList->size()) {
399         return NULL;
400     }
401
402     char* ret = NULL;
403     int index = 0;
404     Vector<struct libInfo*>::iterator it = mLibList->begin();
405     while (it != mLibList->end()) {
406         if (index == abi) {
407             ret = (*it)->abiName;
408             break;
409         }
410
411         index++;
412         it++;
413     }
414
415     return ret;
416 }
417
418 int ABIPicker::getAbiIndex(const char* abiName) {
419     int ret = -1;
420
421     int index = 0;
422     Vector<struct libInfo*>::iterator it = mLibList->begin();
423     while (it != mLibList->end()) {
424         if (0 == strcmp(abiName, (*it)->abiName)) {
425             ret = index;
426             break;
427         }
428
429         index++;
430         it++;
431     }
432
433     return ret;
434 }
435
436 Vector<char*>* ABIPicker::getLibList(const char* abiName) {
437     Vector<char*>* ret = NULL;
438     Vector<struct libInfo*>::iterator it = mLibList->begin();
439     while (it != mLibList->end()) {
440         if (0 == strcmp(abiName, (*it)->abiName)) {
441             ret = (*it)->libNameList;
442             break;
443         }
444         it++;
445     }
446     P_LOG("getLibList of %s return %p\n", abiName, ret);
447     return ret;
448 }
449
450
451 size_t ABIPicker::getSpecficABILibCount(const char* abiName) {
452     Vector<char*>* specificAbiLibList = getLibList(abiName);
453     return specificAbiLibList && specificAbiLibList->size();
454 }
455
456 bool ABIPicker::foundMixedELF(const char* abiName) {
457     Vector<char*>* libNameList = getLibList(abiName);
458     if (!libNameList) {
459         return false;
460     }
461     if (libNameList->size() == 0) {
462         return false;
463     }
464
465     if (0 != strcasecmp(*(libNameList->begin()), IMPOSSIBLE_LIB_NAME)) {
466         return false;
467     }
468
469     return true;
470 }
471
472
473 //////////////////////////////////////////////////////////////////////
474 ABIPicker::ABIPicker(const char* pkgName, Vector<ScopedUtfChars*> abiList) {
475     mLibList = new Vector<struct libInfo*>();
476     mpkgName = (char*)malloc(strlen(pkgName)+1);
477     if (!mpkgName) {
478         P_LOG("ABIPicker Construct Allocated space fails");
479     } else {
480         snprintf(mpkgName, strlen(pkgName)+1, "%s", pkgName);
481     }
482     Vector<ScopedUtfChars*>::iterator it = abiList.begin();
483     while (it != abiList.end()) {
484         if (!(*it)) {
485             break;
486         }
487
488         struct libInfo* tmp = (struct libInfo*)calloc(1,
489                 sizeof(struct libInfo));
490         if (!tmp) {
491            P_LOG("ABIPicker Construct Allocated space fail %s", (*it)->c_str());
492            break;
493         }
494
495         snprintf(tmp->abiName, (*it)->size() + 1, "%s", (*it)->c_str());
496         tmp->libNameList = new Vector<char*>();
497         P_LOG("ABIPicker Construct %s , libNameList: %p",
498              tmp->abiName, tmp->libNameList);
499         mLibList->push_back(tmp);
500         it++;
501     }
502 }
503
504 ABIPicker::~ABIPicker(void) {
505     if(NULL != mpkgName) {
506         free(mpkgName);
507         mpkgName = NULL;
508     }
509     Vector<struct libInfo*>::iterator it = mLibList->begin();
510     while (it != mLibList->end()) {
511         freeAllString(*((*it)->libNameList));
512         (*it)->libNameList->clear();
513         delete (*it)->libNameList;
514         (*it)->libNameList = NULL;
515
516         free(*it);
517         *it = NULL;
518         it++;
519     }
520     mLibList->clear();
521     delete(mLibList);
522 }
523
524 bool ABIPicker::buildNativeLibList(void* apkHandle) {
525     bool ret = false;
526
527     if (!apkHandle) {
528         ALOGE("apkHandle is NULL\n");
529         return ret;
530     }
531
532     ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
533     void* cookie = NULL;
534     if (!zipFile->startIteration(&cookie)) {
535         ALOGE("apk file is broken\n");
536         return ret;
537     }
538
539     ZipEntryRO next = NULL;
540     char* unCompBuff = NULL;
541     char fileName[SO_NAME_MAX + 1];
542     while ((next = zipFile->nextEntry(cookie))) {
543         if (zipFile->getEntryFileName(next, fileName, SO_NAME_MAX)) {
544             ALOGE("apk file is broken, can not get entry name\n");
545             ret = false;
546             break;
547         }
548         fileName[SO_NAME_MAX] = '\0';
549
550         // Make sure we're in the lib directory of the ZIP.
551         // find out entries with such names: "lib/xxxxxxx" or "lib/"
552         if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
553             continue;
554         }
555
556         // find out any invalid ELF file
557         uint32_t unCompLen = 0;
558         if (!zipFile->getEntryInfo(next, NULL, &unCompLen, NULL, NULL, NULL,
559                                     NULL)) {
560             ALOGE("apk file is broken, can not get entry info\n");
561             ret = false;
562             break;
563         }
564
565         if (unCompLen == 0) {
566             ALOGV("skip a empty file(%s)\n", fileName);
567             continue;
568         }
569
570         if (!unCompBuff) {
571             free(unCompBuff);
572             unCompBuff = NULL;
573         }
574
575         unCompBuff = (char*)malloc(unCompLen);
576         if (!unCompBuff) {
577             ALOGE("malloc failed size %d\n", unCompLen);
578             ret = false;
579             break;
580         }
581         memset(unCompBuff, 0, unCompLen);
582         // THE MOST TIME COST OPERATION
583         if (!zipFile->uncompressEntry(next, unCompBuff, unCompLen)) {
584             ALOGE("%s: uncompress failed\n", fileName);
585             ret = false;
586             break;
587         }
588
589         if (!isValidELF(unCompBuff)) {
590             ALOGI("skip a fake .ELF file(%s)\n", fileName);
591             continue;
592         }
593
594         // It is a real .so file, prepare to record
595         // find abi name and focus on what we care: arm(s) and x86(s)
596         // at least lastSlash points to the end of "lib/"
597         const char* lastSlash = strrchr(fileName, '/');
598         const char* cpuAbiOffset = fileName + APK_LIB_LEN;
599         // just in case if fileName is in an abnormal format, like lib/libname,
600         // lib//libname
601         if (lastSlash <= cpuAbiOffset) {
602             ALOGI("skip a invalid lib file(%s)\n", fileName);
603             continue;
604         }
605
606         const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;
607         char curAbiName[ABI_NAME_MAX_LENGTH];
608         if (cpuAbiRegionSize >= ABI_NAME_MAX_LENGTH) {
609             continue;
610         }
611         snprintf(curAbiName, cpuAbiRegionSize + 1, "%s", cpuAbiOffset);
612
613         Vector<char*>* libListOfCurAbi = getLibList(curAbiName);
614         if (!libListOfCurAbi) {
615             P_LOG("getLibList of %s return NULL\n", curAbiName);
616             continue;
617         }
618
619         // mixed arm elf in lib/x86 or lib/x86_64
620         // but we don't consider a compareable scenario in lib/arm*
621         if (0 == strcmp(curAbiName, X86ABI) ||
622                 0 == strcmp(curAbiName, X8664ABI)) {
623             if (!libListOfCurAbi->empty()) {
624                 char* firstElement = libListOfCurAbi->itemAt(0);
625                 if (0 == strcmp(firstElement, IMPOSSIBLE_LIB_NAME)) {
626                     // won't add any new into the list if found mixed
627                     // lib before
628                     P_LOG("won't count count if found mixed lib before");
629                     continue;
630                 }
631             }
632
633             if (isMixedLib(curAbiName, unCompBuff)) {
634                 P_LOG("found mixed lib(%s) in lib/%s/", curAbiName, fileName);
635                 freeAllString(*libListOfCurAbi);
636                 libListOfCurAbi->clear();
637                 char* mixedLib = (char*)malloc(IMPOSSIBLE_LIB_LEN+1);
638                 if (!mixedLib) {
639                     ALOGE("malloc failed size %d", IMPOSSIBLE_LIB_LEN + 1);
640                     ret = false;
641                     break;
642                 }
643                 snprintf(mixedLib, (IMPOSSIBLE_LIB_LEN+1), "%s", IMPOSSIBLE_LIB_NAME);
644                 mixedLib[IMPOSSIBLE_LIB_LEN] ='\0';
645                 libListOfCurAbi->push_back(mixedLib);
646                 continue;
647             }
648         }
649
650         // now, lastSlash should point to lib name
651         lastSlash++;
652         const size_t libNameSize = strlen(lastSlash);
653         char* curLibName = (char*)malloc(libNameSize+1);
654         if (!curLibName) {
655             ALOGE("malloc failed size %d\n", libNameSize+1);
656             ret = false;
657             break;
658         }
659         snprintf(curLibName,libNameSize+1, "%s", lastSlash);
660         curLibName[libNameSize] = '\0';
661
662         libListOfCurAbi->push_back(curLibName);
663
664         ret = true;
665     }
666
667     if (unCompBuff) {
668         free(unCompBuff);
669         unCompBuff = NULL;
670     }
671
672     zipFile->endIteration(cookie);
673
674     for (unsigned i = 0; i < mLibList->size(); i++) {
675         struct libInfo* tmp = mLibList->itemAt(i);
676         insertionSort(*(tmp->libNameList));
677     }
678     return ret;
679 }
680
681 int ABIPicker::pickupRightABI(int sysPrefer) {
682     char* sysPreferAbiName = getAbiName(sysPrefer);
683     if (!sysPreferAbiName) {
684         return sysPrefer;
685     }
686
687     bool is64BitPrefer = (0 == strcmp(sysPreferAbiName, X8664ABI));
688     bool x8664HasMixedELF = foundMixedELF(X8664ABI);
689     bool x86HasMixedELF = foundMixedELF(X86ABI);
690
691     size_t armv7LibCount = getSpecficABILibCount(ARMV7ABI);
692     size_t armv5LibCount = getSpecficABILibCount(ARMABI);
693     size_t armv8LibCount = getSpecficABILibCount(ARM64ABI);
694     size_t x86LibCount = x86HasMixedELF ? 0 : getSpecficABILibCount(X86ABI);
695     size_t x8664LibCount = x8664HasMixedELF ? 0 : getSpecficABILibCount(X8664ABI);
696     P_LOG("armv7LibCount:%d armv5LibCount:%d armv8LibCount:%d x86LibCount:%d x8664LibCount:%d", armv7LibCount, armv5LibCount, armv8LibCount, x86LibCount, x8664LibCount);
697
698     // in OEMBlackList, need to be supported by bt
699     // but in case of armlib doesn't exist, we choose x86 or x86_64
700     if (isInOEMBlackList(mpkgName)) {
701         if (armv7LibCount > 0) {
702             return getAbiIndex(ARMV7ABI);
703         } else if (armv5LibCount > 0) {
704             return getAbiIndex(ARMABI);
705         } else if (armv8LibCount > 0) {
706             return getAbiIndex(ARM64ABI);
707         }
708     }
709
710     char arm64Ref[ABI_NAME_MAX_LENGTH];
711     if (armv8LibCount > 0) {
712         snprintf(arm64Ref, sizeof(ARM64ABI), "%s", ARM64ABI);
713     } else {
714         arm64Ref[0] = '\0';
715     }
716
717     char arm32Ref[ABI_NAME_MAX_LENGTH];
718     if (armv7LibCount > 0) {
719         snprintf(arm32Ref, sizeof(ARMV7ABI), "%s", ARMV7ABI);
720     } else if (armv5LibCount > 0) {
721         snprintf(arm32Ref, sizeof(ARMABI), "%s", ARMABI);
722     } else {
723         arm32Ref[0] = '\0';
724     }
725
726     char ia32Ref[ABI_NAME_MAX_LENGTH];
727     if (x86LibCount > 0) {
728         snprintf(ia32Ref, sizeof(X86ABI), "%s", X86ABI);
729     } else {
730         ia32Ref[0] = '\0';
731     }
732
733     char ia64Ref[ABI_NAME_MAX_LENGTH];
734     if (x8664LibCount > 0) {
735         snprintf(ia64Ref, ABI_NAME_MAX_LENGTH, "%s", X8664ABI);
736     } else {
737         ia64Ref[0] = '\0';
738     }
739
740     char* retAbiName = sysPreferAbiName;
741     do {
742         // # The basic rule is:
743         // - on 32 bit system, compare ia32Ref native libraries with
744         // arm32Ref native libraries. If pass, return ia32Ref .
745         // If fail, return arm32Ref.
746         // - on 64 bit system, IA has two chances. if ia64Ref native
747         // libraries can't pass the comparation with arm64Ref, we should
748         // run the comparation again with ia32Ref
749         if (is64BitPrefer) {
750             if (!compare(arm64Ref, ia64Ref, sysPreferAbiName, &retAbiName)) {
751                 char rawRes[ABI_NAME_MAX_LENGTH];
752                 snprintf(rawRes, ABI_NAME_MAX_LENGTH, "%s", retAbiName);
753                 compare(arm32Ref, ia32Ref, rawRes, &retAbiName);
754             }
755         } else {
756             compare(arm32Ref, ia32Ref, sysPreferAbiName, &retAbiName);
757         }
758     } while (0);
759     int ret = getAbiIndex(retAbiName);
760     ALOGI("selected abi %s(%d) for %s", retAbiName, ret, mpkgName);
761     return ret;
762 }
763
764 }  // namespace android