SDK emulator: support relative path in avd root ini files.

Change-Id: I0488a930c0975dfb605fddba857739c36477286f
diff --git a/Makefile.android b/Makefile.android
index 4faea98..78dad44 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -86,12 +86,10 @@
 # itself only works on GCC 4.x anyway.
 GCC_W_NO_MISSING_FIELD_INITIALIZERS := -Wno-missing-field-initializers
 ifeq ($(HOST_OS),windows)
-  ifeq ($(USE_MINGW),)
     ifeq (,$(shell gcc -Q --help=warnings 2>/dev/null | grep missing-field-initializers))
         $(info emulator: Ignoring unsupported GCC flag $(GCC_W_NO_MISSING_FIELD_INITIALIZERS))
         GCC_W_NO_MISSING_FIELD_INITIALIZERS :=
     endif
-  endif
 endif
 
 # BUILD_STANDALONE_EMULATOR is only defined when building with
diff --git a/android/avd/info.c b/android/avd/info.c
index 0f43de6..7d4191d 100644
--- a/android/avd/info.c
+++ b/android/avd/info.c
@@ -11,6 +11,7 @@
 */
 #include "android/avd/info.h"
 #include "android/avd/util.h"
+#include "android/avd/keys.h"
 #include "android/config/config.h"
 #include "android/utils/path.h"
 #include "android/utils/bufprint.h"
@@ -64,38 +65,6 @@
  * with one of the usual options.
  */
 
-/* the prefix of config.ini keys that will be used for search directories
- * of system images.
- */
-#define  SEARCH_PREFIX   "image.sysdir."
-
-/* the maximum number of search path keys we're going to read from the
- * config.ini file
- */
-#define  MAX_SEARCH_PATHS  2
-
-/* the config.ini key that will be used to indicate the full relative
- * path to the skin directory (including the skin name).
- */
-#define  SKIN_PATH       "skin.path"
-
-/* the config.ini key that will be used to indicate the default skin's name.
- * this is ignored if there is a valid SKIN_PATH entry in the file.
- */
-#define  SKIN_NAME       "skin.name"
-
-/* the config.ini key that specifies if this AVD should use a dynamic skin */
-#define  SKIN_DYNAMIC    "skin.dynamic"
-
-/* default skin name */
-#define  SKIN_DEFAULT    "HVGA"
-
-/* the config.ini key that is used to indicate the absolute path
- * to the SD Card image file, if you don't want to place it in
- * the content directory.
- */
-#define  SDCARD_PATH     "sdcard.path"
-
 /* the name of the .ini file that will contain the complete hardware
  * properties for the AVD. This will be used to launch the corresponding
  * core from the UI.
@@ -479,15 +448,30 @@
 static int
 _avdInfo_getContentPath( AvdInfo*  i )
 {
-#   define  ROOT_PATH_KEY    "path"
+    char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
 
-    i->contentPath = iniFile_getString(i->rootIni, ROOT_PATH_KEY, NULL);
+    i->contentPath = iniFile_getString(i->rootIni, ROOT_ABS_PATH_KEY, NULL);
 
     if (i->contentPath == NULL) {
         derror("bad config: %s",
-               "virtual device file lacks a "ROOT_PATH_KEY" entry");
+               "virtual device file lacks a "ROOT_ABS_PATH_KEY" entry");
         return -1;
     }
+
+    if (!path_is_dir(i->contentPath)) {
+        // If the absolute path doesn't match an actual directory, try
+        // the relative path if present.
+        const char* relPath = iniFile_getString(i->rootIni, ROOT_REL_PATH_KEY, NULL);
+        if (relPath != NULL) {
+            p = bufprint_config_path(temp, end);
+            p = bufprint(p, end, PATH_SEP "%s", relPath);
+            if (p < end && path_is_dir(temp)) {
+                AFREE(i->contentPath);
+                i->contentPath = ASTRDUP(temp);
+            }
+        }
+    }
+
     D("virtual device content at %s", i->contentPath);
     return 0;
 }
diff --git a/android/avd/keys.h b/android/avd/keys.h
new file mode 100755
index 0000000..9f4aff6
--- /dev/null
+++ b/android/avd/keys.h
@@ -0,0 +1,70 @@
+/* Copyright (C) 2012 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#ifndef _ANDROID_AVD_KEYS_H
+#define _ANDROID_AVD_KEYS_H
+
+/* Keys of the properties found in avd/name.ini and config.ini files.
+ *
+ * These keys must match their counterpart defined in
+ * sdk/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
+ */
+
+
+/* -- Keys used in avd/name.ini -- */
+
+/* Absolute path of the AVD content directory.
+ */
+#define  ROOT_ABS_PATH_KEY    "path"
+
+/* Relative path of the AVD content directory.
+ * Path is relative to the bufprint_config_path().
+ */
+#define  ROOT_REL_PATH_KEY    "path.rel"
+
+
+/* -- Keys used in config.ini -- */
+
+/* the prefix of config.ini keys that will be used for search directories
+ * of system images.
+ */
+#define  SEARCH_PREFIX   "image.sysdir."
+
+/* the maximum number of search path keys we're going to read from the
+ * config.ini file
+ */
+#define  MAX_SEARCH_PATHS  2
+
+/* the config.ini key that will be used to indicate the full relative
+ * path to the skin directory (including the skin name).
+ */
+#define  SKIN_PATH       "skin.path"
+
+/* the config.ini key that will be used to indicate the default skin's name.
+ * this is ignored if there is a valid SKIN_PATH entry in the file.
+ */
+#define  SKIN_NAME       "skin.name"
+
+/* the config.ini key that specifies if this AVD should use a dynamic skin */
+#define  SKIN_DYNAMIC    "skin.dynamic"
+
+/* default skin name */
+#define  SKIN_DEFAULT    "HVGA"
+
+/* the config.ini key that is used to indicate the absolute path
+ * to the SD Card image file, if you don't want to place it in
+ * the content directory.
+ */
+#define  SDCARD_PATH     "sdcard.path"
+
+
+
+#endif /* _ANDROID_AVD_KEYS_H */
diff --git a/android/avd/util.c b/android/avd/util.c
index cc51e0f..75263a3 100644
--- a/android/avd/util.c
+++ b/android/avd/util.c
@@ -19,6 +19,7 @@
 #include "android/utils/path.h"
 #include "android/utils/system.h"
 #include "android/avd/util.h"
+#include "android/avd/keys.h"
 
 #define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
 
@@ -86,7 +87,7 @@
     char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
 
     p = bufprint_config_path(temp, end);
-    p = bufprint(p, end, "/" ANDROID_AVD_DIR "/%s.ini", avdName);
+    p = bufprint(p, end, PATH_SEP ANDROID_AVD_DIR PATH_SEP "%s.ini", avdName);
     if (p >= end) {
         return NULL;
     }
@@ -112,26 +113,37 @@
 static char*
 _getAvdContentPath(const char* avdName)
 {
-    char*    sdkHome = path_getSdkHome();
+    char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+    IniFile* ini = NULL;
+    char*    iniPath = path_getRootIniPath(avdName);
     char*    avdPath = NULL;
-    IniFile* ini;
-    char     temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
 
-    /* Look for the root .ini file */
-    p = bufprint(temp, end, "%s/avd/%s.ini", sdkHome, avdName);
-    if (p >= end) {
-        APANIC("AVD Name too long: %s\n", avdName);
+    if (iniPath != NULL) {
+        ini = iniFile_newFromFile(iniPath);
+        AFREE(iniPath);
     }
 
-    ini = iniFile_newFromFile(temp);
     if (ini == NULL) {
-        APANIC("Could not open: %s", temp);
+        APANIC("Could not open: %s\n", iniPath == NULL ? avdName : iniPath);
     }
 
-    avdPath = iniFile_getString(ini, "path", NULL);
+    avdPath = iniFile_getString(ini, ROOT_ABS_PATH_KEY, NULL);
+
+    if (!path_is_dir(avdPath)) {
+        // If the absolute path doesn't match an actual directory, try
+        // the relative path if present.
+        const char* relPath = iniFile_getString(ini, ROOT_REL_PATH_KEY, NULL);
+        if (relPath != NULL) {
+            p = bufprint_config_path(temp, end);
+            p = bufprint(p, end, PATH_SEP "%s", relPath);
+            if (p < end && path_is_dir(temp)) {
+                AFREE(avdPath);
+                avdPath = ASTRDUP(temp);
+            }
+        }
+    }
 
     iniFile_free(ini);
-    AFREE(sdkHome);
 
     return avdPath;
 }
@@ -143,13 +155,13 @@
     IniFile* ini;
     char*    targetArch = NULL;
     char     temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
-    p = bufprint(temp, end, "%s/config.ini", avdPath);
+    p = bufprint(temp, end, "%s" PATH_SEP "config.ini", avdPath);
     if (p >= end) {
         APANIC("AVD path too long: %s\n", avdPath);
     }
     ini = iniFile_newFromFile(temp);
     if (ini == NULL) {
-        APANIC("Could not open AVD config file: %s", temp);
+        APANIC("Could not open AVD config file: %s\n", temp);
     }
     targetArch = iniFile_getString(ini, "hw.cpu.arch", "arm");
     iniFile_free(ini);
diff --git a/android/utils/path.c b/android/utils/path.c
index 3e9d97b..95c9c2e 100644
--- a/android/utils/path.c
+++ b/android/utils/path.c
@@ -219,6 +219,8 @@
 path_exists( const char*  path )
 {
     int  ret;
+    if (path == NULL)
+        return 0;
     CHECKED(ret, access(path, F_OK));
     return (ret == 0) || (errno != ENOENT);
 }
@@ -230,6 +232,8 @@
     int          ret;
     struct stat  st;
 
+    if (path == NULL)
+        return 0;
     CHECKED(ret, stat(path, &st));
     if (ret < 0)
         return 0;
@@ -245,6 +249,8 @@
     int          ret;
     struct stat  st;
 
+    if (path == NULL)
+        return 0;
     CHECKED(ret, stat(path, &st));
     if (ret < 0)
         return 0;
@@ -257,6 +263,8 @@
 path_can_read( const char*  path )
 {
     int  ret;
+    if (path == NULL)
+        return 0;
     CHECKED(ret, access(path, R_OK));
     return (ret == 0);
 }
@@ -265,6 +273,8 @@
 path_can_write( const char*  path )
 {
     int  ret;
+    if (path == NULL)
+        return 0;
     CHECKED(ret, access(path, R_OK));
     return (ret == 0);
 }
@@ -273,6 +283,8 @@
 path_can_exec( const char* path )
 {
     int  ret;
+    if (path == NULL)
+        return 0;
     CHECKED(ret, access(path, X_OK));
     return (ret == 0);
 }