| // | 
 | // Copyright 2005 The Android Open Source Project | 
 | // | 
 | // Our collection of devices. | 
 | // | 
 |  | 
 | // For compilers that support precompilation, include "wx/wx.h". | 
 | #include "wx/wxprec.h" | 
 |  | 
 | // Otherwise, include all standard headers | 
 | #ifndef WX_PRECOMP | 
 | # include "wx/wx.h" | 
 | #endif | 
 | //#include "wx/image.h"   // needed for Windows build | 
 |  | 
 |  | 
 | #include "PhoneCollection.h" | 
 | #include "PhoneData.h" | 
 | #include "MyApp.h" | 
 |  | 
 | #include "utils.h" | 
 |  | 
 | #include <stdlib.h> | 
 | #include <unistd.h> | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include <sys/types.h> | 
 | #include <dirent.h> | 
 | #include <assert.h> | 
 |  | 
 | using namespace android; | 
 |  | 
 | /*static*/ PhoneCollection* PhoneCollection::mpInstance = NULL; | 
 |  | 
 | /*static*/ const char* PhoneCollection::kLayoutFile = "layout.xml"; | 
 |  | 
 |  | 
 | /* | 
 |  * (Re-)scan the specified directory for phones.  We register a hit if we can | 
 |  * see a file called "<directory>/layout.xml". | 
 |  */ | 
 | void PhoneCollection::ScanForPhones(const char* directory) | 
 | { | 
 |     /* | 
 |      * Scan through the directory and find everything that looks like it | 
 |      * might hold phone data. | 
 |      */ | 
 |     StringArray strArr; | 
 |  | 
 | #ifdef BEFORE_ASSET | 
 |     DIR* dirp; | 
 |     struct dirent* entp; | 
 |  | 
 |     dirp = opendir(directory); | 
 |     if (dirp == NULL) { | 
 |         char buf[512]; | 
 |         fprintf(stderr, "ERROR: unable to scan directory '%s' for phone data\n", | 
 |             directory); | 
 |         fprintf(stderr, "Current dir is %s\n", getcwd(buf, sizeof(buf))); | 
 |         return; | 
 |     } | 
 |  | 
 |     while (1) { | 
 |         wxString dirName; | 
 |         wxString fileName; | 
 |  | 
 |         entp = readdir(dirp); | 
 |         if (entp == NULL) | 
 |             break;              // done with scan | 
 |         dirName = directory; | 
 |         dirName += '/'; | 
 |         dirName += entp->d_name; | 
 |         fileName = dirName; | 
 |         fileName += '/'; | 
 |         fileName += kLayoutFile; | 
 |  | 
 |         if (access(fileName, R_OK) == 0) { | 
 |             strArr.push_back(dirName); | 
 |             //printf("--- examining '%s'\n", (const char*) fileName); | 
 |         } | 
 |     } | 
 |     closedir(dirp); | 
 | #else | 
 |     android::AssetManager* pAssetMgr = ((MyApp*)wxTheApp)->GetAssetManager(); | 
 |     android::AssetDir* pDir; | 
 |     int i, count; | 
 |  | 
 |     pDir = pAssetMgr->openDir(""); | 
 |     assert(pDir != NULL); | 
 |     count = pDir->getFileCount(); | 
 |  | 
 |     for (i = 0; i < count; i++) { | 
 |         android::String8 layoutPath; | 
 |  | 
 |         if (pDir->getFileType(i) != kFileTypeDirectory) | 
 |             continue; | 
 |  | 
 |         layoutPath = pDir->getFileName(i); | 
 |         layoutPath.appendPath(kLayoutFile); | 
 |  | 
 |         if (pAssetMgr->getFileType(layoutPath.string()) == kFileTypeRegular) { | 
 |             strArr.push_back(pDir->getFileName(i).string()); | 
 |             printf("--- examining '%s'\n", layoutPath.string()); | 
 |         } | 
 |     } | 
 |  | 
 |     delete pDir; | 
 | #endif | 
 |  | 
 |     if (strArr.size() == 0) { | 
 |         fprintf(stderr, "ERROR: no phone data found in '%s'\n", directory); | 
 |         return; | 
 |     } | 
 |  | 
 |     /* | 
 |      * Found some candidates.  If they parse successfully, add them to | 
 |      * our list. | 
 |      * | 
 |      * We sort them first, because it's nice when everybody's user | 
 |      * interface looks the same.  Note we're sorting the directory name, | 
 |      * so it's possible to define a sort order in the filesystem that | 
 |      * doesn't require messing up the phone's title string. | 
 |      */ | 
 |     mPhoneList.clear(); | 
 |     strArr.sort(StringArray::cmpAscendingAlpha); | 
 |  | 
 |     for (int i = 0; i < strArr.size(); i++) { | 
 |         PhoneData tmpPhone; | 
 |  | 
 |         if (!tmpPhone.Create(strArr.getEntry(i))) { | 
 |             fprintf(stderr, "Sim: Abandoning phone '%s'\n", strArr.getEntry(i)); | 
 |             //strArr.erase(i); | 
 |             //i--; | 
 |         } else { | 
 |             if (GetPhoneData(tmpPhone.GetName()) != NULL) { | 
 |                 fprintf(stderr, "Sim: ERROR: duplicate name '%s' in '%s'\n", | 
 |                     tmpPhone.GetName(), strArr.getEntry(i)); | 
 |             } else { | 
 |                 mPhoneList.push_back(tmpPhone); | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | /* | 
 |  * Return the Nth member of the phone data array.  (Replace w/Vector.) | 
 |  */ | 
 | PhoneData* PhoneCollection::GetPhoneData(int idx) | 
 | { | 
 |     typedef List<PhoneData>::iterator Iter; | 
 |  | 
 |     for (Iter ii = mPhoneList.begin(); ii != mPhoneList.end(); ++ii) { | 
 |         if (idx == 0) | 
 |             return &(*ii); | 
 |         --idx; | 
 |     } | 
 |     return NULL; | 
 | } | 
 |  | 
 | /* | 
 |  * Return the entry whose phone data name matches "name". | 
 |  */ | 
 | PhoneData* PhoneCollection::GetPhoneData(const char* name) | 
 | { | 
 |     typedef List<PhoneData>::iterator Iter; | 
 |  | 
 |     for (Iter ii = mPhoneList.begin(); ii != mPhoneList.end(); ++ii) { | 
 |         if (strcasecmp((*ii).GetName(), name) == 0) | 
 |             return &(*ii); | 
 |     } | 
 |     return NULL; | 
 | } | 
 |  |