1 // 2 // Copyright 2005 The Android Open Source Project 3 // 4 // Our collection of devices. 5 // 6 7 // For compilers that support precompilation, include "wx/wx.h". 8 #include "wx/wxprec.h" 9 10 // Otherwise, include all standard headers 11 #ifndef WX_PRECOMP 12 # include "wx/wx.h" 13 #endif 14 //#include "wx/image.h" // needed for Windows build 15 16 17 #include "PhoneCollection.h" 18 #include "PhoneData.h" 19 #include "MyApp.h" 20 21 #include "utils.h" 22 23 #include <stdlib.h> 24 #include <unistd.h> 25 #include <stdio.h> 26 #include <string.h> 27 #include <sys/types.h> 28 #include <dirent.h> 29 #include <assert.h> 30 31 using namespace android; 32 33 /*static*/ PhoneCollection* PhoneCollection::mpInstance = NULL; 34 35 /*static*/ const char* PhoneCollection::kLayoutFile = "layout.xml"; 36 37 38 /* 39 * (Re-)scan the specified directory for phones. We register a hit if we can 40 * see a file called "<directory>/layout.xml". 41 */ 42 void PhoneCollection::ScanForPhones(const char* directory) 43 { 44 /* 45 * Scan through the directory and find everything that looks like it 46 * might hold phone data. 47 */ 48 StringArray strArr; 49 50 #ifdef BEFORE_ASSET 51 DIR* dirp; 52 struct dirent* entp; 53 54 dirp = opendir(directory); 55 if (dirp == NULL) { 56 char buf[512]; 57 fprintf(stderr, "ERROR: unable to scan directory '%s' for phone data\n", 58 directory); 59 fprintf(stderr, "Current dir is %s\n", getcwd(buf, sizeof(buf))); 60 return; 61 } 62 63 while (1) { 64 wxString dirName; 65 wxString fileName; 66 67 entp = readdir(dirp); 68 if (entp == NULL) 69 break; // done with scan 70 dirName = directory; 71 dirName += '/'; 72 dirName += entp->d_name; 73 fileName = dirName; 74 fileName += '/'; 75 fileName += kLayoutFile; 76 77 if (access(fileName, R_OK) == 0) { 78 strArr.push_back(dirName); 79 //printf("--- examining '%s'\n", (const char*) fileName); 80 } 81 } 82 closedir(dirp); 83 #else 84 android::AssetManager* pAssetMgr = ((MyApp*)wxTheApp)->GetAssetManager(); 85 android::AssetDir* pDir; 86 int i, count; 87 88 pDir = pAssetMgr->openDir(""); 89 assert(pDir != NULL); 90 count = pDir->getFileCount(); 91 92 for (i = 0; i < count; i++) { 93 android::String8 layoutPath; 94 95 if (pDir->getFileType(i) != kFileTypeDirectory) 96 continue; 97 98 layoutPath = pDir->getFileName(i); 99 layoutPath.appendPath(kLayoutFile); 100 101 if (pAssetMgr->getFileType(layoutPath.string()) == kFileTypeRegular) { 102 strArr.push_back(pDir->getFileName(i).string()); 103 printf("--- examining '%s'\n", layoutPath.string()); 104 } 105 } 106 107 delete pDir; 108 #endif 109 110 if (strArr.size() == 0) { 111 fprintf(stderr, "ERROR: no phone data found in '%s'\n", directory); 112 return; 113 } 114 115 /* 116 * Found some candidates. If they parse successfully, add them to 117 * our list. 118 * 119 * We sort them first, because it's nice when everybody's user 120 * interface looks the same. Note we're sorting the directory name, 121 * so it's possible to define a sort order in the filesystem that 122 * doesn't require messing up the phone's title string. 123 */ 124 mPhoneList.clear(); 125 strArr.sort(StringArray::cmpAscendingAlpha); 126 127 for (int i = 0; i < strArr.size(); i++) { 128 PhoneData tmpPhone; 129 130 if (!tmpPhone.Create(strArr.getEntry(i))) { 131 fprintf(stderr, "Sim: Abandoning phone '%s'\n", strArr.getEntry(i)); 132 //strArr.erase(i); 133 //i--; 134 } else { 135 if (GetPhoneData(tmpPhone.GetName()) != NULL) { 136 fprintf(stderr, "Sim: ERROR: duplicate name '%s' in '%s'\n", 137 tmpPhone.GetName(), strArr.getEntry(i)); 138 } else { 139 mPhoneList.push_back(tmpPhone); 140 } 141 } 142 } 143 } 144 145 146 /* 147 * Return the Nth member of the phone data array. (Replace w/Vector.) 148 */ 149 PhoneData* PhoneCollection::GetPhoneData(int idx) 150 { 151 typedef List<PhoneData>::iterator Iter; 152 153 for (Iter ii = mPhoneList.begin(); ii != mPhoneList.end(); ++ii) { 154 if (idx == 0) 155 return &(*ii); 156 --idx; 157 } 158 return NULL; 159 } 160 161 /* 162 * Return the entry whose phone data name matches "name". 163 */ 164 PhoneData* PhoneCollection::GetPhoneData(const char* name) 165 { 166 typedef List<PhoneData>::iterator Iter; 167 168 for (Iter ii = mPhoneList.begin(); ii != mPhoneList.end(); ++ii) { 169 if (strcasecmp((*ii).GetName(), name) == 0) 170 return &(*ii); 171 } 172 return NULL; 173 } 174 175