18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2009 The Android Open Source Project 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms. 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful, 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details. 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/ 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/user-config.h" 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/bufprint.h" 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/debug.h" 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/system.h" 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/path.h" 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h> 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <errno.h> 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/time.h> 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define D(...) VERBOSE_PRINT(init,__VA_ARGS__) 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0 /* set to 1 for more debugging */ 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DD(...) D(__VA_ARGS__) 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DD(...) ((void)0) 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct AUserConfig { 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ABool changed; 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int windowX; 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int windowY; 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint64_t uuid; 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* iniPath; 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Name of the user-config file */ 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define USER_CONFIG_FILE "emulator-user.ini" 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define KEY_WINDOW_X "window.x" 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define KEY_WINDOW_Y "window.y" 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define KEY_UUID "uuid" 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DEFAULT_X 100 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DEFAULT_Y 100 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Create a new AUserConfig object from a given AvdInfo */ 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectAUserConfig* 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectauserConfig_new( AvdInfo* info ) 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project AUserConfig* uc; 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char inAndroidBuild = avdInfo_inAndroidBuild(info); 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char needUUID = 1; 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp); 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* parentPath; 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project IniFile* ini = NULL; 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ANEW0(uc); 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* If we are in the Android build system, store the configuration 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in ~/.android/emulator-user.ini. otherwise, store it in the file 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * emulator-user.ini in the AVD's content directory. 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (inAndroidBuild) { 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p = bufprint_config_file(temp, end, USER_CONFIG_FILE); 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 67c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner p = bufprint(temp, end, "%s/%s", avdInfo_getContentPath(info), 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project USER_CONFIG_FILE); 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* handle the unexpected */ 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (p >= end) { 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Hmmm, something is weird, let's use a temporary file instead */ 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p = bufprint_temp_file(temp, end, USER_CONFIG_FILE); 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (p >= end) { 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project derror("Weird: Cannot create temporary user-config file?"); 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(2); 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dwarning("Weird: Content path too long, using temporary user-config."); 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->iniPath = ASTRDUP(temp); 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DD("looking user-config in: %s", uc->iniPath); 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ensure that the parent directory exists */ 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project parentPath = path_parent(uc->iniPath, 1); 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (parentPath == NULL) { 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project derror("Weird: Can't find parent of user-config file: %s", 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->iniPath); 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(2); 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!path_exists(parentPath)) { 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!inAndroidBuild) { 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project derror("Weird: No content path for this AVD: %s", parentPath); 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(2); 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DD("creating missing directory: %s", parentPath); 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (path_mkdir_if_needed(parentPath, 0755) < 0) { 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project derror("Using empty user-config, can't create %s: %s", 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project parentPath, strerror(errno)); 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(2); 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (path_exists(uc->iniPath)) { 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DD("reading user-config file"); 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ini = iniFile_newFromFile(uc->iniPath); 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ini == NULL) { 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dwarning("Can't read user-config file: %s\nUsing default values", 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->iniPath); 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ini != NULL) { 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->windowX = iniFile_getInteger(ini, KEY_WINDOW_X, DEFAULT_X); 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DD(" found %s = %d", KEY_WINDOW_X, uc->windowX); 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->windowY = iniFile_getInteger(ini, KEY_WINDOW_Y, DEFAULT_Y); 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DD(" found %s = %d", KEY_WINDOW_Y, uc->windowY); 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iniFile_getValue(ini, KEY_UUID) != NULL) { 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->uuid = (uint64_t) iniFile_getInt64(ini, KEY_UUID, 0LL); 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project needUUID = 0; 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DD(" found %s = %lld", KEY_UUID, uc->uuid); 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iniFile_free(ini); 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->windowX = DEFAULT_X; 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->windowY = DEFAULT_Y; 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->changed = 1; 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Generate a 64-bit UUID if necessary. We simply take the 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * current time, which avoids any privacy-related value. 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (needUUID) { 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct timeval tm; 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gettimeofday( &tm, NULL ); 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->uuid = (uint64_t)tm.tv_sec*1000 + tm.tv_usec/1000; 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uc->changed = 1; 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DD(" Generated UUID = %lld", uc->uuid); 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return uc; 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint64_t 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectauserConfig_getUUID( AUserConfig* uconfig ) 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return uconfig->uuid; 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectauserConfig_getWindowPos( AUserConfig* uconfig, int *pX, int *pY ) 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *pX = uconfig->windowX; 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *pY = uconfig->windowY; 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectauserConfig_setWindowPos( AUserConfig* uconfig, int x, int y ) 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (x != uconfig->windowX || y != uconfig->windowY) { 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uconfig->windowX = x; 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uconfig->windowY = y; 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uconfig->changed = 1; 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Save the user configuration back to the content directory. 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Should be used in an atexit() handler */ 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectauserConfig_save( AUserConfig* uconfig ) 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project IniFile* ini; 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char temp[256]; 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (uconfig->changed == 0) { 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project D("User-config was not changed."); 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bufprint(temp, temp+sizeof(temp), 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "%s = %d\n" 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "%s = %d\n" 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "%s = %lld\n", 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project KEY_WINDOW_X, uconfig->windowX, 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project KEY_WINDOW_Y, uconfig->windowY, 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project KEY_UUID, uconfig->uuid ); 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DD("Generated user-config file:\n%s", temp); 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ini = iniFile_newFromMemory(temp, uconfig->iniPath); 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ini == NULL) { 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project D("Weird: can't create user-config iniFile?"); 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iniFile_saveToFile(ini, uconfig->iniPath) < 0) { 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dwarning("could not save user configuration: %s: %s", 2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uconfig->iniPath, strerror(errno)); 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project D("User configuration saved to %s", uconfig->iniPath); 2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iniFile_free(ini); 2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 213