• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "info.h"
15 
16 #include "util.h"
17 #include "keys.h"
18 #include "base/ArraySize.h"
19 #include "base/export.h"
20 #include "host-common/feature_control.h"
21 
22 #include <assert.h>
23 #include <ctype.h>
24 #include <stdbool.h>
25 #include <stddef.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <errno.h>
30 
31 /* global variables - see android/globals.h */
32 AvdInfoParams   android_avdParams[1];
33 AvdInfo*        android_avdInfo;
34 
aemu_get_android_avdInfoPtr()35 AEMU_EXPORT AvdInfo** aemu_get_android_avdInfoPtr() {
36     return &android_avdInfo;
37 }
38 
39 /* set to 1 for debugging */
40 #define DEBUG 0
41 
42 #if DEBUG >= 1
43 #include <stdio.h>
44 #define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
45 #define DD(...) VERBOSE_PRINT(avd_config,__VA_ARGS__)
46 #else
47 #define D(...) (void)0
48 #define DD(...) (void)0
49 #endif
50 
51 /* technical note on how all of this is supposed to work:
52  *
53  * Each AVD corresponds to a "content directory" that is used to
54  * store persistent disk images and configuration files. Most remarkable
55  * are:
56  *
57  * - a "config.ini" file used to hold configuration information for the
58  *   AVD
59  *
60  * - mandatory user data image ("userdata-qemu.img") and cache image
61  *   ("cache.img")
62  *
63  * - optional mutable system image ("system-qemu.img"), kernel image
64  *   ("kernel-qemu") and read-only ramdisk ("ramdisk.img")
65  *
66  * When starting up an AVD, the emulator looks for relevant disk images
67  * in the content directory. If it doesn't find a given image there, it
68  * will try to search in the list of system directories listed in the
69  * 'config.ini' file through one of the following (key,value) pairs:
70  *
71  *    images.sysdir.1 = <first search path>
72  *    images.sysdir.2 = <second search path>
73  *
74  * The search paths can be absolute, or relative to the root SDK installation
75  * path (which is determined from the emulator program's location, or from the
76  * ANDROID_SDK_ROOT environment variable).
77  *
78  * Individual image disk search patch can be over-riden on the command-line
79  * with one of the usual options.
80  */
81 
82 /* certain disk image files are mounted read/write by the emulator
83  * to ensure that several emulators referencing the same files
84  * do not corrupt these files, we need to lock them and respond
85  * to collision depending on the image type.
86  *
87  * the enumeration below is used to record information about
88  * each image file path.
89  *
90  * READONLY means that the file will be mounted read-only
91  * and this doesn't need to be locked. must be first in list
92  *
93  * MUSTLOCK means that the file should be locked before
94  * being mounted by the emulator
95  *
96  * TEMPORARY means that the file has been copied to a
97  * temporary image, which can be mounted read/write
98  * but doesn't require locking.
99  */
100 typedef enum {
101     IMAGE_STATE_READONLY,     /* unlocked */
102     IMAGE_STATE_MUSTLOCK,     /* must be locked */
103     IMAGE_STATE_LOCKED,       /* locked */
104     IMAGE_STATE_LOCKED_EMPTY, /* locked and empty */
105     IMAGE_STATE_TEMPORARY,    /* copied to temp file (no lock needed) */
106 } AvdImageState;
107 
108 struct AvdInfo {
109     /* for the Android build system case */
110     char      inAndroidBuild;
111     char*     androidOut;
112     char*     androidBuildRoot;
113     char*     targetArch;
114     char*     targetAbi;
115     char*     acpiIniPath;
116 
117     /* for the normal virtual device case */
118     char*     deviceName;
119     char*     deviceId;
120     char*     sdkRootPath;
121     char*     searchPaths[ MAX_SEARCH_PATHS ];
122     int       numSearchPaths;
123     char*     contentPath;
124     char*     rootIniPath;
125     CIniFile* rootIni;   /* root <foo>.ini file, empty if missing */
126     CIniFile* configIni; /* virtual device's config.ini, NULL if missing */
127     CIniFile* skinHardwareIni; /* skin-specific hardware.ini */
128 
129     /* for both */
130     int       apiLevel;
131     int       incrementalVersion;
132 
133     /* For preview releases where we don't know the exact API level this flag
134      * indicates that at least we know it's M+ (for some code that needs to
135      * select either legacy or modern operation mode.
136      */
137     bool      isMarshmallowOrHigher;
138     bool      isGoogleApis;
139     bool      isUserBuild;
140     AvdFlavor flavor;
141     char*     skinName;     /* skin name */
142     char*     skinDirPath;  /* skin directory */
143     char*     coreHardwareIniPath;  /* core hardware.ini path */
144     char*     snapshotLockPath;  /* core snapshot.lock path */
145     char*     multiInstanceLockPath;
146 
147     // FileData  buildProperties[1];  /* build.prop file */
148     // FileData  bootProperties[1];   /* boot.prop file */
149 
150     /* image files */
151     char*     imagePath [ AVD_IMAGE_MAX ];
152     char      imageState[ AVD_IMAGE_MAX ];
153 
154     /* skip checks */
155     bool noChecks;
156 };
157 
158 
159 // void
160 // avdInfo_free( AvdInfo*  i )
161 // {
162 //     if (i) {
163 //         int  nn;
164 //
165 //         for (nn = 0; nn < AVD_IMAGE_MAX; nn++)
166 //             AFREE(i->imagePath[nn]);
167 //
168 //         AFREE(i->skinName);
169 //         AFREE(i->skinDirPath);
170 //         AFREE(i->coreHardwareIniPath);
171 //         AFREE(i->snapshotLockPath);
172 //
173 //         fileData_done(i->buildProperties);
174 //         fileData_done(i->bootProperties);
175 //
176 //         for (nn = 0; nn < i->numSearchPaths; nn++)
177 //             AFREE(i->searchPaths[nn]);
178 //
179 //         i->numSearchPaths = 0;
180 //
181 //         if (i->configIni) {
182 //             iniFile_free(i->configIni);
183 //             i->configIni = NULL;
184 //         }
185 //
186 //         if (i->skinHardwareIni) {
187 //             iniFile_free(i->skinHardwareIni);
188 //             i->skinHardwareIni = NULL;
189 //         }
190 //
191 //         if (i->rootIni) {
192 //             iniFile_free(i->rootIni);
193 //             i->rootIni = NULL;
194 //         }
195 //
196 //         AFREE(i->contentPath);
197 //         AFREE(i->sdkRootPath);
198 //         AFREE(i->rootIniPath);
199 //         AFREE(i->targetArch);
200 //         AFREE(i->targetAbi);
201 //
202 //         if (i->inAndroidBuild) {
203 //             AFREE(i->androidOut);
204 //             AFREE(i->androidBuildRoot);
205 //             AFREE(i->acpiIniPath);
206 //         }
207 //
208 //         AFREE(i->deviceName);
209 //         AFREE(i->deviceId);
210 //         AFREE(i);
211 //     }
212 // }
213 //
214 // /* list of default file names for each supported image file type */
215 // static const char*  const  _imageFileNames[ AVD_IMAGE_MAX ] = {
216 // #define  _AVD_IMG(x,y,z)  y,
217 //     AVD_IMAGE_LIST
218 // #undef _AVD_IMG
219 // };
220 //
221 // /***************************************************************
222 //  ***************************************************************
223 //  *****
224 //  *****    UTILITY FUNCTIONS
225 //  *****
226 //  *****  The following functions do not depend on the AvdInfo
227 //  *****  structure and could easily be moved elsewhere.
228 //  *****
229 //  *****/
230 //
231 // /* Parse a given config.ini file and extract the list of SDK search paths
232 //  * from it. Returns the number of valid paths stored in 'searchPaths', or -1
233 //  * in case of problem.
234 //  *
235 //  * Relative search paths in the config.ini will be stored as full pathnames
236 //  * relative to 'sdkRootPath'.
237 //  *
238 //  * 'searchPaths' must be an array of char* pointers of at most 'maxSearchPaths'
239 //  * entries.
240 //  */
241 // static int _getSearchPaths(CIniFile* configIni,
242 //                            const char* sdkRootPath,
243 //                            int maxSearchPaths,
244 //                            char** searchPaths) {
245 //     char  temp[PATH_MAX], *p = temp, *end= p+sizeof temp;
246 //     int   nn, count = 0;
247 //
248 //     for (nn = 0; nn < maxSearchPaths; nn++) {
249 //         char*  path;
250 //
251 //         p = bufprint(temp, end, "%s%d", SEARCH_PREFIX, nn+1 );
252 //         if (p >= end)
253 //             continue;
254 //
255 //         path = iniFile_getString(configIni, temp, NULL);
256 //         if (path != NULL) {
257 //             DD("    found image search path: %s", path);
258 //             if (!path_is_absolute(path)) {
259 //                 p = bufprint(temp, end, "%s"PATH_SEP"%s", sdkRootPath, path);
260 //                 AFREE(path);
261 //                 path = ASTRDUP(temp);
262 //             }
263 //             searchPaths[count++] = path;
264 //         }
265 //     }
266 //     return count;
267 // }
268 //
269 // /* Check that an AVD name is valid. Returns 1 on success, 0 otherwise.
270 //  */
271 // static int
272 // _checkAvdName( const char*  name )
273 // {
274 //     int  len  = strlen(name);
275 //     int  len2 = strspn(name, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
276 //                              "abcdefghijklmnopqrstuvwxyz"
277 //                              "0123456789_.-");
278 //     return (len == len2);
279 // }
280 //
281 // /* Returns the full path of a given file.
282 //  *
283 //  * If 'fileName' is an absolute path, this returns a simple copy.
284 //  * Otherwise, this returns a new string corresponding to <rootPath>/<fileName>
285 //  *
286 //  * This returns NULL if the paths are too long.
287 //  */
288 // static char*
289 // _getFullFilePath( const char* rootPath, const char* fileName )
290 // {
291 //     if (path_is_absolute(fileName)) {
292 //         return ASTRDUP(fileName);
293 //     } else {
294 //         char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
295 //
296 //         p = bufprint(temp, end, "%s"PATH_SEP"%s", rootPath, fileName);
297 //         if (p >= end) {
298 //             return NULL;
299 //         }
300 //         return ASTRDUP(temp);
301 //     }
302 // }
303 //
304 // /* check that a given directory contains a valid skin.
305 //  * returns 1 on success, 0 on failure.
306 //  */
307 // static int
308 // _checkSkinPath( const char*  skinPath )
309 // {
310 //     char  temp[MAX_PATH], *p=temp, *end=p+sizeof(temp);
311 //
312 //     /* for now, if it has a 'layout' file, it is a valid skin path */
313 //     p = bufprint(temp, end, "%s"PATH_SEP"layout", skinPath);
314 //     if (p >= end || !path_exists(temp))
315 //         return 0;
316 //
317 //     return 1;
318 // }
319 //
320 // /* Check that there is a skin named 'skinName' listed from 'skinDirRoot'
321 //  * this returns the full path of the skin directory (after alias expansions),
322 //  * including the skin name, or NULL on failure.
323 //  */
324 // static char*
325 // _checkSkinSkinsDir( const char*  skinDirRoot,
326 //                     const char*  skinName )
327 // {
328 //     DirScanner*  scanner;
329 //     char*        result;
330 //     char         temp[MAX_PATH], *p = temp, *end = p + sizeof(temp);
331 //
332 //     p = bufprint(temp, end, "%s"PATH_SEP"skins"PATH_SEP"%s", skinDirRoot, skinName);
333 //     DD("Probing skin directory: %s", temp);
334 //     if (p >= end || !path_exists(temp)) {
335 //         DD("    ignore bad skin directory %s", temp);
336 //         return NULL;
337 //     }
338 //
339 //     /* first, is this a normal skin directory ? */
340 //     if (_checkSkinPath(temp)) {
341 //         /* yes */
342 //         DD("    found skin directory: %s", temp);
343 //         return ASTRDUP(temp);
344 //     }
345 //
346 //     /* second, is it an alias to another skin ? */
347 //     *p      = 0;
348 //     result  = NULL;
349 //     scanner = dirScanner_new(temp);
350 //     if (scanner != NULL) {
351 //         for (;;) {
352 //             const char*  file = dirScanner_next(scanner);
353 //
354 //             if (file == NULL)
355 //                 break;
356 //
357 //             if (strncmp(file, "alias-", 6) || file[6] == 0)
358 //                 continue;
359 //
360 //             p = bufprint(temp, end, "%s"PATH_SEP"skins"PATH_SEP"%s", skinDirRoot, file+6);
361 //             if (p < end && _checkSkinPath(temp)) {
362 //                 /* yes, it's an alias */
363 //                 DD("    skin alias '%s' points to skin directory: %s",
364 //                    file+6, temp);
365 //                 result = ASTRDUP(temp);
366 //                 break;
367 //             }
368 //         }
369 //         dirScanner_free(scanner);
370 //     }
371 //     return result;
372 // }
373 //
374 // /* try to see if the skin name leads to a magic skin or skin path directly
375 //  * returns 1 on success, 0 on error.
376 //  *
377 //  * on success, this sets up '*pSkinName' and '*pSkinDir'
378 //  */
379 // static int
380 // _getSkinPathFromName( const char*  skinName,
381 //                       const char*  sdkRootPath,
382 //                       char**       pSkinName,
383 //                       char**       pSkinDir )
384 // {
385 //     char  temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
386 //
387 //     /* if the skin name has the format 'NNNNxNNN' where
388 //     * NNN is a decimal value, then this is a 'magic' skin
389 //     * name that doesn't require a skin directory
390 //     */
391 //     if (isdigit(skinName[0])) {
392 //         int  width, height;
393 //         if (sscanf(skinName, "%dx%d", &width, &height) == 2) {
394 //             D("'magic' skin format detected: %s", skinName);
395 //             *pSkinName = ASTRDUP(skinName);
396 //             *pSkinDir  = NULL;
397 //             return 1;
398 //         }
399 //     }
400 //
401 //     /* is the skin name a direct path to the skin directory ? */
402 //     if (path_is_absolute(skinName) && _checkSkinPath(skinName)) {
403 //         goto FOUND_IT;
404 //     }
405 //
406 //     /* is the skin name a relative path from the SDK root ? */
407 //     p = bufprint(temp, end, "%s"PATH_SEP"%s", sdkRootPath, skinName);
408 //     if (p < end && _checkSkinPath(temp)) {
409 //         skinName = temp;
410 //         goto FOUND_IT;
411 //     }
412 //
413 //     /* nope */
414 //     return 0;
415 //
416 // FOUND_IT:
417 //     if (path_split(skinName, pSkinDir, pSkinName) < 0) {
418 //         derror("malformed skin name: %s", skinName);
419 //         return 0;
420 //     }
421 //     D("found skin '%s' in directory: %s", *pSkinName, *pSkinDir);
422 //     return 1;
423 // }
424 //
425 // /***************************************************************
426 //  ***************************************************************
427 //  *****
428 //  *****    NORMAL VIRTUAL DEVICE SUPPORT
429 //  *****
430 //  *****/
431 //
432 // /* compute path to the root SDK directory
433 //  * assume we are in $SDKROOT/tools/emulator[.exe]
434 //  */
435 // static int
436 // _avdInfo_getSdkRoot( AvdInfo*  i )
437 // {
438 //
439 //     i->sdkRootPath = path_getSdkRoot();
440 //     if (i->sdkRootPath == NULL) {
441 //         derror("can't find SDK installation directory");
442 //         return -1;
443 //     }
444 //     return 0;
445 // }
446 //
447 // /* parse the root config .ini file. it is located in
448 //  * ~/.android/avd/<name>.ini or Windows equivalent
449 //  */
450 // static int
451 // _avdInfo_getRootIni( AvdInfo*  i )
452 // {
453 //     i->rootIniPath = path_getRootIniPath( i->deviceName );
454 //
455 //     if (i->rootIniPath == NULL) {
456 //         derror("unknown virtual device name: '%s'", i->deviceName);
457 //         return -1;
458 //     }
459 //
460 //     D("Android virtual device file at: %s", i->rootIniPath);
461 //
462 //     i->rootIni = iniFile_newFromFile(i->rootIniPath);
463 //
464 //     if (i->rootIni == NULL) {
465 //         derror("Corrupt virtual device config file!");
466 //         return -1;
467 //     }
468 //     return 0;
469 // }
470 //
471 // /* Returns the AVD's content path, i.e. the directory that contains
472 //  * the AVD's content files (e.g. data partition, cache, sd card, etc...).
473 //  *
474 //  * We extract this by parsing the root config .ini file, looking for
475 //  * a "path" elements.
476 //  */
477 // static int
478 // _avdInfo_getContentPath( AvdInfo*  i )
479 // {
480 //     if (i->inAndroidBuild && i->androidOut && i->contentPath) {
481 //         return 0;
482 //     }
483 //
484 //     char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
485 //
486 //     i->contentPath = iniFile_getString(i->rootIni, ROOT_ABS_PATH_KEY, NULL);
487 //
488 //     if (i->contentPath == NULL) {
489 //         derror("bad config: %s",
490 //                "virtual device file lacks a "ROOT_ABS_PATH_KEY" entry");
491 //         return -1;
492 //     }
493 //
494 //     if (!path_is_dir(i->contentPath)) {
495 //         // If the absolute path doesn't match an actual directory, try
496 //         // the relative path if present.
497 //         const char* relPath = iniFile_getString(i->rootIni, ROOT_REL_PATH_KEY, NULL);
498 //         if (relPath != NULL) {
499 //             p = bufprint_config_path(temp, end);
500 //             p = bufprint(p, end, PATH_SEP "%s", relPath);
501 //             if (p < end && path_is_dir(temp)) {
502 //                 str_reset(&i->contentPath, temp);
503 //             }
504 //         }
505 //     }
506 //
507 //     D("virtual device content at %s", i->contentPath);
508 //     return 0;
509 // }
510 //
511 // static int
512 // _avdInfo_getApiLevel(AvdInfo* i, bool* isMarshmallowOrHigher)
513 // {
514 //     char*       target;
515 //     const char* p;
516 //     const int   defaultLevel = kUnknownApiLevel;
517 //     int         level        = defaultLevel;
518 //
519 // #    define ROOT_TARGET_KEY   "target"
520 //
521 //     target = iniFile_getString(i->rootIni, ROOT_TARGET_KEY, NULL);
522 //     if (target == NULL) {
523 //         D("No target field in root AVD .ini file?");
524 //         D("Defaulting to API level %d", level);
525 //         return level;
526 //     }
527 //
528 //     DD("Found target field in root AVD .ini file: '%s'", target);
529 //
530 //     /* There are two acceptable formats for the target key.
531 //      *
532 //      * 1/  android-<level>
533 //      * 2/  <vendor-name>:<add-on-name>:<level>
534 //      *
535 //      * Where <level> can be either a _name_ (for experimental/preview SDK builds)
536 //      * or a decimal number. Note that if a _name_, it can start with a digit.
537 //      */
538 //
539 //     /* First, extract the level */
540 //     if (!memcmp(target, "android-", 8))
541 //         p = target + 8;
542 //     else {
543 //         /* skip two columns */
544 //         p = strchr(target, ':');
545 //         if (p != NULL) {
546 //             p = strchr(p+1, ':');
547 //             if (p != NULL)
548 //                 p += 1;
549 //         }
550 //     }
551 //     if (p == NULL || !isdigit(*p)) {
552 //         // preview versions usually have a single letter instead of the API
553 //         // level.
554 //         if (p && isalpha(p[0]) && p[1] == 0) {
555 //             level = avdInfo_getApiLevelFromLetter(p[0]);
556 //             if (level > 99 && toupper(p[0]) >= 'M') {
557 //                 *isMarshmallowOrHigher = true;
558 //             }
559 //         } else {
560 //             goto NOT_A_NUMBER;
561 //         }
562 //     } else {
563 //         char* end;
564 //         long  val = strtol(p, &end, 10);
565 //         if (end == NULL || *end != '\0' || val != (int)val) {
566 //             goto NOT_A_NUMBER;
567 //         }
568 //         level = (int)val;
569 //
570 //         /* Sanity check, we don't support anything prior to Android 1.5 */
571 //         if (level < 3)
572 //             level = 3;
573 //
574 //         D("Found AVD target API level: %d", level);
575 //     }
576 // EXIT:
577 //     AFREE(target);
578 //     return level;
579 //
580 // NOT_A_NUMBER:
581 //     if (p == NULL) {
582 //         D("Invalid target field in root AVD .ini file");
583 //     } else {
584 //         D("Target AVD api level is not a number");
585 //     }
586 //     D("Defaulting to API level %d", level);
587 //     goto EXIT;
588 // }
589 //
590 // bool
591 // avdInfo_isGoogleApis(const AvdInfo* i) {
592 //     return i->isGoogleApis;
593 // }
594 //
595 // bool
596 // avdInfo_isUserBuild(const AvdInfo* i) {
597 //     return i->isUserBuild;
598 // }
599 //
600 // AvdFlavor avdInfo_getAvdFlavor(const AvdInfo* i) {
601 //     return i->flavor;
602 // }
603 //
604 // int
605 // avdInfo_getApiLevel(const AvdInfo* i) {
606 //     return i->apiLevel;
607 // }
608 //
609 // // This information was taken from the SDK Manager:
610 // // Appearances & Behavior > System Settings > Android SDK > SDK Platforms
611 // static const struct {
612 //     int apiLevel;
613 //     const char* dessertName;
614 //     const char* fullName;
615 // } kApiLevelInfo[] = {
616 //     { 10, "Gingerbread", "2.3.3 (Gingerbread) - API 10 (Rev 2)" },
617 //     { 14, "Ice Cream Sandwich", "4.0 (Ice Cream Sandwich) - API 14 (Rev 4)" },
618 //     { 15, "Ice Cream Sandwich", "4.0.3 (Ice Cream Sandwich) - API 15 (Rev 5)" },
619 //     { 16, "Jelly Bean", "4.1 (Jelly Bean) - API 16 (Rev 5)" },
620 //     { 17, "Jelly Bean", "4.2 (Jelly Bean) - API 17 (Rev 3)" },
621 //     { 18, "Jelly Bean", "4.3 (Jelly Bean) - API 18 (Rev 3)" },
622 //     { 19, "KitKat", "4.4 (KitKat) - API 19 (Rev 4)" },
623 //     { 20, "KitKat", "4.4 (KitKat Wear) - API 20 (Rev 2)" },
624 //     { 21, "Lollipop", "5.0 (Lollipop) - API 21 (Rev 2)" },
625 //     { 22, "Lollipop", "5.1 (Lollipop) - API 22 (Rev 2)" },
626 //     { 23, "Marshmallow", "6.0 (Marshmallow) - API 23 (Rev 1)" },
627 //     { 24, "Nougat", "7.0 (Nougat) - API 24" },
628 //     { 25, "Nougat", "7.1 (Nougat) - API 25" },
629 //     { 26, "Oreo", "8.0 (Oreo) - API 26" },
630 //     { 27, "Oreo", "8.1 (Oreo) - API 27" },
631 //     { 28, "Pie", "9.0 (Pie) - API 28" },
632 //     { 29, "Q", "10.0 (Q) - API 29" },
633 //     { 30, "R", "11.0 (R) - API 30"}
634 // };
635 //
636 // const char* avdInfo_getApiDessertName(int apiLevel) {
637 //     int i = 0;
638 //     for (; i < ARRAY_SIZE(kApiLevelInfo); ++i) {
639 //         if (kApiLevelInfo[i].apiLevel == apiLevel) {
640 //             return kApiLevelInfo[i].dessertName;
641 //         }
642 //     }
643 //     return "";
644 // }
645 //
646 // void avdInfo_getFullApiName(int apiLevel, char* nameStr, int strLen) {
647 //     if (apiLevel < 0 || apiLevel > 99) {
648 //         strncpy(nameStr, "Unknown API version", strLen);
649 //         return;
650 //     }
651 //
652 //     int i = 0;
653 //     for (; i < ARRAY_SIZE(kApiLevelInfo); ++i) {
654 //         if (kApiLevelInfo[i].apiLevel == apiLevel) {
655 //             strncpy(nameStr, kApiLevelInfo[i].fullName, strLen);
656 //             return;
657 //         }
658 //     }
659 //     snprintf(nameStr, strLen, "API %d", apiLevel);
660 // }
661 //
662 // int avdInfo_getApiLevelFromLetter(char letter) {
663 //     const char letterUpper = toupper(letter);
664 //     int i = 0;
665 //     for (; i < ARRAY_SIZE(kApiLevelInfo); ++i) {
666 //         if (toupper(kApiLevelInfo[i].dessertName[0]) == letterUpper) {
667 //             return kApiLevelInfo[i].apiLevel;
668 //         }
669 //     }
670 //     return kUnknownApiLevel;
671 // }
672 //
673 // /* Look for a named file inside the AVD's content directory.
674 //  * Returns NULL if it doesn't exist, or a strdup() copy otherwise.
675 //  */
676 // static char*
677 // _avdInfo_getContentFilePath(const AvdInfo*  i, const char* fileName)
678 // {
679 //     char temp[MAX_PATH], *p = temp, *end = p + sizeof(temp);
680 //
681 //     p = bufprint(p, end, "%s"PATH_SEP"%s", i->contentPath, fileName);
682 //     if (p >= end) {
683 //         derror("can't access virtual device content directory");
684 //         return NULL;
685 //     }
686 //     if (!path_exists(temp)) {
687 //         return NULL;
688 //     }
689 //     return ASTRDUP(temp);
690 // }
691 //
692 // /* find and parse the config.ini file from the content directory */
693 // static int
694 // _avdInfo_getConfigIni(AvdInfo*  i)
695 // {
696 //     char*  iniPath = _avdInfo_getContentFilePath(i, CORE_CONFIG_INI);
697 //
698 //     /* Allow non-existing config.ini */
699 //     if (iniPath == NULL) {
700 //         D("virtual device has no config file - no problem");
701 //         return 0;
702 //     }
703 //
704 //     D("virtual device config file: %s", iniPath);
705 //     i->configIni = iniFile_newFromFile(iniPath);
706 //     AFREE(iniPath);
707 //
708 //     if (i->configIni == NULL) {
709 //         derror("bad config: %s",
710 //                "virtual device has corrupted " CORE_CONFIG_INI);
711 //         return -1;
712 //     }
713 //     return 0;
714 // }
715 //
716 // /* The AVD's config.ini contains a list of search paths (all beginning
717 //  * with SEARCH_PREFIX) which are directory locations searched for
718 //  * AVD platform files.
719 //  */
720 // static bool
721 // _avdInfo_getSearchPaths( AvdInfo*  i )
722 // {
723 //     if (i->configIni == NULL)
724 //         return true;
725 //
726 //     if (android_cmdLineOptions && android_cmdLineOptions->sysdir) {
727 //         // The user specified a path on the command line.
728 //         // Use only that.
729 //         i->numSearchPaths = 1;
730 //         i->searchPaths[0] = android_cmdLineOptions->sysdir;
731 //         DD("using one search path from the command line for this AVD");
732 //         return true;
733 //     }
734 //
735 //     i->numSearchPaths = _getSearchPaths( i->configIni,
736 //                                          i->sdkRootPath,
737 //                                          MAX_SEARCH_PATHS,
738 //                                          i->searchPaths );
739 //     if (i->numSearchPaths == 0) {
740 //         derror("no search paths found in this AVD's configuration.\n"
741 //                "Weird, the AVD's " CORE_CONFIG_INI " file is malformed. "
742 //                "Try re-creating it.\n");
743 //         return false;
744 //     }
745 //     else
746 //         DD("found a total of %d search paths for this AVD", i->numSearchPaths);
747 //     return true;
748 // }
749 //
750 // /* Search a file in the SDK search directories. Return NULL if not found,
751 //  * or a strdup() otherwise.
752 //  */
753 // static char*
754 // _avdInfo_getSdkFilePath(const AvdInfo*  i, const char*  fileName)
755 // {
756 //     char temp[MAX_PATH], *p = temp, *end = p + sizeof(temp);
757 //
758 //     do {
759 //         /* try the search paths */
760 //         int  nn;
761 //
762 //         for (nn = 0; nn < i->numSearchPaths; nn++) {
763 //             const char* searchDir = i->searchPaths[nn];
764 //
765 //             p = bufprint(temp, end, "%s"PATH_SEP"%s", searchDir, fileName);
766 //             if (p < end && path_exists(temp)) {
767 //                 DD("found %s in search dir: %s", fileName, searchDir);
768 //                 goto FOUND;
769 //             }
770 //             DD("    no %s in search dir: %s", fileName, searchDir);
771 //         }
772 //
773 //         return NULL;
774 //
775 //     } while (0);
776 //
777 // FOUND:
778 //     return ASTRDUP(temp);
779 // }
780 //
781 // /* Search for a file in the content directory, and if not found, in the
782 //  * SDK search directory. Returns NULL if not found.
783 //  */
784 // static char*
785 // _avdInfo_getContentOrSdkFilePath(const AvdInfo*  i, const char*  fileName)
786 // {
787 //     char*  path;
788 //
789 //     path = _avdInfo_getContentFilePath(i, fileName);
790 //     if (path)
791 //         return path;
792 //
793 //     path = _avdInfo_getSdkFilePath(i, fileName);
794 //     if (path)
795 //         return path;
796 //
797 //     return NULL;
798 // }
799 //
800 // #if 0
801 // static int
802 // _avdInfo_findContentOrSdkImage(const AvdInfo* i, AvdImageType id)
803 // {
804 //     const char* fileName = _imageFileNames[id];
805 //     char*       path     = _avdInfo_getContentOrSdkFilePath(i, fileName);
806 //
807 //     i->imagePath[id]  = path;
808 //     i->imageState[id] = IMAGE_STATE_READONLY;
809 //
810 //     if (path == NULL)
811 //         return -1;
812 //     else
813 //         return 0;
814 // }
815 // #endif
816 //
817 // /* Returns path to the core hardware .ini file. This contains the
818 //  * hardware configuration that is read by the core. The content of this
819 //  * file is auto-generated before launching a core, but we need to know
820 //  * its path before that.
821 //  */
822 // static int
823 // _avdInfo_getCoreHwIniPath( AvdInfo* i, const char* basePath )
824 // {
825 //     i->coreHardwareIniPath = _getFullFilePath(basePath, CORE_HARDWARE_INI);
826 //     if (i->coreHardwareIniPath == NULL) {
827 //         DD("Path too long for %s: %s", CORE_HARDWARE_INI, basePath);
828 //         return -1;
829 //     }
830 //     D("using core hw config path: %s", i->coreHardwareIniPath);
831 //     return 0;
832 // }
833 //
834 // static int
835 // _avdInfo_getSnapshotLockFilePath( AvdInfo* i, const char* basePath )
836 // {
837 //     i->snapshotLockPath = _getFullFilePath(basePath, SNAPSHOT_LOCK);
838 //     if (i->snapshotLockPath == NULL) {
839 //         DD("Path too long for %s: %s", SNAPSHOT_LOCK, basePath);
840 //         return -1;
841 //     }
842 //     D("using snapshot lock path: %s", i->snapshotLockPath);
843 //     return 0;
844 // }
845 //
846 // static int
847 // _avdInfo_getMultiInstanceLockFilePath( AvdInfo* i, const char* basePath )
848 // {
849 //     i->multiInstanceLockPath = _getFullFilePath(basePath, MULTIINSTANCE_LOCK);
850 //     if (i->multiInstanceLockPath == NULL) {
851 //         DD("Path too long for %s: %s", MULTIINSTANCE_LOCK, basePath);
852 //         return -1;
853 //     }
854 //     D("using multi-instance lock path: %s", i->multiInstanceLockPath);
855 //     return 0;
856 // }
857 //
858 // static void
859 // _avdInfo_readPropertyFile(const AvdInfo* i,
860 //                           const char* filePath,
861 //                           FileData* data) {
862 //     int ret = fileData_initFromFile(data, filePath);
863 //     if (ret < 0) {
864 //         D("Error reading property file %s: %s", filePath, strerror(-ret));
865 //     } else {
866 //         D("Read property file at %s", filePath);
867 //     }
868 // }
869 //
870 // static void
871 // _avdInfo_extractBuildProperties(AvdInfo* i) {
872 //     i->targetArch = propertyFile_getTargetArch(i->buildProperties);
873 //     if (!i->targetArch) {
874 //         str_reset(&i->targetArch, "arm");
875 //         D("Cannot find target CPU architecture, defaulting to '%s'",
876 //           i->targetArch);
877 //     }
878 //     i->targetAbi = propertyFile_getTargetAbi(i->buildProperties);
879 //     if (!i->targetAbi) {
880 //         str_reset(&i->targetAbi, "armeabi");
881 //         D("Cannot find target CPU ABI, defaulting to '%s'",
882 //           i->targetAbi);
883 //     }
884 //     if (!i->apiLevel) {
885 //         // Note: for regular AVDs, the API level is already extracted
886 //         // from config.ini, besides, for older SDK platform images,
887 //         // there is no build.prop file and the following function
888 //         // would always return 1000, making the AVD unbootable!.
889 //         i->apiLevel = propertyFile_getApiLevel(i->buildProperties);
890 //         if (i->apiLevel < 3) {
891 //             i->apiLevel = 3;
892 //             D("Cannot find target API level, defaulting to %d",
893 //             i->apiLevel);
894 //         }
895 //     }
896 //
897 //     i->flavor = propertyFile_getAvdFlavor(i->buildProperties);
898 //
899 //     i->isGoogleApis = propertyFile_isGoogleApis(i->buildProperties);
900 //     i->isUserBuild = propertyFile_isUserBuild(i->buildProperties);
901 //     i->incrementalVersion = propertyFile_getInt(
902 //         i->buildProperties,
903 //         "ro.build.version.incremental",
904 //         -1,
905 //         NULL);
906 // }
907 //
908 //
909 // static void
910 // _avdInfo_getPropertyFile(AvdInfo* i,
911 //                          const char* propFileName,
912 //                          FileData* data ) {
913 //     char* filePath = _avdInfo_getContentOrSdkFilePath(i, propFileName);
914 //     if (!filePath) {
915 //         D("No %s property file found.", propFileName);
916 //         return;
917 //     }
918 //
919 //     _avdInfo_readPropertyFile(i, filePath, data);
920 //     free(filePath);
921 // }
922 //
923 // AvdInfo*
924 // avdInfo_new( const char*  name, AvdInfoParams*  params )
925 // {
926 //     AvdInfo*  i;
927 //
928 //     if (name == NULL)
929 //         return NULL;
930 //
931 //     if (!_checkAvdName(name)) {
932 //         derror("virtual device name contains invalid characters");
933 //         return NULL;
934 //     }
935 //
936 //     ANEW0(i);
937 //     str_reset(&i->deviceName, name);
938 //     str_reset(&i->deviceId, name);
939 //     i->noChecks = false;
940 //
941 //     if ( _avdInfo_getSdkRoot(i) < 0     ||
942 //          _avdInfo_getRootIni(i) < 0     ||
943 //          _avdInfo_getContentPath(i) < 0 ||
944 //          _avdInfo_getConfigIni(i)   < 0 ||
945 //          _avdInfo_getCoreHwIniPath(i, i->contentPath) < 0 ||
946 //          _avdInfo_getSnapshotLockFilePath(i, i->contentPath) < 0 ||
947 //          _avdInfo_getMultiInstanceLockFilePath(i, i->contentPath) < 0)
948 //         goto FAIL;
949 //
950 //     i->apiLevel = _avdInfo_getApiLevel(i, &i->isMarshmallowOrHigher);
951 //
952 //     /* look for image search paths. handle post 1.1/pre cupcake
953 //      * obsolete SDKs.
954 //      */
955 //     if (!_avdInfo_getSearchPaths(i)) {
956 //         goto FAIL;
957 //     }
958 //
959 //     // Find the build.prop and boot.prop files and read them.
960 //     _avdInfo_getPropertyFile(i, "build.prop", i->buildProperties);
961 //     _avdInfo_getPropertyFile(i, "boot.prop", i->bootProperties);
962 //
963 //     _avdInfo_extractBuildProperties(i);
964 //
965 //     /* don't need this anymore */
966 //     iniFile_free(i->rootIni);
967 //     i->rootIni = NULL;
968 //
969 //     return i;
970 //
971 // FAIL:
972 //     avdInfo_free(i);
973 //     return NULL;
974 // }
975 //
976 // void avdInfo_setAvdId( AvdInfo* i, const char* avdId)
977 // {
978 //     if (i == NULL) return;
979 //
980 //     str_reset(&i->deviceId, avdId);
981 // }
982 //
983 // /***************************************************************
984 //  ***************************************************************
985 //  *****
986 //  *****    ANDROID BUILD SUPPORT
987 //  *****
988 //  *****    The code below corresponds to the case where we're
989 //  *****    starting the emulator inside the Android build
990 //  *****    system. The main differences are that:
991 //  *****
992 //  *****    - the $ANDROID_PRODUCT_OUT directory is used as the
993 //  *****      content file.
994 //  *****
995 //  *****    - built images must not be modified by the emulator,
996 //  *****      so system.img must be copied to a temporary file
997 //  *****      and userdata.img must be copied to userdata-qemu.img
998 //  *****      if the latter doesn't exist.
999 //  *****
1000 //  *****    - the kernel and default skin directory are taken from
1001 //  *****      prebuilt
1002 //  *****
1003 //  *****    - there is no root .ini file, or any config.ini in
1004 //  *****      the content directory, no SDK images search path.
1005 //  *****/
1006 //
1007 // /* Read a hardware.ini if it is located in the skin directory */
1008 // static int
1009 // _avdInfo_getBuildSkinHardwareIni( AvdInfo*  i )
1010 // {
1011 //     char* skinName;
1012 //     char* skinDirPath;
1013 //
1014 //     avdInfo_getSkinInfo(i, &skinName, &skinDirPath);
1015 //     if (skinDirPath == NULL)
1016 //         return 0;
1017 //
1018 //     int result = avdInfo_getSkinHardwareIni(i, skinName, skinDirPath);
1019 //
1020 //     AFREE(skinName);
1021 //     AFREE(skinDirPath);
1022 //
1023 //     return result;
1024 // }
1025 //
1026 // int avdInfo_getSkinHardwareIni( AvdInfo* i, char* skinName, char* skinDirPath)
1027 // {
1028 //     char  temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
1029 //
1030 //     p = bufprint(temp, end, "%s"PATH_SEP"%s"PATH_SEP"hardware.ini", skinDirPath, skinName);
1031 //     if (p >= end || !path_exists(temp)) {
1032 //         DD("no skin-specific hardware.ini in %s", skinDirPath);
1033 //         return 0;
1034 //     }
1035 //
1036 //     D("found skin-specific hardware.ini: %s", temp);
1037 //     if (i->skinHardwareIni != NULL)
1038 //         iniFile_free(i->skinHardwareIni);
1039 //     i->skinHardwareIni = iniFile_newFromFile(temp);
1040 //     if (i->skinHardwareIni == NULL)
1041 //         return -1;
1042 //
1043 //     return 0;
1044 // }
1045 //
1046 // AvdInfo*
1047 // avdInfo_newForAndroidBuild( const char*     androidBuildRoot,
1048 //                             const char*     androidOut,
1049 //                             AvdInfoParams*  params )
1050 // {
1051 //     AvdInfo*  i;
1052 //
1053 //     ANEW0(i);
1054 //
1055 //     i->inAndroidBuild   = 1;
1056 //     str_reset(&i->androidBuildRoot, androidBuildRoot);
1057 //     str_reset(&i->androidOut, androidOut);
1058 //     str_reset(&i->contentPath, androidOut);
1059 //
1060 //     // Find the build.prop file and read it.
1061 //     char* buildPropPath = path_getBuildBuildProp(i->androidOut);
1062 //     if (buildPropPath) {
1063 //         _avdInfo_readPropertyFile(i, buildPropPath, i->buildProperties);
1064 //         free(buildPropPath);
1065 //     }
1066 //
1067 //     // FInd the boot.prop file and read it.
1068 //     char* bootPropPath = path_getBuildBootProp(i->androidOut);
1069 //     if (bootPropPath) {
1070 //         _avdInfo_readPropertyFile(i, bootPropPath, i->bootProperties);
1071 //         free(bootPropPath);
1072 //     }
1073 //
1074 //     _avdInfo_extractBuildProperties(i);
1075 //
1076 //     str_reset(&i->deviceName, "<build>");
1077 //     str_reset(&i->deviceId, "<build>");
1078 //
1079 //     i->numSearchPaths = 1;
1080 //     i->searchPaths[0] = strdup(androidOut);
1081 //     /* out/target/product/<name>/config.ini, if exists, provide configuration
1082 //      * from build files. */
1083 //     if (_avdInfo_getConfigIni(i) < 0 ||
1084 //         _avdInfo_getCoreHwIniPath(i, i->androidOut) < 0 ||
1085 //         _avdInfo_getSnapshotLockFilePath(i, i->androidOut) < 0 ||
1086 //         _avdInfo_getMultiInstanceLockFilePath(i, i->androidOut) < 0)
1087 //         goto FAIL;
1088 //
1089 //     /* Read the build skin's hardware.ini, if any */
1090 //     _avdInfo_getBuildSkinHardwareIni(i);
1091 //
1092 //     return i;
1093 //
1094 // FAIL:
1095 //     avdInfo_free(i);
1096 //     return NULL;
1097 // }
1098 //
1099 // const char*
1100 // avdInfo_getName( const AvdInfo*  i )
1101 // {
1102 //     return i ? i->deviceName : NULL;
1103 // }
1104 //
1105 // const char*
1106 // avdInfo_getId( const AvdInfo*  i )
1107 // {
1108 //     return i ? i->deviceId : NULL;
1109 // }
1110 //
1111 // const char*
1112 // avdInfo_getImageFile( const AvdInfo*  i, AvdImageType  imageType )
1113 // {
1114 //     if (i == NULL || (unsigned)imageType >= AVD_IMAGE_MAX)
1115 //         return NULL;
1116 //
1117 //     return i->imagePath[imageType];
1118 // }
1119 //
1120 // uint64_t
1121 // avdInfo_getImageFileSize( const AvdInfo*  i, AvdImageType  imageType )
1122 // {
1123 //     const char* file = avdInfo_getImageFile(i, imageType);
1124 //     uint64_t    size;
1125 //
1126 //     if (file == NULL)
1127 //         return 0ULL;
1128 //
1129 //     if (path_get_size(file, &size) < 0)
1130 //         return 0ULL;
1131 //
1132 //     return size;
1133 // }
1134 //
1135 // int
1136 // avdInfo_isImageReadOnly( const AvdInfo*  i, AvdImageType  imageType )
1137 // {
1138 //     if (i == NULL || (unsigned)imageType >= AVD_IMAGE_MAX)
1139 //         return 1;
1140 //
1141 //     return (i->imageState[imageType] == IMAGE_STATE_READONLY);
1142 // }
1143 //
1144 // char*
1145 // avdInfo_getKernelPath( const AvdInfo*  i )
1146 // {
1147 //     const char* imageName = _imageFileNames[ AVD_IMAGE_KERNEL ];
1148 //
1149 //     char*  kernelPath = _avdInfo_getContentOrSdkFilePath(i, imageName);
1150 //
1151 //     do {
1152 //         if (kernelPath || !i->inAndroidBuild)
1153 //             break;
1154 //
1155 //         /* When in the Android build, look into the prebuilt directory
1156 //          * for our target architecture.
1157 //          */
1158 //         char temp[PATH_MAX], *p = temp, *end = p + sizeof(temp);
1159 //         const char* suffix = "";
1160 //
1161 //         // If the target ABI is armeabi-v7a, then look for
1162 //         // kernel-qemu-armv7 instead of kernel-qemu in the prebuilt
1163 //         // directory.
1164 //         if (!strcmp(i->targetAbi, "armeabi-v7a")) {
1165 //             suffix = "-armv7";
1166 //         }
1167 //
1168 //         p = bufprint(temp, end, "%s"PATH_SEP"kernel", i->androidOut);
1169 //         if (p < end && path_exists(temp)) {
1170 //             str_reset(&kernelPath, temp);
1171 //             break;
1172 //         }
1173 //
1174 //         p = bufprint(temp, end, "%s"PATH_SEP"prebuilts"PATH_SEP"qemu-kernel"PATH_SEP"%s"PATH_SEP"kernel-qemu%s",
1175 //                      i->androidBuildRoot, i->targetArch, suffix);
1176 //         if (p >= end || !path_exists(temp)) {
1177 //             derror("bad workspace: cannot find prebuilt kernel in: %s", temp);
1178 //             kernelPath = NULL;
1179 //             break;
1180 //         }
1181 //         str_reset(&kernelPath, temp);
1182 //
1183 //     } while (0);
1184 //
1185 //     return kernelPath;
1186 // }
1187 //
1188 // char*
1189 // avdInfo_getRanchuKernelPath( const AvdInfo*  i )
1190 // {
1191 //     const char* imageName = _imageFileNames[ AVD_IMAGE_KERNELRANCHU64 ];
1192 //     char*  kernelPath = _avdInfo_getContentOrSdkFilePath(i, imageName);
1193 //     if (kernelPath) {
1194 //         return kernelPath;
1195 //     }
1196 //
1197 //     imageName = _imageFileNames[ AVD_IMAGE_KERNELRANCHU ];
1198 //     kernelPath = _avdInfo_getContentOrSdkFilePath(i, imageName);
1199 //
1200 //     //old flow, checks the prebuilds/qemu-kernel, ignore //32bit-image-on-64bit scenario:
1201 //     //the build process should have a copy of kernel-ranchu/kernel-ranchu-64 in the
1202 //     //android out already,and will be handled by _avdInfo_getContentOrSdkFilePath()
1203 //     do {
1204 //         if (kernelPath || !i->inAndroidBuild)
1205 //             break;
1206 //
1207 //         /* When in the Android build, look into the prebuilt directory
1208 //          * for our target architecture.
1209 //          */
1210 //         char temp[PATH_MAX], *p = temp, *end = p + sizeof(temp);
1211 //         const char* suffix = "";
1212 //
1213 //         /* mips/ranchu holds distinct images for mips & mips32[r5|r6] */
1214 //         if (!strcmp(i->targetAbi, "mips32r6")) {
1215 //             suffix = "-mips32r6";
1216 //         } else if (!strcmp(i->targetAbi, "mips32r5")) {
1217 //             suffix = "-mips32r5";
1218 //         }
1219 //
1220 //         p = bufprint(temp, end, "%s"PATH_SEP"prebuilts"PATH_SEP"qemu-kernel"PATH_SEP"%s"PATH_SEP"ranchu"PATH_SEP"kernel-qemu%s",
1221 //                      i->androidBuildRoot, i->targetArch, suffix);
1222 //         if (p >= end || !path_exists(temp)) {
1223 //             /* arm64 and mips64 are special: their kernel-qemu is actually kernel-ranchu */
1224 //             if (!strcmp(i->targetArch, "arm64") || !strcmp(i->targetArch, "mips64")) {
1225 //                 return avdInfo_getKernelPath(i);
1226 //             } else {
1227 //                 derror("bad workspace: cannot find prebuilt ranchu kernel in: %s", temp);
1228 //                 kernelPath = NULL;
1229 //                 break;
1230 //             }
1231 //         }
1232 //         str_reset(&kernelPath, temp);
1233 //     } while (0);
1234 //
1235 //     return kernelPath;
1236 // }
1237 //
1238 //
1239 // char*
1240 // avdInfo_getRamdiskPath( const AvdInfo* i )
1241 // {
1242 //     const char* userImageName = _imageFileNames[ AVD_IMAGE_USERRAMDISK ];
1243 //     char* result = _avdInfo_getContentOrSdkFilePath(i, userImageName);
1244 //     if (result) return result;
1245 //
1246 //     const char* imageName = _imageFileNames[ AVD_IMAGE_RAMDISK ];
1247 //     return _avdInfo_getContentOrSdkFilePath(i, imageName);
1248 // }
1249 //
1250 // char*  avdInfo_getCachePath( const AvdInfo*  i )
1251 // {
1252 //     const char* imageName = _imageFileNames[ AVD_IMAGE_CACHE ];
1253 //     return _avdInfo_getContentFilePath(i, imageName);
1254 // }
1255 //
1256 // char*  avdInfo_getDefaultCachePath( const AvdInfo*  i )
1257 // {
1258 //     const char* imageName = _imageFileNames[ AVD_IMAGE_CACHE ];
1259 //     return _getFullFilePath(i->contentPath, imageName);
1260 // }
1261 //
1262 // char*  avdInfo_getSdCardPath( const AvdInfo* i )
1263 // {
1264 //     const char* imageName = _imageFileNames[ AVD_IMAGE_SDCARD ];
1265 //     char*       path;
1266 //
1267 //     /* Special case, the config.ini can have a SDCARD_PATH entry
1268 //      * that gives the full path to the SD Card.
1269 //      */
1270 //     if (i->configIni != NULL) {
1271 //         path = iniFile_getString(i->configIni, SDCARD_PATH, NULL);
1272 //         if (path != NULL) {
1273 //             if (path_exists(path))
1274 //                 return path;
1275 //
1276 //             dwarning("Ignoring invalid SDCard path: %s", path);
1277 //             AFREE(path);
1278 //         }
1279 //     }
1280 //
1281 //     if (i->imagePath[ AVD_IMAGE_SDCARD ] != NULL) {
1282 //         path = ASTRDUP(i->imagePath[ AVD_IMAGE_SDCARD ]);
1283 //         if (path_exists(path))
1284 //             return path;
1285 //
1286 //         dwarning("Ignoring invalid SDCard path: %s", path);
1287 //         AFREE(path);
1288 //     }
1289 //
1290 //     /* Otherwise, simply look into the content directory */
1291 //     return _avdInfo_getContentFilePath(i, imageName);
1292 // }
1293 //
1294 // char* avdInfo_getEncryptionKeyImagePath(const AvdInfo* i )
1295 // {
1296 //     const char* imageName = _imageFileNames[ AVD_IMAGE_ENCRYPTIONKEY ];
1297 //     return _avdInfo_getContentFilePath(i, imageName);
1298 // }
1299 //
1300 // char*
1301 // avdInfo_getSnapStoragePath( const AvdInfo* i )
1302 // {
1303 //     const char* imageName = _imageFileNames[ AVD_IMAGE_SNAPSHOTS ];
1304 //     return _avdInfo_getContentFilePath(i, imageName);
1305 // }
1306 //
1307 // char*
1308 // avdInfo_getSystemImagePath( const AvdInfo*  i )
1309 // {
1310 //     const char* imageName = _imageFileNames[ AVD_IMAGE_USERSYSTEM ];
1311 //     return _avdInfo_getContentFilePath(i, imageName);
1312 // }
1313 //
1314 // char*
1315 // avdInfo_getVerifiedBootParamsPath( const AvdInfo*  i )
1316 // {
1317 //     const char* imageName = _imageFileNames[ AVD_IMAGE_VERIFIEDBOOTPARAMS ];
1318 //     return _avdInfo_getContentOrSdkFilePath(i, imageName);
1319 // }
1320 //
1321 // char*
1322 // avdInfo_getSystemInitImagePath( const AvdInfo*  i )
1323 // {
1324 //     const char* imageName = _imageFileNames[ AVD_IMAGE_INITSYSTEM ];
1325 //     return _avdInfo_getContentOrSdkFilePath(i, imageName);
1326 // }
1327 //
1328 // char*
1329 // avdInfo_getVendorImagePath( const AvdInfo*  i )
1330 // {
1331 //     const char* imageName = _imageFileNames[ AVD_IMAGE_USERVENDOR ];
1332 //     return _avdInfo_getContentFilePath(i, imageName);
1333 // }
1334 //
1335 // char*
1336 // avdInfo_getVendorInitImagePath( const AvdInfo*  i )
1337 // {
1338 //     const char* imageName = _imageFileNames[ AVD_IMAGE_INITVENDOR ];
1339 //     return _avdInfo_getContentOrSdkFilePath(i, imageName);
1340 // }
1341 //
1342 // static bool
1343 // is_x86ish(const AvdInfo* i)
1344 // {
1345 //     if (strncmp(i->targetAbi, "x86", 3) == 0) {
1346 //         return true;
1347 //     } else {
1348 //         return false;
1349 //     }
1350 // }
1351 //
1352 // static bool
1353 // is_armish(const AvdInfo* i)
1354 // {
1355 //     if (strncmp(i->targetAbi, "arm", 3) == 0) {
1356 //         return true;
1357 //     } else {
1358 //         return false;
1359 //     }
1360 // }
1361 //
1362 // static bool
1363 // is_mipsish(const AvdInfo* i)
1364 // {
1365 //     if (strncmp(i->targetAbi, "mips", 4) == 0) {
1366 //         return true;
1367 //     } else {
1368 //         return false;
1369 //     }
1370 // }
1371 //
1372 // /*
1373 //     arm is pretty tricky: the system image device path
1374 //     changes depending on the number of disks: the last
1375 //     one seems always a003e00, we need to know how many
1376 //     devices it actually has
1377 // */
1378 // const char* const arm_device_id[] = {
1379 //     "a003e00",
1380 //     "a003c00",
1381 //     "a003a00",
1382 //     "a003800",
1383 //     "a003600",
1384 //     "a003400",
1385 // };
1386 //
1387 // const char* const mips_device_id[] = {
1388 //     "1f03d000",
1389 //     "1f03d200",
1390 //     "1f03d400",
1391 //     "1f03d600",
1392 //     "1f03d800",
1393 // };
1394 //
1395 // static
1396 // bool has_sdcard(const AvdInfo* i) {
1397 //     char* path = avdInfo_getSdCardPath(i);
1398 //     if (path) {
1399 //         free(path);
1400 //         return true;
1401 //     }
1402 //     return false;
1403 // }
1404 //
1405 // static
1406 // bool has_vendor(const AvdInfo* i) {
1407 //     char* path = avdInfo_getVendorInitImagePath(i);
1408 //     if (path) {
1409 //         free(path);
1410 //         return true;
1411 //     }
1412 //     path = avdInfo_getVendorImagePath(i);
1413 //     if (path) {
1414 //         free(path);
1415 //         return true;
1416 //     }
1417 //     return false;
1418 // }
1419 //
1420 // static
1421 // bool has_encryption(const AvdInfo* i) {
1422 //     char* path = avdInfo_getEncryptionKeyImagePath(i);
1423 //     if (path) {
1424 //         free(path);
1425 //         return true;
1426 //     }
1427 //     return false;
1428 // }
1429 //
1430 //
1431 // static
1432 // char* get_device_path(const AvdInfo* info, const char* image)
1433 // {
1434 //     const char* device_table[6] = {"", "","" ,"" ,"" , ""};
1435 //     int i = 0;
1436 //     if (has_sdcard(info)) {
1437 //         device_table[i++] = "sdcard";
1438 //     }
1439 //     if (has_vendor(info)) {
1440 //         device_table[i++] = "vendor";
1441 //     }
1442 //     if (has_encryption(info)) {
1443 //         device_table[i++] = "encryption";
1444 //     }
1445 //     device_table[i++] = "userdata";
1446 //     device_table[i++] = "cache";
1447 //     device_table[i++] = "system";
1448 //     int count = ARRAY_SIZE(device_table);
1449 //     for ( i=0; i < count; ++i) {
1450 //         if (strcmp(image, device_table[i]) ==0) {
1451 //             break;
1452 //         }
1453 //     }
1454 //     if (i == count) {
1455 //         return NULL;
1456 //     }
1457 //     char buf[1024];
1458 //
1459 //     if (is_armish(info)) {
1460 //         snprintf(buf, sizeof(buf), "/dev/block/platform/%s.virtio_mmio/by-name/%s",
1461 //                 arm_device_id[i], image);
1462 //     } else if (is_mipsish(info)) {
1463 //         snprintf(buf, sizeof(buf), "/dev/block/platform/%s.virtio_mmio/by-name/%s",
1464 //                 mips_device_id[i], image);
1465 //     }
1466 //     return strdup(buf);
1467 // }
1468 //
1469 // char*
1470 // avdInfo_getVendorImageDevicePathInGuest( const AvdInfo*  i )
1471 // {
1472 //     if (!has_vendor(i)) {
1473 //         return NULL;
1474 //     }
1475 //
1476 //     if (is_x86ish(i)) {
1477 //         if (has_encryption(i)) {
1478 //             return strdup("/dev/block/pci/pci0000:00/0000:00:07.0/by-name/vendor");
1479 //         } else {
1480 //             return strdup("/dev/block/pci/pci0000:00/0000:00:06.0/by-name/vendor");
1481 //         }
1482 //     } else {
1483 //         return get_device_path(i, "vendor");
1484 //     }
1485 //     return NULL;
1486 // }
1487 //
1488 // char*
1489 // avdInfo_getDynamicPartitionBootDevice( const AvdInfo*  i )
1490 // {
1491 //     if (is_x86ish(i)) {
1492 //         return strdup("pci0000:00/0000:00:03.0");
1493 //     }
1494 //
1495 //     char* system_path = get_device_path(i, "system");
1496 //     if (!system_path) {
1497 //         return NULL;
1498 //     }
1499 //
1500 //     char* bootdev = strdup(system_path + strlen("/dev/block/platform/"));
1501 //     char* end = strstr(bootdev, "/by-name/system");
1502 //     *end = '\0';
1503 //     return bootdev;
1504 // }
1505 //
1506 // char*
1507 // avdInfo_getSystemImageDevicePathInGuest( const AvdInfo*  i )
1508 // {
1509 //     if (feature_is_enabled(kFeature_SystemAsRoot)) {
1510 //         return NULL;
1511 //     }
1512 //     if (is_x86ish(i)) {
1513 //         return strdup("/dev/block/pci/pci0000:00/0000:00:03.0/by-name/system");
1514 //     } else {
1515 //         return get_device_path(i, "system");
1516 //     }
1517 // }
1518 //
1519 // char*
1520 // avdInfo_getDataImagePath( const AvdInfo*  i )
1521 // {
1522 //     const char* imageName = _imageFileNames[ AVD_IMAGE_USERDATA ];
1523 //     return _avdInfo_getContentFilePath(i, imageName);
1524 // }
1525 //
1526 // char*
1527 // avdInfo_getDefaultDataImagePath( const AvdInfo*  i )
1528 // {
1529 //     const char* imageName = _imageFileNames[ AVD_IMAGE_USERDATA ];
1530 //     return _getFullFilePath(i->contentPath, imageName);
1531 // }
1532 //
1533 // char* avdInfo_getDefaultSystemFeatureControlPath(const AvdInfo* i) {
1534 //     char* retVal = _avdInfo_getSdkFilePath(i, "advancedFeatures.ini");
1535 //     return retVal;
1536 // }
1537 //
1538 // char* avdInfo_getDataInitImagePath(const AvdInfo* i) {
1539 //     const char* imageName = _imageFileNames[ AVD_IMAGE_INITDATA ];
1540 //     return _avdInfo_getContentOrSdkFilePath(i, imageName);
1541 // }
1542 //
1543 // char* avdInfo_getDataInitDirPath(const AvdInfo* i) {
1544 //     const char* imageName = _imageFileNames[ AVD_IMAGE_INITZIP ];
1545 //     return _avdInfo_getSdkFilePath(i, imageName);
1546 // }
1547 //
1548 // int
1549 // avdInfo_initHwConfig(const AvdInfo* i, AndroidHwConfig*  hw, bool isQemu2)
1550 // {
1551 //     int  ret = 0;
1552 //
1553 //     androidHwConfig_init(hw, i->apiLevel);
1554 //
1555 //     /* First read the skin's hardware.ini, if any */
1556 //     if (i->skinHardwareIni != NULL) {
1557 //         ret = androidHwConfig_read(hw, i->skinHardwareIni);
1558 //     }
1559 //
1560 //     /* The device's config.ini can override the skin's values
1561 //      * (which is preferable to the opposite order)
1562 //      */
1563 //     if (ret == 0 && i->configIni != NULL) {
1564 //         ret = androidHwConfig_read(hw, i->configIni);
1565 //         /* We will set hw.arc in avd manager when creating new avd.
1566 //          * Before new avd manager released, we check tag.id to see
1567 //          * if it's a Chrome OS image.
1568 //          */
1569 //         if (ret == 0 && !hw->hw_arc) {
1570 //             char *tag = iniFile_getString(i->configIni, TAG_ID, "default");
1571 //             if (!strcmp(tag, TAG_ID_CHROMEOS)) {
1572 //                 hw->hw_arc = true;
1573 //             }
1574 //             AFREE(tag);
1575 //         }
1576 //     }
1577 //
1578 //     /* Auto-disable keyboard emulation on sapphire platform builds */
1579 //     if (i->androidOut != NULL) {
1580 //         char*  p = strrchr(i->androidOut, *PATH_SEP);
1581 //         if (p != NULL && !strcmp(p,"sapphire")) {
1582 //             hw->hw_keyboard = 0;
1583 //         }
1584 //     }
1585 //
1586 //     // for api <= 10 there is no multi-touch support in any of the ranchu
1587 //     // or goldfish kernels and GUI won't respond as a result;
1588 //     // force it to be "touch"
1589 //     //
1590 //     // for api <= 21 the goldfish kernel is not updated to
1591 //     // support multi-touch yet; so just force touch
1592 //     // bug: https://code.google.com/p/android/issues/detail?id=199289
1593 //     //
1594 //     // System images above 10 support multi-touch if they have a ranchu kernel
1595 //     // and we're using QEMU2 as indicated by the isQemu2 flag.
1596 //     //
1597 //     // TODO: There is currently an issue related to this to track the release of
1598 //     // system images with ranchu kernels for API 21 and below at:
1599 //     // https://code.google.com/p/android/issues/detail?id=200332
1600 //     if (i->apiLevel <= 10 || (!isQemu2 && i->apiLevel <= 21)) {
1601 //             str_reset(&hw->hw_screen, "touch");
1602 //     }
1603 //
1604 //     if (hw->hw_arc) {
1605 //         // Chrome OS GPU acceleration is not perfect now, disable it
1606 //         // in "default" mode, it still can be enabled with explicit
1607 //         // setting.
1608 //         if (hw->hw_gpu_mode == NULL || !strcmp(hw->hw_gpu_mode, "auto"))
1609 //             str_reset(&hw->hw_gpu_mode, "off");
1610 //         str_reset(&hw->hw_cpu_arch, "x86_64");
1611 //     }
1612 //
1613 //     return ret;
1614 // }
1615 //
1616 // void
1617 // avdInfo_setImageFile( AvdInfo*  i, AvdImageType  imageType,
1618 //                       const char*  imagePath )
1619 // {
1620 //     assert(i != NULL && (unsigned)imageType < AVD_IMAGE_MAX);
1621 //
1622 //     i->imagePath[imageType] = ASTRDUP(imagePath);
1623 // }
1624 //
1625 // void
1626 // avdInfo_setAcpiIniPath( AvdInfo* i, const char* iniPath )
1627 // {
1628 //     assert(i != NULL);
1629 //
1630 //     i->acpiIniPath = ASTRDUP(iniPath);
1631 // }
1632 // const char*
1633 // avdInfo_getContentPath( const AvdInfo*  i )
1634 // {
1635 //     return i->contentPath;
1636 // }
1637 //
1638 // const char*
1639 // avdInfo_getRootIniPath( const AvdInfo*  i )
1640 // {
1641 //     return i->rootIniPath;
1642 // }
1643 //
1644 // const char*
1645 // avdInfo_getAcpiIniPath( const AvdInfo* i )
1646 // {
1647 //     return i->acpiIniPath;
1648 // }
1649 //
1650 // int
1651 // avdInfo_inAndroidBuild( const AvdInfo*  i )
1652 // {
1653 //     return i->inAndroidBuild;
1654 // }
1655 //
1656 // char*
1657 // avdInfo_getTargetCpuArch(const AvdInfo* i) {
1658 //     return ASTRDUP(i->targetArch);
1659 // }
1660 //
1661 // char*
1662 // avdInfo_getTargetAbi( const AvdInfo* i )
1663 // {
1664 //     /* For now, we can't get the ABI from SDK AVDs */
1665 //     return ASTRDUP(i->targetAbi);
1666 // }
1667 //
1668 // bool avdInfo_is_x86ish(const AvdInfo* i)
1669 // {
1670 //     return is_x86ish(i);
1671 // }
1672 //
1673 // char*
1674 // avdInfo_getCodeProfilePath( const AvdInfo*  i, const char*  profileName )
1675 // {
1676 //     char   tmp[MAX_PATH], *p=tmp, *end=p + sizeof(tmp);
1677 //
1678 //     if (i == NULL || profileName == NULL || profileName[0] == 0)
1679 //         return NULL;
1680 //
1681 //     if (i->inAndroidBuild) {
1682 //         p = bufprint( p, end, "%s" PATH_SEP "profiles" PATH_SEP "%s",
1683 //                       i->androidOut, profileName );
1684 //     } else {
1685 //         p = bufprint( p, end, "%s" PATH_SEP "profiles" PATH_SEP "%s",
1686 //                       i->contentPath, profileName );
1687 //     }
1688 //     return ASTRDUP(tmp);
1689 // }
1690 //
1691 // const char*
1692 // avdInfo_getCoreHwIniPath( const AvdInfo* i )
1693 // {
1694 //     return i->coreHardwareIniPath;
1695 // }
1696 //
1697 // const char*
1698 // avdInfo_getSnapshotLockFilePath( const AvdInfo* i )
1699 // {
1700 //     return i->snapshotLockPath;
1701 // }
1702 //
1703 // const char*
1704 // avdInfo_getMultiInstanceLockFilePath( const AvdInfo* i )
1705 // {
1706 //     return i->multiInstanceLockPath;
1707 // }
1708 //
1709 // void
1710 // avdInfo_getSkinInfo( const AvdInfo*  i, char** pSkinName, char** pSkinDir )
1711 // {
1712 //     char*  skinName = NULL;
1713 //     char*  skinPath;
1714 //     char   temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
1715 //
1716 //     *pSkinName = NULL;
1717 //     *pSkinDir  = NULL;
1718 //
1719 //     if (!i->contentPath) {
1720 //         *pSkinName = ASTRDUP(SKIN_DEFAULT);
1721 //         return;
1722 //     }
1723 //
1724 //     /* First, see if the config.ini contains a SKIN_PATH entry that
1725 //      * names the full directory path for the skin.
1726 //      */
1727 //     if (i->configIni != NULL ) {
1728 //         skinPath = iniFile_getString( i->configIni, SKIN_PATH, NULL );
1729 //         if (skinPath != NULL) {
1730 //             /* If this skin name is magic or a direct directory path
1731 //             * we have our result right here.
1732 //             */
1733 //             if (_getSkinPathFromName(skinPath, i->sdkRootPath,
1734 //                                      pSkinName, pSkinDir )) {
1735 //                 AFREE(skinPath);
1736 //                 return;
1737 //             }
1738 //         }
1739 //
1740 //         /* The SKIN_PATH entry was not valid, so look at SKIN_NAME */
1741 //         D("Warning: " CORE_CONFIG_INI " contains invalid %s entry: %s",
1742 //           SKIN_PATH, skinPath);
1743 //         AFREE(skinPath);
1744 //
1745 //         skinName = iniFile_getString( i->configIni, SKIN_NAME, NULL );
1746 //     }
1747 //
1748 //     if (skinName == NULL) {
1749 //         /* If there is no skin listed in the config.ini, try to see if
1750 //          * there is one single 'skin' directory in the content directory.
1751 //          */
1752 //         p = bufprint(temp, end, "%s"PATH_SEP"skin", i->contentPath);
1753 //         if (p < end && _checkSkinPath(temp)) {
1754 //             D("using skin content from %s", temp);
1755 //             AFREE(i->skinName);
1756 //             *pSkinName = ASTRDUP("skin");
1757 //             *pSkinDir  = ASTRDUP(i->contentPath);
1758 //             return;
1759 //         }
1760 //
1761 //         if (i->configIni != NULL ) {
1762 //             /* We need to create a name.
1763 //              * Make a "magical" name using the screen size from config.ini
1764 //              * (parse_skin_files() in main-common-ui.c parses this name
1765 //              *  to determine the screen size.)
1766 //              */
1767 //             int width = iniFile_getInteger(i->configIni, "hw.lcd.width", 0);
1768 //             int height = iniFile_getInteger(i->configIni, "hw.lcd.height", 0);
1769 //             if (width > 0 && height > 0) {
1770 //                 char skinNameBuf[64];
1771 //                 snprintf(skinNameBuf, sizeof skinNameBuf, "%dx%d", width, height);
1772 //                 skinName = ASTRDUP(skinNameBuf);
1773 //             } else {
1774 //                 skinName = ASTRDUP(SKIN_DEFAULT);
1775 //             }
1776 //         } else {
1777 //             skinName = ASTRDUP(SKIN_DEFAULT);
1778 //         }
1779 //     }
1780 //
1781 //     /* now try to find the skin directory for that name -
1782 //      */
1783 //     do {
1784 //         /* first try the content directory, i.e. $CONTENT/skins/<name> */
1785 //         skinPath = _checkSkinSkinsDir(i->contentPath, skinName);
1786 //         if (skinPath != NULL)
1787 //             break;
1788 //
1789 // #define  PREBUILT_SKINS_ROOT "development"PATH_SEP"tools"PATH_SEP"emulator"
1790 //
1791 //         /* if we are in the Android build, try the prebuilt directory */
1792 //         if (i->inAndroidBuild) {
1793 //             p = bufprint( temp, end, "%s"PATH_SEP"%s",
1794 //                         i->androidBuildRoot, PREBUILT_SKINS_ROOT );
1795 //             if (p < end) {
1796 //                 skinPath = _checkSkinSkinsDir(temp, skinName);
1797 //                 if (skinPath != NULL)
1798 //                     break;
1799 //             }
1800 //
1801 //             /* or in the parent directory of the system dir */
1802 //             {
1803 //                 char* parentDir = path_parent(i->androidOut, 1);
1804 //                 if (parentDir != NULL) {
1805 //                     skinPath = _checkSkinSkinsDir(parentDir, skinName);
1806 //                     AFREE(parentDir);
1807 //                     if (skinPath != NULL)
1808 //                         break;
1809 //                 }
1810 //             }
1811 //         }
1812 //
1813 //         /* look in the search paths. For each <dir> in the list,
1814 //          * look into <dir>/../skins/<name>/ */
1815 //         {
1816 //             int  nn;
1817 //             for (nn = 0; nn < i->numSearchPaths; nn++) {
1818 //                 char*  parentDir = path_parent(i->searchPaths[nn], 1);
1819 //                 if (parentDir == NULL)
1820 //                     continue;
1821 //                 skinPath = _checkSkinSkinsDir(parentDir, skinName);
1822 //                 AFREE(parentDir);
1823 //                 if (skinPath != NULL)
1824 //                   break;
1825 //             }
1826 //             if (nn < i->numSearchPaths)
1827 //                 break;
1828 //         }
1829 //
1830 //         /* We didn't find anything ! */
1831 //         *pSkinName = skinName;
1832 //         return;
1833 //
1834 //     } while (0);
1835 //
1836 //     if (path_split(skinPath, pSkinDir, pSkinName) < 0) {
1837 //         derror("weird skin path: %s", skinPath);
1838 //         AFREE(skinPath);
1839 //         return;
1840 //     }
1841 //     DD("found skin '%s' in directory: %s", *pSkinName, *pSkinDir);
1842 //     AFREE(skinPath);
1843 //     return;
1844 // }
1845 //
1846 // char*
1847 // avdInfo_getCharmapFile( const AvdInfo* i, const char* charmapName )
1848 // {
1849 //     char        fileNameBuff[PATH_MAX];
1850 //     const char* fileName;
1851 //
1852 //     if (charmapName == NULL || charmapName[0] == '\0')
1853 //         return NULL;
1854 //
1855 //     if (strstr(charmapName, ".kcm") == NULL) {
1856 //         snprintf(fileNameBuff, sizeof fileNameBuff, "%s.kcm", charmapName);
1857 //         fileName = fileNameBuff;
1858 //     } else {
1859 //         fileName = charmapName;
1860 //     }
1861 //
1862 //     return _avdInfo_getContentOrSdkFilePath(i, fileName);
1863 // }
1864 //
1865 // AdbdCommunicationMode avdInfo_getAdbdCommunicationMode(const AvdInfo* i,
1866 //                                                        bool isQemu2)
1867 // {
1868 //     if (isQemu2) {
1869 //         // All qemu2-compatible system images support modern communication mode.
1870 //         return ADBD_COMMUNICATION_MODE_PIPE;
1871 //     }
1872 //
1873 //     if (i->apiLevel < 16 || (i->apiLevel > 99 && !i->isMarshmallowOrHigher)) {
1874 //         // QEMU pipe for ADB communication was added in android-4.1.1_r1 API 16
1875 //         D("API < 16 or unknown, forcing ro.adb.qemud==0");
1876 //         return ADBD_COMMUNICATION_MODE_LEGACY;
1877 //     }
1878 //
1879 //     // Ignore property file since all system images have been updated a long
1880 //     // time ago to support the pipe service for API level >= 16.
1881 //     return ADBD_COMMUNICATION_MODE_PIPE;
1882 // }
1883 //
1884 // int avdInfo_getSnapshotPresent(const AvdInfo* i)
1885 // {
1886 //     if (i->configIni == NULL) {
1887 //         return 0;
1888 //     } else {
1889 //         return iniFile_getBoolean(i->configIni, SNAPSHOT_PRESENT, "no");
1890 //     }
1891 // }
1892 //
1893 // const FileData* avdInfo_getBootProperties(const AvdInfo* i) {
1894 //     return i->bootProperties;
1895 // }
1896 //
1897 // const FileData* avdInfo_getBuildProperties(const AvdInfo* i) {
1898 //     return i->buildProperties;
1899 // }
1900 //
1901 // CIniFile* avdInfo_getConfigIni(const AvdInfo* i) {
1902 //     return i->configIni;
1903 // }
1904 //
1905 // int avdInfo_getSysImgIncrementalVersion(const AvdInfo* i) {
1906 //     return i->incrementalVersion;
1907 // }
1908 //
1909 // const char* avdInfo_getTag(const AvdInfo* i) {
1910 //     char temp[PATH_MAX];
1911 //     char* tagId = "default";
1912 //     char* tagDisplay = "Default";
1913 //     if (i->configIni) {
1914 //         tagId = iniFile_getString(i->configIni, TAG_ID, "default");
1915 //         tagDisplay = iniFile_getString(i->configIni, TAG_DISPLAY, "Default");
1916 //     }
1917 //     snprintf(temp, PATH_MAX, "%s [%s]", tagId, tagDisplay);
1918 //     return ASTRDUP(temp);
1919 // }
1920 //
1921 // const char* avdInfo_getSdCardSize(const AvdInfo* i) {
1922 //     return (i->configIni) ? iniFile_getString(i->configIni, SDCARD_SIZE, "")
1923 //                           : NULL;
1924 // }
1925 //
1926 // // Guest rendering is deprecated in future API level.  This function controls
1927 // // the current guest rendering blacklist status; particular builds of system
1928 // // images and particular API levels cannot run guest rendering.
1929 // bool avdInfo_sysImgGuestRenderingBlacklisted(const AvdInfo* i) {
1930 //     switch (i->apiLevel) {
1931 //     // Allow guest rendering for older API levels
1932 //     case 9:
1933 //     case 10:
1934 //     case 15:
1935 //     case 16:
1936 //     case 17:
1937 //     case 18:
1938 //         return false;
1939 //     // Disallow guest rendering for some problematic builds
1940 //     case 19:
1941 //         return i->incrementalVersion == 4087698;
1942 //     case 21:
1943 //         return i->incrementalVersion == 4088174;
1944 //     case 22:
1945 //         return i->incrementalVersion == 4088218;
1946 //     case 23:
1947 //         return i->incrementalVersion == 4088240;
1948 //     case 24:
1949 //         return i->incrementalVersion == 4088244;
1950 //     case 25:
1951 //         return i->incrementalVersion == 4153093;
1952 //     case 26:
1953 //         return i->incrementalVersion == 4074420;
1954 //     case 27:
1955 //         return false;
1956 //     // bug 111971822
1957 //     // Guest side Swiftshader becomes much harder to maintain
1958 //     // after SELinux changes that disallow executable memory.
1959 //     case 28:
1960 //     default:
1961 //         return true;
1962 //     }
1963 // }
1964 //
1965 // void avdInfo_replaceDataPartitionSizeInConfigIni(AvdInfo* i, int64_t sizeBytes) {
1966 //     if (!i || !i->configIni) return;
1967 //     iniFile_setInt64(i->configIni, "disk.dataPartition.size", sizeBytes);
1968 //
1969 //     char*  iniPath = _avdInfo_getContentFilePath(i, CORE_CONFIG_INI);
1970 //     iniFile_saveToFile(i->configIni, iniPath);
1971 // }
1972 //
1973 // bool avdInfo_isMarshmallowOrHigher(AvdInfo* i) {
1974 //     return i->isMarshmallowOrHigher;
1975 // }
1976 
avdInfo_newCustom(const char * name,int apiLevel,const char * abi,const char * arch,bool isGoogleApis,AvdFlavor flavor)1977 AvdInfo* avdInfo_newCustom(
1978     const char* name,
1979     int apiLevel,
1980     const char* abi,
1981     const char* arch,
1982     bool isGoogleApis,
1983     AvdFlavor flavor) {
1984 
1985     AvdInfo* i = new AvdInfo;
1986     memset(i, 0, sizeof(AvdInfo));
1987 
1988     i->deviceName = strdup(name);
1989     i->deviceId = strdup(name);
1990 
1991     i->noChecks = true;
1992 
1993     i->apiLevel = apiLevel;
1994     i->targetAbi = strdup(abi);
1995     i->targetArch = strdup(arch);
1996     i->isGoogleApis = isGoogleApis;
1997     i->flavor = flavor;
1998 
1999     return i;
2000 }
2001