Home | History | Annotate | Download | only in avd
      1 /* Copyright (C) 2008 The Android Open Source Project
      2 **
      3 ** This software is licensed under the terms of the GNU General Public
      4 ** License version 2, as published by the Free Software Foundation, and
      5 ** may be copied, distributed, and modified under those terms.
      6 **
      7 ** This program is distributed in the hope that it will be useful,
      8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 ** GNU General Public License for more details.
     11 */
     12 #include "android/avd/info.h"
     13 #include "android/avd/util.h"
     14 #include "android/avd/keys.h"
     15 #include "android/config/config.h"
     16 #include "android/utils/file_data.h"
     17 #include "android/utils/path.h"
     18 #include "android/utils/property_file.h"
     19 #include "android/utils/bufprint.h"
     20 #include "android/utils/filelock.h"
     21 #include "android/utils/tempfile.h"
     22 #include "android/utils/debug.h"
     23 #include "android/utils/dirscanner.h"
     24 #include <ctype.h>
     25 #include <stddef.h>
     26 #include <string.h>
     27 #include <stdlib.h>
     28 #include <stdio.h>
     29 #include <errno.h>
     30 
     31 /* global variables - see android/globals.h */
     32 AvdInfoParams   android_avdParams[1];
     33 AvdInfo*        android_avdInfo;
     34 
     35 /* for debugging */
     36 #define  D(...)   VERBOSE_PRINT(init,__VA_ARGS__)
     37 #define  DD(...)  VERBOSE_PRINT(avd_config,__VA_ARGS__)
     38 
     39 /* technical note on how all of this is supposed to work:
     40  *
     41  * Each AVD corresponds to a "content directory" that is used to
     42  * store persistent disk images and configuration files. Most remarkable
     43  * are:
     44  *
     45  * - a "config.ini" file used to hold configuration information for the
     46  *   AVD
     47  *
     48  * - mandatory user data image ("userdata-qemu.img") and cache image
     49  *   ("cache.img")
     50  *
     51  * - optional mutable system image ("system-qemu.img"), kernel image
     52  *   ("kernel-qemu") and read-only ramdisk ("ramdisk.img")
     53  *
     54  * When starting up an AVD, the emulator looks for relevant disk images
     55  * in the content directory. If it doesn't find a given image there, it
     56  * will try to search in the list of system directories listed in the
     57  * 'config.ini' file through one of the following (key,value) pairs:
     58  *
     59  *    images.sysdir.1 = <first search path>
     60  *    images.sysdir.2 = <second search path>
     61  *
     62  * The search paths can be absolute, or relative to the root SDK installation
     63  * path (which is determined from the emulator program's location, or from the
     64  * ANDROID_SDK_ROOT environment variable).
     65  *
     66  * Individual image disk search patch can be over-riden on the command-line
     67  * with one of the usual options.
     68  */
     69 
     70 /* the name of the .ini file that will contain the complete hardware
     71  * properties for the AVD. This will be used to launch the corresponding
     72  * core from the UI.
     73  */
     74 #define  CORE_HARDWARE_INI   "hardware-qemu.ini"
     75 
     76 /* certain disk image files are mounted read/write by the emulator
     77  * to ensure that several emulators referencing the same files
     78  * do not corrupt these files, we need to lock them and respond
     79  * to collision depending on the image type.
     80  *
     81  * the enumeration below is used to record information about
     82  * each image file path.
     83  *
     84  * READONLY means that the file will be mounted read-only
     85  * and this doesn't need to be locked. must be first in list
     86  *
     87  * MUSTLOCK means that the file should be locked before
     88  * being mounted by the emulator
     89  *
     90  * TEMPORARY means that the file has been copied to a
     91  * temporary image, which can be mounted read/write
     92  * but doesn't require locking.
     93  */
     94 typedef enum {
     95     IMAGE_STATE_READONLY,     /* unlocked */
     96     IMAGE_STATE_MUSTLOCK,     /* must be locked */
     97     IMAGE_STATE_LOCKED,       /* locked */
     98     IMAGE_STATE_LOCKED_EMPTY, /* locked and empty */
     99     IMAGE_STATE_TEMPORARY,    /* copied to temp file (no lock needed) */
    100 } AvdImageState;
    101 
    102 struct AvdInfo {
    103     /* for the Android build system case */
    104     char      inAndroidBuild;
    105     char*     androidOut;
    106     char*     androidBuildRoot;
    107     char*     targetArch;
    108     char*     targetAbi;
    109 
    110     /* for the normal virtual device case */
    111     char*     deviceName;
    112     char*     sdkRootPath;
    113     char      sdkRootPathFromEnv;
    114     char*     searchPaths[ MAX_SEARCH_PATHS ];
    115     int       numSearchPaths;
    116     char*     contentPath;
    117     IniFile*  rootIni;      /* root <foo>.ini file, empty if missing */
    118     IniFile*  configIni;    /* virtual device's config.ini, NULL if missing */
    119     IniFile*  skinHardwareIni;  /* skin-specific hardware.ini */
    120 
    121     /* for both */
    122     int       apiLevel;
    123     char*     skinName;     /* skin name */
    124     char*     skinDirPath;  /* skin directory */
    125     char*     coreHardwareIniPath;  /* core hardware.ini path */
    126 
    127     FileData  buildProperties[1];  /* build.prop file */
    128     FileData  bootProperties[1];   /* boot.prop file */
    129 
    130     /* image files */
    131     char*     imagePath [ AVD_IMAGE_MAX ];
    132     char      imageState[ AVD_IMAGE_MAX ];
    133 };
    134 
    135 
    136 void
    137 avdInfo_free( AvdInfo*  i )
    138 {
    139     if (i) {
    140         int  nn;
    141 
    142         for (nn = 0; nn < AVD_IMAGE_MAX; nn++)
    143             AFREE(i->imagePath[nn]);
    144 
    145         AFREE(i->skinName);
    146         AFREE(i->skinDirPath);
    147         AFREE(i->coreHardwareIniPath);
    148 
    149         fileData_done(i->buildProperties);
    150         fileData_done(i->bootProperties);
    151 
    152         for (nn = 0; nn < i->numSearchPaths; nn++)
    153             AFREE(i->searchPaths[nn]);
    154 
    155         i->numSearchPaths = 0;
    156 
    157         if (i->configIni) {
    158             iniFile_free(i->configIni);
    159             i->configIni = NULL;
    160         }
    161 
    162         if (i->skinHardwareIni) {
    163             iniFile_free(i->skinHardwareIni);
    164             i->skinHardwareIni = NULL;
    165         }
    166 
    167         if (i->rootIni) {
    168             iniFile_free(i->rootIni);
    169             i->rootIni = NULL;
    170         }
    171 
    172         AFREE(i->contentPath);
    173         AFREE(i->sdkRootPath);
    174         AFREE(i->targetArch);
    175         AFREE(i->targetAbi);
    176 
    177         if (i->inAndroidBuild) {
    178             AFREE(i->androidOut);
    179             AFREE(i->androidBuildRoot);
    180         }
    181 
    182         AFREE(i->deviceName);
    183         AFREE(i);
    184     }
    185 }
    186 
    187 /* list of default file names for each supported image file type */
    188 static const char*  const  _imageFileNames[ AVD_IMAGE_MAX ] = {
    189 #define  _AVD_IMG(x,y,z)  y,
    190     AVD_IMAGE_LIST
    191 #undef _AVD_IMG
    192 };
    193 
    194 /* list of short text description for each supported image file type */
    195 static const char*  const _imageFileText[ AVD_IMAGE_MAX ] = {
    196 #define  _AVD_IMG(x,y,z)  z,
    197     AVD_IMAGE_LIST
    198 #undef _AVD_IMG
    199 };
    200 
    201 /***************************************************************
    202  ***************************************************************
    203  *****
    204  *****    UTILITY FUNCTIONS
    205  *****
    206  *****  The following functions do not depend on the AvdInfo
    207  *****  structure and could easily be moved elsewhere.
    208  *****
    209  *****/
    210 
    211 /* Parse a given config.ini file and extract the list of SDK search paths
    212  * from it. Returns the number of valid paths stored in 'searchPaths', or -1
    213  * in case of problem.
    214  *
    215  * Relative search paths in the config.ini will be stored as full pathnames
    216  * relative to 'sdkRootPath'.
    217  *
    218  * 'searchPaths' must be an array of char* pointers of at most 'maxSearchPaths'
    219  * entries.
    220  */
    221 static int
    222 _getSearchPaths( IniFile*    configIni,
    223                  const char* sdkRootPath,
    224                  int         maxSearchPaths,
    225                  char**      searchPaths )
    226 {
    227     char  temp[PATH_MAX], *p = temp, *end= p+sizeof temp;
    228     int   nn, count = 0;
    229 
    230     for (nn = 0; nn < maxSearchPaths; nn++) {
    231         char*  path;
    232 
    233         p = bufprint(temp, end, "%s%d", SEARCH_PREFIX, nn+1 );
    234         if (p >= end)
    235             continue;
    236 
    237         path = iniFile_getString(configIni, temp, NULL);
    238         if (path != NULL) {
    239             DD("    found image search path: %s", path);
    240             if (!path_is_absolute(path)) {
    241                 p = bufprint(temp, end, "%s/%s", sdkRootPath, path);
    242                 AFREE(path);
    243                 path = ASTRDUP(temp);
    244             }
    245             searchPaths[count++] = path;
    246         }
    247     }
    248     return count;
    249 }
    250 
    251 /* Check that an AVD name is valid. Returns 1 on success, 0 otherwise.
    252  */
    253 static int
    254 _checkAvdName( const char*  name )
    255 {
    256     int  len  = strlen(name);
    257     int  len2 = strspn(name, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    258                              "abcdefghijklmnopqrstuvwxyz"
    259                              "0123456789_.-");
    260     return (len == len2);
    261 }
    262 
    263 /* Returns the full path of a given file.
    264  *
    265  * If 'fileName' is an absolute path, this returns a simple copy.
    266  * Otherwise, this returns a new string corresponding to <rootPath>/<fileName>
    267  *
    268  * This returns NULL if the paths are too long.
    269  */
    270 static char*
    271 _getFullFilePath( const char* rootPath, const char* fileName )
    272 {
    273     if (path_is_absolute(fileName)) {
    274         return ASTRDUP(fileName);
    275     } else {
    276         char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
    277 
    278         p = bufprint(temp, end, "%s/%s", rootPath, fileName);
    279         if (p >= end) {
    280             return NULL;
    281         }
    282         return ASTRDUP(temp);
    283     }
    284 }
    285 
    286 /* check that a given directory contains a valid skin.
    287  * returns 1 on success, 0 on failure.
    288  */
    289 static int
    290 _checkSkinPath( const char*  skinPath )
    291 {
    292     char  temp[MAX_PATH], *p=temp, *end=p+sizeof(temp);
    293 
    294     /* for now, if it has a 'layout' file, it is a valid skin path */
    295     p = bufprint(temp, end, "%s/layout", skinPath);
    296     if (p >= end || !path_exists(temp))
    297         return 0;
    298 
    299     return 1;
    300 }
    301 
    302 /* Check that there is a skin named 'skinName' listed from 'skinDirRoot'
    303  * this returns the full path of the skin directory (after alias expansions),
    304  * including the skin name, or NULL on failure.
    305  */
    306 static char*
    307 _checkSkinSkinsDir( const char*  skinDirRoot,
    308                     const char*  skinName )
    309 {
    310     DirScanner*  scanner;
    311     char*        result;
    312     char         temp[MAX_PATH], *p = temp, *end = p + sizeof(temp);
    313 
    314     p = bufprint(temp, end, "%s/skins/%s", skinDirRoot, skinName);
    315     DD("Probing skin directory: %s", temp);
    316     if (p >= end || !path_exists(temp)) {
    317         DD("    ignore bad skin directory %s", temp);
    318         return NULL;
    319     }
    320 
    321     /* first, is this a normal skin directory ? */
    322     if (_checkSkinPath(temp)) {
    323         /* yes */
    324         DD("    found skin directory: %s", temp);
    325         return ASTRDUP(temp);
    326     }
    327 
    328     /* second, is it an alias to another skin ? */
    329     *p      = 0;
    330     result  = NULL;
    331     scanner = dirScanner_new(temp);
    332     if (scanner != NULL) {
    333         for (;;) {
    334             const char*  file = dirScanner_next(scanner);
    335 
    336             if (file == NULL)
    337                 break;
    338 
    339             if (strncmp(file, "alias-", 6) || file[6] == 0)
    340                 continue;
    341 
    342             p = bufprint(temp, end, "%s/skins/%s", skinDirRoot, file+6);
    343             if (p < end && _checkSkinPath(temp)) {
    344                 /* yes, it's an alias */
    345                 DD("    skin alias '%s' points to skin directory: %s",
    346                    file+6, temp);
    347                 result = ASTRDUP(temp);
    348                 break;
    349             }
    350         }
    351         dirScanner_free(scanner);
    352     }
    353     return result;
    354 }
    355 
    356 /* try to see if the skin name leads to a magic skin or skin path directly
    357  * returns 1 on success, 0 on error.
    358  *
    359  * on success, this sets up '*pSkinName' and '*pSkinDir'
    360  */
    361 static int
    362 _getSkinPathFromName( const char*  skinName,
    363                       const char*  sdkRootPath,
    364                       char**       pSkinName,
    365                       char**       pSkinDir )
    366 {
    367     char  temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
    368 
    369     /* if the skin name has the format 'NNNNxNNN' where
    370     * NNN is a decimal value, then this is a 'magic' skin
    371     * name that doesn't require a skin directory
    372     */
    373     if (isdigit(skinName[0])) {
    374         int  width, height;
    375         if (sscanf(skinName, "%dx%d", &width, &height) == 2) {
    376             D("'magic' skin format detected: %s", skinName);
    377             *pSkinName = ASTRDUP(skinName);
    378             *pSkinDir  = NULL;
    379             return 1;
    380         }
    381     }
    382 
    383     /* is the skin name a direct path to the skin directory ? */
    384     if (path_is_absolute(skinName) && _checkSkinPath(skinName)) {
    385         goto FOUND_IT;
    386     }
    387 
    388     /* is the skin name a relative path from the SDK root ? */
    389     p = bufprint(temp, end, "%s/%s", sdkRootPath, skinName);
    390     if (p < end && _checkSkinPath(temp)) {
    391         skinName = temp;
    392         goto FOUND_IT;
    393     }
    394 
    395     /* nope */
    396     return 0;
    397 
    398 FOUND_IT:
    399     if (path_split(skinName, pSkinDir, pSkinName) < 0) {
    400         derror("malformed skin name: %s", skinName);
    401         exit(2);
    402     }
    403     D("found skin '%s' in directory: %s", *pSkinName, *pSkinDir);
    404     return 1;
    405 }
    406 
    407 /***************************************************************
    408  ***************************************************************
    409  *****
    410  *****    NORMAL VIRTUAL DEVICE SUPPORT
    411  *****
    412  *****/
    413 
    414 /* compute path to the root SDK directory
    415  * assume we are in $SDKROOT/tools/emulator[.exe]
    416  */
    417 static int
    418 _avdInfo_getSdkRoot( AvdInfo*  i )
    419 {
    420 
    421     i->sdkRootPath = path_getSdkRoot(&i->sdkRootPathFromEnv);
    422     if (i->sdkRootPath == NULL)
    423         return -1;
    424 
    425     return 0;
    426 }
    427 
    428 /* parse the root config .ini file. it is located in
    429  * ~/.android/avd/<name>.ini or Windows equivalent
    430  */
    431 static int
    432 _avdInfo_getRootIni( AvdInfo*  i )
    433 {
    434     char*  iniPath = path_getRootIniPath( i->deviceName );
    435 
    436     if (iniPath == NULL) {
    437         derror("unknown virtual device name: '%s'", i->deviceName);
    438         return -1;
    439     }
    440 
    441     D("Android virtual device file at: %s", iniPath);
    442 
    443     i->rootIni = iniFile_newFromFile(iniPath);
    444     AFREE(iniPath);
    445 
    446     if (i->rootIni == NULL) {
    447         derror("Corrupt virtual device config file!");
    448         return -1;
    449     }
    450     return 0;
    451 }
    452 
    453 /* Returns the AVD's content path, i.e. the directory that contains
    454  * the AVD's content files (e.g. data partition, cache, sd card, etc...).
    455  *
    456  * We extract this by parsing the root config .ini file, looking for
    457  * a "path" elements.
    458  */
    459 static int
    460 _avdInfo_getContentPath( AvdInfo*  i )
    461 {
    462     char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
    463 
    464     i->contentPath = iniFile_getString(i->rootIni, ROOT_ABS_PATH_KEY, NULL);
    465 
    466     if (i->contentPath == NULL) {
    467         derror("bad config: %s",
    468                "virtual device file lacks a "ROOT_ABS_PATH_KEY" entry");
    469         return -1;
    470     }
    471 
    472     if (!path_is_dir(i->contentPath)) {
    473         // If the absolute path doesn't match an actual directory, try
    474         // the relative path if present.
    475         const char* relPath = iniFile_getString(i->rootIni, ROOT_REL_PATH_KEY, NULL);
    476         if (relPath != NULL) {
    477             p = bufprint_config_path(temp, end);
    478             p = bufprint(p, end, PATH_SEP "%s", relPath);
    479             if (p < end && path_is_dir(temp)) {
    480                 AFREE(i->contentPath);
    481                 i->contentPath = ASTRDUP(temp);
    482             }
    483         }
    484     }
    485 
    486     D("virtual device content at %s", i->contentPath);
    487     return 0;
    488 }
    489 
    490 static int
    491 _avdInfo_getApiLevel( AvdInfo*  i )
    492 {
    493     char*       target;
    494     const char* p;
    495     const int   defaultLevel = 1000;
    496     int         level        = defaultLevel;
    497 
    498 #    define ROOT_TARGET_KEY   "target"
    499 
    500     target = iniFile_getString(i->rootIni, ROOT_TARGET_KEY, NULL);
    501     if (target == NULL) {
    502         D("No target field in root AVD .ini file?");
    503         D("Defaulting to API level %d", level);
    504         return level;
    505     }
    506 
    507     DD("Found target field in root AVD .ini file: '%s'", target);
    508 
    509     /* There are two acceptable formats for the target key.
    510      *
    511      * 1/  android-<level>
    512      * 2/  <vendor-name>:<add-on-name>:<level>
    513      *
    514      * Where <level> can be either a _name_ (for experimental/preview SDK builds)
    515      * or a decimal number. Note that if a _name_, it can start with a digit.
    516      */
    517 
    518     /* First, extract the level */
    519     if (!memcmp(target, "android-", 8))
    520         p = target + 8;
    521     else {
    522         /* skip two columns */
    523         p = strchr(target, ':');
    524         if (p != NULL) {
    525             p = strchr(p+1, ':');
    526             if (p != NULL)
    527                 p += 1;
    528         }
    529     }
    530     if (p == NULL || !isdigit(*p)) {
    531         goto NOT_A_NUMBER;
    532     } else {
    533         char* end;
    534         long  val = strtol(p, &end, 10);
    535         if (end == NULL || *end != '\0' || val != (int)val) {
    536             goto NOT_A_NUMBER;
    537         }
    538         level = (int)val;
    539 
    540         /* Sanity check, we don't support anything prior to Android 1.5 */
    541         if (level < 3)
    542             level = 3;
    543 
    544         D("Found AVD target API level: %d", level);
    545     }
    546 EXIT:
    547     AFREE(target);
    548     return level;
    549 
    550 NOT_A_NUMBER:
    551     if (p == NULL) {
    552         D("Invalid target field in root AVD .ini file");
    553     } else {
    554         D("Target AVD api level is not a number");
    555     }
    556     D("Defaulting to API level %d", level);
    557     goto EXIT;
    558 }
    559 
    560 
    561 int
    562 avdInfo_getApiLevel(AvdInfo* i) {
    563     return i->apiLevel;
    564 }
    565 
    566 /* Look for a named file inside the AVD's content directory.
    567  * Returns NULL if it doesn't exist, or a strdup() copy otherwise.
    568  */
    569 static char*
    570 _avdInfo_getContentFilePath(AvdInfo*  i, const char* fileName)
    571 {
    572     char temp[MAX_PATH], *p = temp, *end = p + sizeof(temp);
    573 
    574     p = bufprint(p, end, "%s/%s", i->contentPath, fileName);
    575     if (p >= end) {
    576         derror("can't access virtual device content directory");
    577         return NULL;
    578     }
    579     if (!path_exists(temp)) {
    580         return NULL;
    581     }
    582     return ASTRDUP(temp);
    583 }
    584 
    585 /* find and parse the config.ini file from the content directory */
    586 static int
    587 _avdInfo_getConfigIni(AvdInfo*  i)
    588 {
    589     char*  iniPath = _avdInfo_getContentFilePath(i, "config.ini");
    590 
    591     /* Allow non-existing config.ini */
    592     if (iniPath == NULL) {
    593         D("virtual device has no config file - no problem");
    594         return 0;
    595     }
    596 
    597     D("virtual device config file: %s", iniPath);
    598     i->configIni = iniFile_newFromFile(iniPath);
    599     AFREE(iniPath);
    600 
    601     if (i->configIni == NULL) {
    602         derror("bad config: %s",
    603                "virtual device has corrupted config.ini");
    604         return -1;
    605     }
    606     return 0;
    607 }
    608 
    609 /* The AVD's config.ini contains a list of search paths (all beginning
    610  * with SEARCH_PREFIX) which are directory locations searched for
    611  * AVD platform files.
    612  */
    613 static void
    614 _avdInfo_getSearchPaths( AvdInfo*  i )
    615 {
    616     if (i->configIni == NULL)
    617         return;
    618 
    619     i->numSearchPaths = _getSearchPaths( i->configIni,
    620                                          i->sdkRootPath,
    621                                          MAX_SEARCH_PATHS,
    622                                          i->searchPaths );
    623     if (i->numSearchPaths == 0) {
    624         derror("no search paths found in this AVD's configuration.\n"
    625                "Weird, the AVD's config.ini file is malformed. Try re-creating it.\n");
    626         exit(2);
    627     }
    628     else
    629         DD("found a total of %d search paths for this AVD", i->numSearchPaths);
    630 }
    631 
    632 /* Search a file in the SDK search directories. Return NULL if not found,
    633  * or a strdup() otherwise.
    634  */
    635 static char*
    636 _avdInfo_getSdkFilePath(AvdInfo*  i, const char*  fileName)
    637 {
    638     char temp[MAX_PATH], *p = temp, *end = p + sizeof(temp);
    639 
    640     do {
    641         /* try the search paths */
    642         int  nn;
    643 
    644         for (nn = 0; nn < i->numSearchPaths; nn++) {
    645             const char* searchDir = i->searchPaths[nn];
    646 
    647             p = bufprint(temp, end, "%s/%s", searchDir, fileName);
    648             if (p < end && path_exists(temp)) {
    649                 DD("found %s in search dir: %s", fileName, searchDir);
    650                 goto FOUND;
    651             }
    652             DD("    no %s in search dir: %s", fileName, searchDir);
    653         }
    654 
    655         return NULL;
    656 
    657     } while (0);
    658 
    659 FOUND:
    660     return ASTRDUP(temp);
    661 }
    662 
    663 /* Search for a file in the content directory, and if not found, in the
    664  * SDK search directory. Returns NULL if not found.
    665  */
    666 static char*
    667 _avdInfo_getContentOrSdkFilePath(AvdInfo*  i, const char*  fileName)
    668 {
    669     char*  path;
    670 
    671     path = _avdInfo_getContentFilePath(i, fileName);
    672     if (path)
    673         return path;
    674 
    675     path = _avdInfo_getSdkFilePath(i, fileName);
    676     if (path)
    677         return path;
    678 
    679     return NULL;
    680 }
    681 
    682 #if 0
    683 static int
    684 _avdInfo_findContentOrSdkImage(AvdInfo* i, AvdImageType id)
    685 {
    686     const char* fileName = _imageFileNames[id];
    687     char*       path     = _avdInfo_getContentOrSdkFilePath(i, fileName);
    688 
    689     i->imagePath[id]  = path;
    690     i->imageState[id] = IMAGE_STATE_READONLY;
    691 
    692     if (path == NULL)
    693         return -1;
    694     else
    695         return 0;
    696 }
    697 #endif
    698 
    699 /* Returns path to the core hardware .ini file. This contains the
    700  * hardware configuration that is read by the core. The content of this
    701  * file is auto-generated before launching a core, but we need to know
    702  * its path before that.
    703  */
    704 static int
    705 _avdInfo_getCoreHwIniPath( AvdInfo* i, const char* basePath )
    706 {
    707     i->coreHardwareIniPath = _getFullFilePath(basePath, CORE_HARDWARE_INI);
    708     if (i->coreHardwareIniPath == NULL) {
    709         DD("Path too long for %s: %s", CORE_HARDWARE_INI, basePath);
    710         return -1;
    711     }
    712     D("using core hw config path: %s", i->coreHardwareIniPath);
    713     return 0;
    714 }
    715 
    716 
    717 static void
    718 _avdInfo_readPropertyFile(AvdInfo* i,
    719                           const char* filePath,
    720                           FileData* data) {
    721     int ret = fileData_initFromFile(data, filePath);
    722     if (ret < 0) {
    723         D("Error reading property file %s: %s", filePath, strerror(-ret));
    724     } else {
    725         D("Read property file at %s", filePath);
    726     }
    727 }
    728 
    729 
    730 static void
    731 _avdInfo_extractBuildProperties(AvdInfo* i) {
    732     i->targetArch = propertyFile_getTargetArch(i->buildProperties);
    733     if (!i->targetArch) {
    734         i->targetArch = ASTRDUP("arm");
    735         D("Cannot find target CPU architecture, defaulting to '%s'",
    736           i->targetArch);
    737     }
    738     i->targetAbi = propertyFile_getTargetAbi(i->buildProperties);
    739     if (!i->targetAbi) {
    740         i->targetAbi = ASTRDUP("armeabi");
    741         D("Cannot find target CPU ABI, defaulting to '%s'",
    742           i->targetAbi);
    743     }
    744     if (!i->apiLevel) {
    745         // Note: for regular AVDs, the API level is already extracted
    746         // from config.ini, besides, for older SDK platform images,
    747         // there is no build.prop file and the following function
    748         // would always return 1000, making the AVD unbootable!.
    749         i->apiLevel = propertyFile_getApiLevel(i->buildProperties);
    750         if (i->apiLevel < 3) {
    751             i->apiLevel = 3;
    752             D("Cannot find target API level, defaulting to %d",
    753             i->apiLevel);
    754         }
    755     }
    756 }
    757 
    758 
    759 static void
    760 _avdInfo_getPropertyFile(AvdInfo* i,
    761                          const char* propFileName,
    762                          FileData* data ) {
    763     char* filePath = _avdInfo_getContentOrSdkFilePath(i, propFileName);
    764     if (!filePath) {
    765         D("No %s property file found.", propFileName);
    766         return;
    767     }
    768 
    769     _avdInfo_readPropertyFile(i, filePath, data);
    770     free(filePath);
    771 }
    772 
    773 AvdInfo*
    774 avdInfo_new( const char*  name, AvdInfoParams*  params )
    775 {
    776     AvdInfo*  i;
    777 
    778     if (name == NULL)
    779         return NULL;
    780 
    781     if (!_checkAvdName(name)) {
    782         derror("virtual device name contains invalid characters");
    783         exit(1);
    784     }
    785 
    786     ANEW0(i);
    787     i->deviceName = ASTRDUP(name);
    788 
    789     if ( _avdInfo_getSdkRoot(i) < 0     ||
    790          _avdInfo_getRootIni(i) < 0     ||
    791          _avdInfo_getContentPath(i) < 0 ||
    792          _avdInfo_getConfigIni(i)   < 0 ||
    793          _avdInfo_getCoreHwIniPath(i, i->contentPath) < 0 )
    794         goto FAIL;
    795 
    796     i->apiLevel = _avdInfo_getApiLevel(i);
    797 
    798     /* look for image search paths. handle post 1.1/pre cupcake
    799      * obsolete SDKs.
    800      */
    801     _avdInfo_getSearchPaths(i);
    802 
    803     // Find the build.prop and boot.prop files and read them.
    804     _avdInfo_getPropertyFile(i, "build.prop", i->buildProperties);
    805     _avdInfo_getPropertyFile(i, "boot.prop", i->bootProperties);
    806 
    807     _avdInfo_extractBuildProperties(i);
    808 
    809     /* don't need this anymore */
    810     iniFile_free(i->rootIni);
    811     i->rootIni = NULL;
    812 
    813     return i;
    814 
    815 FAIL:
    816     avdInfo_free(i);
    817     return NULL;
    818 }
    819 
    820 /***************************************************************
    821  ***************************************************************
    822  *****
    823  *****    ANDROID BUILD SUPPORT
    824  *****
    825  *****    The code below corresponds to the case where we're
    826  *****    starting the emulator inside the Android build
    827  *****    system. The main differences are that:
    828  *****
    829  *****    - the $ANDROID_PRODUCT_OUT directory is used as the
    830  *****      content file.
    831  *****
    832  *****    - built images must not be modified by the emulator,
    833  *****      so system.img must be copied to a temporary file
    834  *****      and userdata.img must be copied to userdata-qemu.img
    835  *****      if the latter doesn't exist.
    836  *****
    837  *****    - the kernel and default skin directory are taken from
    838  *****      prebuilt
    839  *****
    840  *****    - there is no root .ini file, or any config.ini in
    841  *****      the content directory, no SDK images search path.
    842  *****/
    843 
    844 /* Read a hardware.ini if it is located in the skin directory */
    845 static int
    846 _avdInfo_getBuildSkinHardwareIni( AvdInfo*  i )
    847 {
    848     char* skinName;
    849     char* skinDirPath;
    850 
    851     avdInfo_getSkinInfo(i, &skinName, &skinDirPath);
    852     if (skinDirPath == NULL)
    853         return 0;
    854 
    855     int result = avdInfo_getSkinHardwareIni(i, skinName, skinDirPath);
    856 
    857     AFREE(skinName);
    858     AFREE(skinDirPath);
    859 
    860     return result;
    861 }
    862 
    863 int avdInfo_getSkinHardwareIni( AvdInfo* i, char* skinName, char* skinDirPath)
    864 {
    865     char  temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
    866 
    867     p = bufprint(temp, end, "%s/%s/hardware.ini", skinDirPath, skinName);
    868     if (p >= end || !path_exists(temp)) {
    869         DD("no skin-specific hardware.ini in %s", skinDirPath);
    870         return 0;
    871     }
    872 
    873     D("found skin-specific hardware.ini: %s", temp);
    874     if (i->skinHardwareIni != NULL)
    875         iniFile_free(i->skinHardwareIni);
    876     i->skinHardwareIni = iniFile_newFromFile(temp);
    877     if (i->skinHardwareIni == NULL)
    878         return -1;
    879 
    880     return 0;
    881 }
    882 
    883 AvdInfo*
    884 avdInfo_newForAndroidBuild( const char*     androidBuildRoot,
    885                             const char*     androidOut,
    886                             AvdInfoParams*  params )
    887 {
    888     AvdInfo*  i;
    889 
    890     ANEW0(i);
    891 
    892     i->inAndroidBuild   = 1;
    893     i->androidBuildRoot = ASTRDUP(androidBuildRoot);
    894     i->androidOut       = ASTRDUP(androidOut);
    895     i->contentPath      = ASTRDUP(androidOut);
    896 
    897     // Find the build.prop file and read it.
    898     char* buildPropPath = path_getBuildBuildProp(i->androidOut);
    899     if (buildPropPath) {
    900         _avdInfo_readPropertyFile(i, buildPropPath, i->buildProperties);
    901         free(buildPropPath);
    902     }
    903 
    904     // FInd the boot.prop file and read it.
    905     char* bootPropPath = path_getBuildBootProp(i->androidOut);
    906     if (bootPropPath) {
    907         _avdInfo_readPropertyFile(i, bootPropPath, i->bootProperties);
    908         free(bootPropPath);
    909     }
    910 
    911     _avdInfo_extractBuildProperties(i);
    912 
    913     i->deviceName = ASTRDUP("<build>");
    914 
    915     /* out/target/product/<name>/config.ini, if exists, provide configuration
    916      * from build files. */
    917     if (_avdInfo_getConfigIni(i) < 0 ||
    918         _avdInfo_getCoreHwIniPath(i, i->androidOut) < 0)
    919         goto FAIL;
    920 
    921     /* Read the build skin's hardware.ini, if any */
    922     _avdInfo_getBuildSkinHardwareIni(i);
    923 
    924     return i;
    925 
    926 FAIL:
    927     avdInfo_free(i);
    928     return NULL;
    929 }
    930 
    931 const char*
    932 avdInfo_getName( AvdInfo*  i )
    933 {
    934     return i ? i->deviceName : NULL;
    935 }
    936 
    937 const char*
    938 avdInfo_getImageFile( AvdInfo*  i, AvdImageType  imageType )
    939 {
    940     if (i == NULL || (unsigned)imageType >= AVD_IMAGE_MAX)
    941         return NULL;
    942 
    943     return i->imagePath[imageType];
    944 }
    945 
    946 uint64_t
    947 avdInfo_getImageFileSize( AvdInfo*  i, AvdImageType  imageType )
    948 {
    949     const char* file = avdInfo_getImageFile(i, imageType);
    950     uint64_t    size;
    951 
    952     if (file == NULL)
    953         return 0ULL;
    954 
    955     if (path_get_size(file, &size) < 0)
    956         return 0ULL;
    957 
    958     return size;
    959 }
    960 
    961 int
    962 avdInfo_isImageReadOnly( AvdInfo*  i, AvdImageType  imageType )
    963 {
    964     if (i == NULL || (unsigned)imageType >= AVD_IMAGE_MAX)
    965         return 1;
    966 
    967     return (i->imageState[imageType] == IMAGE_STATE_READONLY);
    968 }
    969 
    970 char*
    971 avdInfo_getKernelPath( AvdInfo*  i )
    972 {
    973     const char* imageName = _imageFileNames[ AVD_IMAGE_KERNEL ];
    974 
    975     char*  kernelPath = _avdInfo_getContentOrSdkFilePath(i, imageName);
    976 
    977     do {
    978         if (kernelPath || !i->inAndroidBuild)
    979             break;
    980 
    981         /* When in the Android build, look into the prebuilt directory
    982          * for our target architecture.
    983          */
    984         char temp[PATH_MAX], *p = temp, *end = p + sizeof(temp);
    985         const char* suffix = "";
    986 
    987         // If the target ABI is armeabi-v7a, then look for
    988         // kernel-qemu-armv7 instead of kernel-qemu in the prebuilt
    989         // directory.
    990         if (!strcmp(i->targetAbi, "armeabi-v7a")) {
    991             suffix = "-armv7";
    992         }
    993 
    994         p = bufprint(temp, end, "%s/kernel", i->androidOut);
    995         if (p < end && path_exists(temp)) {
    996             kernelPath = ASTRDUP(temp);
    997             break;
    998         }
    999 
   1000         p = bufprint(temp, end, "%s/prebuilts/qemu-kernel/%s/kernel-qemu%s",
   1001                      i->androidBuildRoot, i->targetArch, suffix);
   1002         if (p >= end || !path_exists(temp)) {
   1003             derror("bad workspace: cannot find prebuilt kernel in: %s", temp);
   1004             exit(1);
   1005         }
   1006         kernelPath = ASTRDUP(temp);
   1007 
   1008     } while (0);
   1009 
   1010     return kernelPath;
   1011 }
   1012 
   1013 
   1014 char*
   1015 avdInfo_getRamdiskPath( AvdInfo* i )
   1016 {
   1017     const char* imageName = _imageFileNames[ AVD_IMAGE_RAMDISK ];
   1018     return _avdInfo_getContentOrSdkFilePath(i, imageName);
   1019 }
   1020 
   1021 char*  avdInfo_getCachePath( AvdInfo*  i )
   1022 {
   1023     const char* imageName = _imageFileNames[ AVD_IMAGE_CACHE ];
   1024     return _avdInfo_getContentFilePath(i, imageName);
   1025 }
   1026 
   1027 char*  avdInfo_getDefaultCachePath( AvdInfo*  i )
   1028 {
   1029     const char* imageName = _imageFileNames[ AVD_IMAGE_CACHE ];
   1030     return _getFullFilePath(i->contentPath, imageName);
   1031 }
   1032 
   1033 char*  avdInfo_getSdCardPath( AvdInfo* i )
   1034 {
   1035     const char* imageName = _imageFileNames[ AVD_IMAGE_SDCARD ];
   1036     char*       path;
   1037 
   1038     /* Special case, the config.ini can have a SDCARD_PATH entry
   1039      * that gives the full path to the SD Card.
   1040      */
   1041     if (i->configIni != NULL) {
   1042         path = iniFile_getString(i->configIni, SDCARD_PATH, NULL);
   1043         if (path != NULL) {
   1044             if (path_exists(path))
   1045                 return path;
   1046 
   1047             dwarning("Ignoring invalid SDCard path: %s", path);
   1048             AFREE(path);
   1049         }
   1050     }
   1051 
   1052     /* Otherwise, simply look into the content directory */
   1053     return _avdInfo_getContentFilePath(i, imageName);
   1054 }
   1055 
   1056 char*
   1057 avdInfo_getSnapStoragePath( AvdInfo* i )
   1058 {
   1059     const char* imageName = _imageFileNames[ AVD_IMAGE_SNAPSHOTS ];
   1060     return _avdInfo_getContentFilePath(i, imageName);
   1061 }
   1062 
   1063 char*
   1064 avdInfo_getSystemImagePath( AvdInfo*  i )
   1065 {
   1066     const char* imageName = _imageFileNames[ AVD_IMAGE_USERSYSTEM ];
   1067     return _avdInfo_getContentFilePath(i, imageName);
   1068 }
   1069 
   1070 char*
   1071 avdInfo_getSystemInitImagePath( AvdInfo*  i )
   1072 {
   1073     const char* imageName = _imageFileNames[ AVD_IMAGE_INITSYSTEM ];
   1074     return _avdInfo_getContentOrSdkFilePath(i, imageName);
   1075 }
   1076 
   1077 char*
   1078 avdInfo_getDataImagePath( AvdInfo*  i )
   1079 {
   1080     const char* imageName = _imageFileNames[ AVD_IMAGE_USERDATA ];
   1081     return _avdInfo_getContentFilePath(i, imageName);
   1082 }
   1083 
   1084 char*
   1085 avdInfo_getDefaultDataImagePath( AvdInfo*  i )
   1086 {
   1087     const char* imageName = _imageFileNames[ AVD_IMAGE_USERDATA ];
   1088     return _getFullFilePath(i->contentPath, imageName);
   1089 }
   1090 
   1091 char*
   1092 avdInfo_getDataInitImagePath( AvdInfo* i )
   1093 {
   1094     const char* imageName = _imageFileNames[ AVD_IMAGE_INITDATA ];
   1095     return _avdInfo_getContentOrSdkFilePath(i, imageName);
   1096 }
   1097 
   1098 int
   1099 avdInfo_initHwConfig( AvdInfo*  i, AndroidHwConfig*  hw )
   1100 {
   1101     int  ret = 0;
   1102 
   1103     androidHwConfig_init(hw, i->apiLevel);
   1104 
   1105     /* First read the config.ini, if any */
   1106     if (i->configIni != NULL) {
   1107         ret = androidHwConfig_read(hw, i->configIni);
   1108     }
   1109 
   1110     /* The skin's hardware.ini can override values */
   1111     if (ret == 0 && i->skinHardwareIni != NULL) {
   1112         ret = androidHwConfig_read(hw, i->skinHardwareIni);
   1113     }
   1114 
   1115     /* Auto-disable keyboard emulation on sapphire platform builds */
   1116     if (i->androidOut != NULL) {
   1117         char*  p = strrchr(i->androidOut, '/');
   1118         if (p != NULL && !strcmp(p,"sapphire")) {
   1119             hw->hw_keyboard = 0;
   1120         }
   1121     }
   1122 
   1123     return ret;
   1124 }
   1125 
   1126 const char*
   1127 avdInfo_getContentPath( AvdInfo*  i )
   1128 {
   1129     return i->contentPath;
   1130 }
   1131 
   1132 int
   1133 avdInfo_inAndroidBuild( AvdInfo*  i )
   1134 {
   1135     return i->inAndroidBuild;
   1136 }
   1137 
   1138 char*
   1139 avdInfo_getTargetCpuArch(AvdInfo* i) {
   1140     return ASTRDUP(i->targetArch);
   1141 }
   1142 
   1143 char*
   1144 avdInfo_getTargetAbi( AvdInfo* i )
   1145 {
   1146     /* For now, we can't get the ABI from SDK AVDs */
   1147     return ASTRDUP(i->targetAbi);
   1148 }
   1149 
   1150 char*
   1151 avdInfo_getTracePath( AvdInfo*  i, const char*  traceName )
   1152 {
   1153     char   tmp[MAX_PATH], *p=tmp, *end=p + sizeof(tmp);
   1154 
   1155     if (i == NULL || traceName == NULL || traceName[0] == 0)
   1156         return NULL;
   1157 
   1158     if (i->inAndroidBuild) {
   1159         p = bufprint( p, end, "%s" PATH_SEP "traces" PATH_SEP "%s",
   1160                       i->androidOut, traceName );
   1161     } else {
   1162         p = bufprint( p, end, "%s" PATH_SEP "traces" PATH_SEP "%s",
   1163                       i->contentPath, traceName );
   1164     }
   1165     return ASTRDUP(tmp);
   1166 }
   1167 
   1168 const char*
   1169 avdInfo_getCoreHwIniPath( AvdInfo* i )
   1170 {
   1171     return i->coreHardwareIniPath;
   1172 }
   1173 
   1174 
   1175 void
   1176 avdInfo_getSkinInfo( AvdInfo*  i, char** pSkinName, char** pSkinDir )
   1177 {
   1178     char*  skinName = NULL;
   1179     char*  skinPath;
   1180     char   temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
   1181 
   1182     *pSkinName = NULL;
   1183     *pSkinDir  = NULL;
   1184 
   1185     /* First, see if the config.ini contains a SKIN_PATH entry that
   1186      * names the full directory path for the skin.
   1187      */
   1188     if (i->configIni != NULL ) {
   1189         skinPath = iniFile_getString( i->configIni, SKIN_PATH, NULL );
   1190         if (skinPath != NULL) {
   1191             /* If this skin name is magic or a direct directory path
   1192             * we have our result right here.
   1193             */
   1194             if (_getSkinPathFromName(skinPath, i->sdkRootPath,
   1195                                      pSkinName, pSkinDir )) {
   1196                 AFREE(skinPath);
   1197                 return;
   1198             }
   1199         }
   1200 
   1201         /* The SKIN_PATH entry was not valid, so look at SKIN_NAME */
   1202         D("Warning: config.ini contains invalid %s entry: %s", SKIN_PATH, skinPath);
   1203         AFREE(skinPath);
   1204 
   1205         skinName = iniFile_getString( i->configIni, SKIN_NAME, NULL );
   1206     }
   1207 
   1208     if (skinName == NULL) {
   1209         /* If there is no skin listed in the config.ini, try to see if
   1210          * there is one single 'skin' directory in the content directory.
   1211          */
   1212         p = bufprint(temp, end, "%s/skin", i->contentPath);
   1213         if (p < end && _checkSkinPath(temp)) {
   1214             D("using skin content from %s", temp);
   1215             AFREE(i->skinName);
   1216             *pSkinName = ASTRDUP("skin");
   1217             *pSkinDir  = ASTRDUP(i->contentPath);
   1218             return;
   1219         }
   1220 
   1221         /* otherwise, use the default name */
   1222         skinName = ASTRDUP(SKIN_DEFAULT);
   1223     }
   1224 
   1225     /* now try to find the skin directory for that name -
   1226      */
   1227     do {
   1228         /* first try the content directory, i.e. $CONTENT/skins/<name> */
   1229         skinPath = _checkSkinSkinsDir(i->contentPath, skinName);
   1230         if (skinPath != NULL)
   1231             break;
   1232 
   1233 #define  PREBUILT_SKINS_ROOT "development/tools/emulator"
   1234 
   1235         /* if we are in the Android build, try the prebuilt directory */
   1236         if (i->inAndroidBuild) {
   1237             p = bufprint( temp, end, "%s/%s",
   1238                         i->androidBuildRoot, PREBUILT_SKINS_ROOT );
   1239             if (p < end) {
   1240                 skinPath = _checkSkinSkinsDir(temp, skinName);
   1241                 if (skinPath != NULL)
   1242                     break;
   1243             }
   1244 
   1245             /* or in the parent directory of the system dir */
   1246             {
   1247                 char* parentDir = path_parent(i->androidOut, 1);
   1248                 if (parentDir != NULL) {
   1249                     skinPath = _checkSkinSkinsDir(parentDir, skinName);
   1250                     AFREE(parentDir);
   1251                     if (skinPath != NULL)
   1252                         break;
   1253                 }
   1254             }
   1255         }
   1256 
   1257         /* look in the search paths. For each <dir> in the list,
   1258          * look into <dir>/../skins/<name>/ */
   1259         {
   1260             int  nn;
   1261             for (nn = 0; nn < i->numSearchPaths; nn++) {
   1262                 char*  parentDir = path_parent(i->searchPaths[nn], 1);
   1263                 if (parentDir == NULL)
   1264                     continue;
   1265                 skinPath = _checkSkinSkinsDir(parentDir, skinName);
   1266                 AFREE(parentDir);
   1267                 if (skinPath != NULL)
   1268                   break;
   1269             }
   1270             if (nn < i->numSearchPaths)
   1271                 break;
   1272         }
   1273 
   1274         /* We didn't find anything ! */
   1275         *pSkinName = skinName;
   1276         return;
   1277 
   1278     } while (0);
   1279 
   1280     if (path_split(skinPath, pSkinDir, pSkinName) < 0) {
   1281         derror("weird skin path: %s", skinPath);
   1282         AFREE(skinPath);
   1283         return;
   1284     }
   1285     DD("found skin '%s' in directory: %s", *pSkinName, *pSkinDir);
   1286     AFREE(skinPath);
   1287     return;
   1288 }
   1289 
   1290 int
   1291 avdInfo_shouldUseDynamicSkin( AvdInfo* i)
   1292 {
   1293     if (i == NULL || i->configIni == NULL)
   1294         return 0;
   1295     return iniFile_getBoolean( i->configIni, SKIN_DYNAMIC, "no" );
   1296 }
   1297 
   1298 char*
   1299 avdInfo_getDynamicSkinPath( AvdInfo* i)
   1300 {
   1301     char tmp[PATH_MAX];
   1302 
   1303     if (i->inAndroidBuild) {
   1304         snprintf(tmp, sizeof(tmp), "%s/sdk/emulator/skins/dynamic/", i->androidBuildRoot);
   1305     } else {
   1306         snprintf(tmp, sizeof(tmp), "%s/tools/lib/emulator/skins/dynamic/", i->sdkRootPath);
   1307     }
   1308 
   1309     if (!path_exists(tmp))
   1310         return NULL;
   1311 
   1312     return ASTRDUP(tmp);
   1313 }
   1314 
   1315 char*
   1316 avdInfo_getCharmapFile( AvdInfo* i, const char* charmapName )
   1317 {
   1318     char        fileNameBuff[PATH_MAX];
   1319     const char* fileName;
   1320 
   1321     if (charmapName == NULL || charmapName[0] == '\0')
   1322         return NULL;
   1323 
   1324     if (strstr(charmapName, ".kcm") == NULL) {
   1325         snprintf(fileNameBuff, sizeof fileNameBuff, "%s.kcm", charmapName);
   1326         fileName = fileNameBuff;
   1327     } else {
   1328         fileName = charmapName;
   1329     }
   1330 
   1331     return _avdInfo_getContentOrSdkFilePath(i, fileName);
   1332 }
   1333 
   1334 int avdInfo_getAdbdCommunicationMode( AvdInfo* i )
   1335 {
   1336     if (i->apiLevel < 16) {
   1337         // QEMU pipe for ADB communication was added in android-4.1.1_r1 API 16
   1338         D("API < 16, forcing ro.adb.qemud==0");
   1339         return 0;
   1340     }
   1341 
   1342     return propertyFile_getAdbdCommunicationMode(i->buildProperties);
   1343 }
   1344 
   1345 int avdInfo_getSnapshotPresent(AvdInfo* i)
   1346 {
   1347     if (i->configIni == NULL) {
   1348         return 0;
   1349     } else {
   1350         return iniFile_getBoolean(i->configIni, "snapshot.present", "no");
   1351     }
   1352 }
   1353 
   1354 const FileData* avdInfo_getBootProperties(AvdInfo* i) {
   1355     return i->bootProperties;
   1356 }
   1357