• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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 
29 struct 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 */
48 AUserConfig*
auserConfig_new(AvdInfo * info)49 auserConfig_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 {
67         p = bufprint(temp, end, "%s/%s", avdInfo_getContentPath(info),
68                      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 
153 uint64_t
auserConfig_getUUID(AUserConfig * uconfig)154 auserConfig_getUUID( AUserConfig*  uconfig )
155 {
156     return uconfig->uuid;
157 }
158 
159 void
auserConfig_getWindowPos(AUserConfig * uconfig,int * pX,int * pY)160 auserConfig_getWindowPos( AUserConfig*  uconfig, int  *pX, int  *pY )
161 {
162     *pX = uconfig->windowX;
163     *pY = uconfig->windowY;
164 }
165 
166 
167 void
auserConfig_setWindowPos(AUserConfig * uconfig,int x,int y)168 auserConfig_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 */
179 void
auserConfig_save(AUserConfig * uconfig)180 auserConfig_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 }
213