• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2011 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 <stdlib.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include "android/utils/debug.h"
16 #include "android/utils/bufprint.h"
17 #include "android/utils/ini.h"
18 #include "android/utils/panic.h"
19 #include "android/utils/path.h"
20 #include "android/utils/system.h"
21 #include "android/avd/util.h"
22 
23 #define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
24 
25 /* this is the subdirectory of $HOME/.android where all
26  * root configuration files (and default content directories)
27  * are located.
28  */
29 #define  ANDROID_AVD_DIR    "avd"
30 
31 
32 /* Return the path to the Android SDK root installation.
33  *
34  * (*pFromEnv) will be set to 1 if it comes from the $ANDROID_SDK_ROOT
35  * environment variable, or 0 otherwise.
36  *
37  * Caller must free() returned string.
38  */
39 char*
path_getSdkRoot(char * pFromEnv)40 path_getSdkRoot( char *pFromEnv )
41 {
42     const char*  env;
43     char*        sdkPath;
44     char         temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
45 
46     /* If ANDROID_SDK_ROOT is defined is must point to a directory
47      * containing a valid SDK installation.
48      */
49 #define  SDK_ROOT_ENV  "ANDROID_SDK_ROOT"
50 
51     env = getenv(SDK_ROOT_ENV);
52     if (env != NULL && env[0] != 0) {
53         if (path_exists(env)) {
54             D("found " SDK_ROOT_ENV ": %s", env);
55             *pFromEnv = 1;
56             return ASTRDUP(env);
57         }
58         D(SDK_ROOT_ENV " points to unknown directory: %s", env);
59     }
60 
61     *pFromEnv = 0;
62 
63     /* We assume the emulator binary is under tools/ so use its
64      * parent as the Android SDK root.
65      */
66     (void) bufprint_app_dir(temp, end);
67     sdkPath = path_parent(temp, 1);
68     if (sdkPath == NULL) {
69         derror("can't find root of SDK directory");
70         return NULL;
71     }
72     D("found SDK root at %s", sdkPath);
73     return sdkPath;
74 }
75 
76 
77 /* Return the path to the AVD's root configuration .ini file. it is located in
78  * ~/.android/avd/<name>.ini or Windows equivalent
79  *
80  * This file contains the path to the AVD's content directory, which
81  * includes its own config.ini.
82  */
83 char*
path_getRootIniPath(const char * avdName)84 path_getRootIniPath( const char*  avdName )
85 {
86     char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
87 
88     p = bufprint_config_path(temp, end);
89     p = bufprint(p, end, "/" ANDROID_AVD_DIR "/%s.ini", avdName);
90     if (p >= end) {
91         return NULL;
92     }
93     if (!path_exists(temp)) {
94         return NULL;
95     }
96     return ASTRDUP(temp);
97 }
98 
99 
100 char*
path_getSdkHome(void)101 path_getSdkHome(void)
102 {
103     char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
104     p = bufprint_config_path(temp, end);
105     if (p >= end) {
106         APANIC("User path too long!: %s\n", temp);
107     }
108     return strdup(temp);
109 }
110 
111 
112 static char*
_getAvdContentPath(const char * avdName)113 _getAvdContentPath(const char* avdName)
114 {
115     char*    sdkHome = path_getSdkHome();
116     char*    avdPath = NULL;
117     IniFile* ini;
118     char     temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
119 
120     /* Look for the root .ini file */
121     p = bufprint(temp, end, "%s/avd/%s.ini", sdkHome, avdName);
122     if (p >= end) {
123         APANIC("AVD Name too long: %s\n", avdName);
124     }
125 
126     ini = iniFile_newFromFile(temp);
127     if (ini == NULL) {
128         APANIC("Could not open: %s", temp);
129     }
130 
131     avdPath = iniFile_getString(ini, "path", NULL);
132 
133     iniFile_free(ini);
134     AFREE(sdkHome);
135 
136     return avdPath;
137 }
138 
139 
140 static char*
_getAvdTargetArch(const char * avdPath)141 _getAvdTargetArch(const char* avdPath)
142 {
143     IniFile* ini;
144     char*    targetArch = NULL;
145     char     temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
146     p = bufprint(temp, end, "%s/config.ini", avdPath);
147     if (p >= end) {
148         APANIC("AVD path too long: %s\n", avdPath);
149     }
150     ini = iniFile_newFromFile(temp);
151     if (ini == NULL) {
152         APANIC("Could not open AVD config file: %s", temp);
153     }
154     targetArch = iniFile_getString(ini, "hw.cpu.arch", "arm");
155     iniFile_free(ini);
156 
157     return targetArch;
158 }
159 
160 char*
path_getAvdTargetArch(const char * avdName)161 path_getAvdTargetArch( const char* avdName )
162 {
163     char*  avdPath = _getAvdContentPath(avdName);
164     char*  avdArch = _getAvdTargetArch(avdPath);
165 
166     return avdArch;
167 }
168 
169 /* Retrieves the value of a given system property defined in a .prop
170  * file. This is a text file that contains definitions of the format:
171  * <name>=<value>
172  *
173  * Returns NULL if property <name> is undefined or empty.
174  * Returned string must be freed by the caller.
175  */
176 static char*
_getSystemProperty(const char * propFile,const char * propName)177 _getSystemProperty( const char* propFile, const char* propName )
178 {
179     FILE*  file;
180     char   temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
181     int    propNameLen = strlen(propName);
182     char*  result = NULL;
183 
184     file = fopen(propFile, "rb");
185     if (file == NULL) {
186         D("Could not open file: %s: %s", propFile, strerror(errno));
187         return NULL;
188     }
189 
190     while (fgets(temp, sizeof temp, file) != NULL) {
191         /* Trim trailing newlines, if any */
192         p = memchr(temp, '\0', sizeof temp);
193         if (p == NULL)
194             p = end;
195         if (p > temp && p[-1] == '\n') {
196             *--p = '\0';
197         }
198         if (p > temp && p[-1] == '\r') {
199             *--p = '\0';
200         }
201         /* force zero-termination in case of full-buffer */
202         if (p == end)
203             *--p = '\0';
204 
205         /* check that the line starts with the property name */
206         if (memcmp(temp, propName, propNameLen) != 0) {
207             continue;
208         }
209         p = temp + propNameLen;
210 
211         /* followed by an equal sign */
212         if (p >= end || *p != '=')
213             continue;
214         p++;
215 
216         /* followed by something */
217         if (p >= end || !*p)
218             break;
219 
220         result = ASTRDUP(p);
221         break;
222     }
223     fclose(file);
224     return result;
225 }
226 
227 static char*
_getBuildProperty(const char * androidOut,const char * propName)228 _getBuildProperty( const char* androidOut, const char* propName )
229 {
230     char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
231 
232     p = bufprint(temp, end, "%s/system/build.prop", androidOut);
233     if (p >= end) {
234         D("%s: ANDROID_PRODUCT_OUT too long: %s", __FUNCTION__, androidOut);
235         return NULL;
236     }
237     return _getSystemProperty(temp, propName);
238 }
239 
240 char*
path_getBuildTargetArch(const char * androidOut)241 path_getBuildTargetArch( const char* androidOut )
242 {
243     const char* defaultArch = "arm";
244     char*       result = NULL;
245     char*       cpuAbi = _getBuildProperty(androidOut, "ro.product.cpu.abi");
246 
247     if (cpuAbi == NULL) {
248         D("Coult not find CPU ABI in build properties!");
249         D("Default target architecture=%s", defaultArch);
250         result = ASTRDUP(defaultArch);
251     } else {
252         /* Translate ABI to cpu arch if necessary */
253         if (!strcmp("armeabi",cpuAbi))
254             result = "arm";
255         else if (!strcmp("armeabi-v7a", cpuAbi))
256             result = "arm";
257         else
258             result = cpuAbi;
259 
260         D("Found target ABI=%s, architecture=%s", cpuAbi, result);
261         result = ASTRDUP(result);
262         AFREE(cpuAbi);
263     }
264     return result;
265 }
266 
267 char*
path_getBuildTargetAbi(const char * androidOut)268 path_getBuildTargetAbi( const char* androidOut )
269 {
270     const char* defaultAbi = "armeabi";
271     char*       result = NULL;
272     char*       cpuAbi = _getBuildProperty(androidOut, "ro.product.cpu.abi");
273 
274     if (cpuAbi == NULL) {
275         D("Coult not find CPU ABI in build properties!");
276         D("Default target ABI: %s", defaultAbi);
277         result = ASTRDUP(defaultAbi);
278     } else {
279         D("Found target ABI=%s", cpuAbi);
280         result = cpuAbi;
281     }
282     return result;
283 }
284 
285 
286 int
path_getBuildTargetApiLevel(const char * androidOut)287 path_getBuildTargetApiLevel( const char* androidOut )
288 {
289     const int  defaultLevel = 1000;
290     int        level        = defaultLevel;
291     char*      sdkVersion = _getBuildProperty(androidOut, "ro.build.version.sdk");
292 
293     if (sdkVersion != NULL) {
294         long  value;
295         char* end;
296         value = strtol(sdkVersion, &end, 10);
297         if (end == NULL || *end != '\0' || value != (int)value) {
298             D("Invalid SDK version build property: '%s'", sdkVersion);
299             D("Defaulting to target API level %d", level);
300         } else {
301             level = (int)value;
302             /* Sanity check, the Android SDK doesn't support anything
303              * before Android 1.5, a.k.a API level 3 */
304             if (level < 3)
305                 level = 3;
306             D("Found target API level: %d", level);
307         }
308         AFREE(sdkVersion);
309     } else {
310         D("Could not find target API level / SDK version in build properties!");
311         D("Default target API level: %d", level);
312     }
313     return level;
314 }
315 
316 int
path_getAdbdCommunicationMode(const char * androidOut)317 path_getAdbdCommunicationMode( const char* androidOut )
318 {
319     char* prop = _getBuildProperty(androidOut, "ro.adb.qemud");
320     if (prop != NULL) {
321         long val = 0;
322         char* end;
323         val = strtol(prop, &end, 10);
324         if (end == NULL || *end != '\0' || val != (int)val) {
325             D("Invalid ro.adb.qemud build property: '%s'", prop);
326             val = 0;
327         } else {
328             D("Found ro.adb.qemud build property: %d", val);
329         }
330         AFREE(prop);
331         return (int)val;
332     } else {
333         /* Missing ro.adb.qemud means "legacy" ADBD. */
334         return 0;
335     }
336 }
337