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