blob: 8cdbf7886120b8a645bbe6ed94fe186b5fbffba0 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/* Copyright (C) 2009 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
12#include "android/user-config.h"
13#include "android/utils/bufprint.h"
14#include "android/utils/debug.h"
15#include "android/utils/system.h"
16#include "android/utils/path.h"
17#include <stdlib.h>
18#include <errno.h>
19#include <sys/time.h>
20
21#define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
22
23#if 0 /* set to 1 for more debugging */
24# define DD(...) D(__VA_ARGS__)
25#else
26# define DD(...) ((void)0)
27#endif
28
29struct AUserConfig {
30 ABool changed;
31 int windowX;
32 int windowY;
33 uint64_t uuid;
34 char* iniPath;
35};
36
37/* Name of the user-config file */
38#define USER_CONFIG_FILE "emulator-user.ini"
39
40#define KEY_WINDOW_X "window.x"
41#define KEY_WINDOW_Y "window.y"
42#define KEY_UUID "uuid"
43
44#define DEFAULT_X 100
45#define DEFAULT_Y 100
46
47/* Create a new AUserConfig object from a given AvdInfo */
48AUserConfig*
49auserConfig_new( AvdInfo* info )
50{
51 AUserConfig* uc;
52 char inAndroidBuild = avdInfo_inAndroidBuild(info);
53 char needUUID = 1;
54 char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
55 char* parentPath;
56 IniFile* ini = NULL;
57
58 ANEW0(uc);
59
60 /* If we are in the Android build system, store the configuration
61 * in ~/.android/emulator-user.ini. otherwise, store it in the file
62 * emulator-user.ini in the AVD's content directory.
63 */
64 if (inAndroidBuild) {
65 p = bufprint_config_file(temp, end, USER_CONFIG_FILE);
66 } else {
David 'Digit' Turnerc0052462014-02-25 18:39:29 +010067 p = bufprint(temp, end, "%s/%s", avdInfo_getContentPath(info),
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080068 USER_CONFIG_FILE);
69 }
70
71 /* handle the unexpected */
72 if (p >= end) {
73 /* Hmmm, something is weird, let's use a temporary file instead */
74 p = bufprint_temp_file(temp, end, USER_CONFIG_FILE);
75 if (p >= end) {
76 derror("Weird: Cannot create temporary user-config file?");
77 exit(2);
78 }
79 dwarning("Weird: Content path too long, using temporary user-config.");
80 }
81
82 uc->iniPath = ASTRDUP(temp);
83 DD("looking user-config in: %s", uc->iniPath);
84
85
86 /* ensure that the parent directory exists */
87 parentPath = path_parent(uc->iniPath, 1);
88 if (parentPath == NULL) {
89 derror("Weird: Can't find parent of user-config file: %s",
90 uc->iniPath);
91 exit(2);
92 }
93
94 if (!path_exists(parentPath)) {
95 if (!inAndroidBuild) {
96 derror("Weird: No content path for this AVD: %s", parentPath);
97 exit(2);
98 }
99 DD("creating missing directory: %s", parentPath);
100 if (path_mkdir_if_needed(parentPath, 0755) < 0) {
101 derror("Using empty user-config, can't create %s: %s",
102 parentPath, strerror(errno));
103 exit(2);
104 }
105 }
106
107 if (path_exists(uc->iniPath)) {
108 DD("reading user-config file");
109 ini = iniFile_newFromFile(uc->iniPath);
110 if (ini == NULL) {
111 dwarning("Can't read user-config file: %s\nUsing default values",
112 uc->iniPath);
113 }
114 }
115
116 if (ini != NULL) {
117 uc->windowX = iniFile_getInteger(ini, KEY_WINDOW_X, DEFAULT_X);
118 DD(" found %s = %d", KEY_WINDOW_X, uc->windowX);
119
120 uc->windowY = iniFile_getInteger(ini, KEY_WINDOW_Y, DEFAULT_Y);
121 DD(" found %s = %d", KEY_WINDOW_Y, uc->windowY);
122
123 if (iniFile_getValue(ini, KEY_UUID) != NULL) {
124 uc->uuid = (uint64_t) iniFile_getInt64(ini, KEY_UUID, 0LL);
125 needUUID = 0;
126 DD(" found %s = %lld", KEY_UUID, uc->uuid);
127 }
128
129 iniFile_free(ini);
130 }
131 else {
132 uc->windowX = DEFAULT_X;
133 uc->windowY = DEFAULT_Y;
134 uc->changed = 1;
135 }
136
137 /* Generate a 64-bit UUID if necessary. We simply take the
138 * current time, which avoids any privacy-related value.
139 */
140 if (needUUID) {
141 struct timeval tm;
142
143 gettimeofday( &tm, NULL );
144 uc->uuid = (uint64_t)tm.tv_sec*1000 + tm.tv_usec/1000;
145 uc->changed = 1;
146 DD(" Generated UUID = %lld", uc->uuid);
147 }
148
149 return uc;
150}
151
152
153uint64_t
154auserConfig_getUUID( AUserConfig* uconfig )
155{
156 return uconfig->uuid;
157}
158
159void
160auserConfig_getWindowPos( AUserConfig* uconfig, int *pX, int *pY )
161{
162 *pX = uconfig->windowX;
163 *pY = uconfig->windowY;
164}
165
166
167void
168auserConfig_setWindowPos( AUserConfig* uconfig, int x, int y )
169{
170 if (x != uconfig->windowX || y != uconfig->windowY) {
171 uconfig->windowX = x;
172 uconfig->windowY = y;
173 uconfig->changed = 1;
174 }
175}
176
177/* Save the user configuration back to the content directory.
178 * Should be used in an atexit() handler */
179void
180auserConfig_save( AUserConfig* uconfig )
181{
182 IniFile* ini;
183 char temp[256];
184
185 if (uconfig->changed == 0) {
186 D("User-config was not changed.");
187 return;
188 }
189
190 bufprint(temp, temp+sizeof(temp),
191 "%s = %d\n"
192 "%s = %d\n"
193 "%s = %lld\n",
194 KEY_WINDOW_X, uconfig->windowX,
195 KEY_WINDOW_Y, uconfig->windowY,
196 KEY_UUID, uconfig->uuid );
197
198 DD("Generated user-config file:\n%s", temp);
199
200 ini = iniFile_newFromMemory(temp, uconfig->iniPath);
201 if (ini == NULL) {
202 D("Weird: can't create user-config iniFile?");
203 return;
204 }
205 if (iniFile_saveToFile(ini, uconfig->iniPath) < 0) {
206 dwarning("could not save user configuration: %s: %s",
207 uconfig->iniPath, strerror(errno));
208 } else {
209 D("User configuration saved to %s", uconfig->iniPath);
210 }
211 iniFile_free(ini);
212}