1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.layoutlib.bridge.intensive.setup;
18 
19 import com.android.ide.common.rendering.api.HardwareConfig;
20 import com.android.ide.common.resources.configuration.CountryCodeQualifier;
21 import com.android.ide.common.resources.configuration.DensityQualifier;
22 import com.android.ide.common.resources.configuration.FolderConfiguration;
23 import com.android.ide.common.resources.configuration.KeyboardStateQualifier;
24 import com.android.ide.common.resources.configuration.LayoutDirectionQualifier;
25 import com.android.ide.common.resources.configuration.LocaleQualifier;
26 import com.android.ide.common.resources.configuration.NavigationMethodQualifier;
27 import com.android.ide.common.resources.configuration.NetworkCodeQualifier;
28 import com.android.ide.common.resources.configuration.NightModeQualifier;
29 import com.android.ide.common.resources.configuration.ScreenDimensionQualifier;
30 import com.android.ide.common.resources.configuration.ScreenOrientationQualifier;
31 import com.android.ide.common.resources.configuration.ScreenRatioQualifier;
32 import com.android.ide.common.resources.configuration.ScreenSizeQualifier;
33 import com.android.ide.common.resources.configuration.TextInputMethodQualifier;
34 import com.android.ide.common.resources.configuration.TouchScreenQualifier;
35 import com.android.ide.common.resources.configuration.UiModeQualifier;
36 import com.android.ide.common.resources.configuration.VersionQualifier;
37 import com.android.resources.Density;
38 import com.android.resources.Keyboard;
39 import com.android.resources.KeyboardState;
40 import com.android.resources.Navigation;
41 import com.android.resources.NightMode;
42 import com.android.resources.ScreenOrientation;
43 import com.android.resources.ScreenRatio;
44 import com.android.resources.ScreenSize;
45 import com.android.resources.TouchScreen;
46 import com.android.resources.UiMode;
47 
48 import org.xmlpull.v1.XmlPullParser;
49 import org.xmlpull.v1.XmlPullParserException;
50 import org.xmlpull.v1.XmlPullParserFactory;
51 
52 import java.io.File;
53 import java.io.FileInputStream;
54 import java.io.IOException;
55 import java.util.Map;
56 import java.util.Properties;
57 
58 import com.google.android.collect.Maps;
59 
60 /**
61  * Provides {@link FolderConfiguration} and {@link HardwareConfig} for various devices. Also
62  * provides utility methods to parse build.prop and attrs.xml to generate the appropriate maps.
63  */
64 @SuppressWarnings("UnusedDeclaration") // For the pre-configured nexus generators.
65 public class ConfigGenerator {
66 
67     public static final ConfigGenerator NEXUS_4 = new ConfigGenerator();
68 
69     public static final ConfigGenerator NEXUS_5 = new ConfigGenerator()
70                                                         .setScreenHeight(1920)
71                                                         .setScreenWidth(1080)
72                                                         .setXdpi(445)
73                                                         .setYdpi(445)
74                                                         .setOrientation(ScreenOrientation.PORTRAIT)
75                                                         .setDensity(Density.XXHIGH)
76                                                         .setRatio(ScreenRatio.NOTLONG)
77                                                         .setSize(ScreenSize.NORMAL)
78                                                         .setKeyboard(Keyboard.NOKEY)
79                                                         .setTouchScreen(TouchScreen.FINGER)
80                                                         .setKeyboardState(KeyboardState.SOFT)
81                                                         .setSoftButtons(true)
82                                                         .setNavigation(Navigation.NONAV);
83 
84     public static final ConfigGenerator NEXUS_7 = new ConfigGenerator()
85                                                         .setScreenHeight(1920)
86                                                         .setScreenWidth(1200)
87                                                         .setXdpi(323)
88                                                         .setYdpi(323)
89                                                         .setOrientation(ScreenOrientation.PORTRAIT)
90                                                         .setDensity(Density.XHIGH)
91                                                         .setRatio(ScreenRatio.NOTLONG)
92                                                         .setSize(ScreenSize.LARGE)
93                                                         .setKeyboard(Keyboard.NOKEY)
94                                                         .setTouchScreen(TouchScreen.FINGER)
95                                                         .setKeyboardState(KeyboardState.SOFT)
96                                                         .setSoftButtons(true)
97                                                         .setNavigation(Navigation.NONAV);
98 
99     public static final ConfigGenerator NEXUS_10 = new ConfigGenerator()
100                                                         .setScreenHeight(1600)
101                                                         .setScreenWidth(2560)
102                                                         .setXdpi(300)
103                                                         .setYdpi(300)
104                                                         .setOrientation(ScreenOrientation.LANDSCAPE)
105                                                         .setDensity(Density.XHIGH)
106                                                         .setRatio(ScreenRatio.NOTLONG)
107                                                         .setSize(ScreenSize.XLARGE)
108                                                         .setKeyboard(Keyboard.NOKEY)
109                                                         .setTouchScreen(TouchScreen.FINGER)
110                                                         .setKeyboardState(KeyboardState.SOFT)
111                                                         .setSoftButtons(true)
112                                                         .setNavigation(Navigation.NONAV);
113 
114     public static final ConfigGenerator NEXUS_5_LAND = new ConfigGenerator()
115                                                         .setScreenHeight(1080)
116                                                         .setScreenWidth(1920)
117                                                         .setXdpi(445)
118                                                         .setYdpi(445)
119                                                         .setOrientation(ScreenOrientation.LANDSCAPE)
120                                                         .setDensity(Density.XXHIGH)
121                                                         .setRatio(ScreenRatio.NOTLONG)
122                                                         .setSize(ScreenSize.NORMAL)
123                                                         .setKeyboard(Keyboard.NOKEY)
124                                                         .setTouchScreen(TouchScreen.FINGER)
125                                                         .setKeyboardState(KeyboardState.SOFT)
126                                                         .setSoftButtons(true)
127                                                         .setNavigation(Navigation.NONAV);
128 
129     public static final ConfigGenerator NEXUS_7_2012 = new ConfigGenerator()
130                                                         .setScreenHeight(1280)
131                                                         .setScreenWidth(800)
132                                                         .setXdpi(195)
133                                                         .setYdpi(200)
134                                                         .setOrientation(ScreenOrientation.PORTRAIT)
135                                                         .setDensity(Density.TV)
136                                                         .setRatio(ScreenRatio.NOTLONG)
137                                                         .setSize(ScreenSize.LARGE)
138                                                         .setKeyboard(Keyboard.NOKEY)
139                                                         .setTouchScreen(TouchScreen.FINGER)
140                                                         .setKeyboardState(KeyboardState.SOFT)
141                                                         .setSoftButtons(true)
142                                                         .setNavigation(Navigation.NONAV);
143 
144     private static final String TAG_ATTR = "attr";
145     private static final String TAG_ENUM = "enum";
146     private static final String TAG_FLAG = "flag";
147     private static final String ATTR_NAME = "name";
148     private static final String ATTR_VALUE = "value";
149 
150     // Device Configuration. Defaults are for a Nexus 4 device.
151     private int mScreenHeight = 1280;
152     private int mScreenWidth = 768;
153     private int mXdpi = 320;
154     private int mYdpi = 320;
155     private ScreenOrientation mOrientation = ScreenOrientation.PORTRAIT;
156     private Density mDensity = Density.XHIGH;
157     private ScreenRatio mRatio = ScreenRatio.NOTLONG;
158     private ScreenSize mSize = ScreenSize.NORMAL;
159     private Keyboard mKeyboard = Keyboard.NOKEY;
160     private TouchScreen mTouchScreen = TouchScreen.FINGER;
161     private KeyboardState mKeyboardState = KeyboardState.SOFT;
162     private boolean mSoftButtons = true;
163     private Navigation mNavigation = Navigation.NONAV;
164 
getFolderConfig()165     public FolderConfiguration getFolderConfig() {
166         FolderConfiguration config = FolderConfiguration.createDefault();
167         config.setDensityQualifier(new DensityQualifier(mDensity));
168         config.setNavigationMethodQualifier(new NavigationMethodQualifier(mNavigation));
169         if (mScreenWidth > mScreenHeight) {
170             config.setScreenDimensionQualifier(new ScreenDimensionQualifier(mScreenWidth,
171                     mScreenHeight));
172         } else {
173             config.setScreenDimensionQualifier(new ScreenDimensionQualifier(mScreenHeight,
174                     mScreenWidth));
175         }
176         config.setScreenRatioQualifier(new ScreenRatioQualifier(mRatio));
177         config.setScreenSizeQualifier(new ScreenSizeQualifier(mSize));
178         config.setTextInputMethodQualifier(new TextInputMethodQualifier(mKeyboard));
179         config.setTouchTypeQualifier(new TouchScreenQualifier(mTouchScreen));
180         config.setKeyboardStateQualifier(new KeyboardStateQualifier(mKeyboardState));
181         config.setScreenOrientationQualifier(new ScreenOrientationQualifier(mOrientation));
182 
183         config.updateScreenWidthAndHeight();
184 
185         // some default qualifiers.
186         config.setUiModeQualifier(new UiModeQualifier(UiMode.NORMAL));
187         config.setNightModeQualifier(new NightModeQualifier(NightMode.NOTNIGHT));
188         config.setCountryCodeQualifier(new CountryCodeQualifier());
189         config.setLayoutDirectionQualifier(new LayoutDirectionQualifier());
190         config.setNetworkCodeQualifier(new NetworkCodeQualifier());
191         config.setLocaleQualifier(new LocaleQualifier());
192         config.setVersionQualifier(new VersionQualifier());
193         return config;
194     }
195 
getHardwareConfig()196     public HardwareConfig getHardwareConfig() {
197         return new HardwareConfig(mScreenWidth, mScreenHeight, mDensity, mXdpi, mYdpi, mSize,
198                 mOrientation, null, mSoftButtons);
199     }
200 
loadProperties(File path)201     public static Map<String, String> loadProperties(File path) {
202         Properties p = new Properties();
203         Map<String, String> map = Maps.newHashMap();
204         try {
205             p.load(new FileInputStream(path));
206             for (String key : p.stringPropertyNames()) {
207                 map.put(key, p.getProperty(key));
208             }
209         } catch (IOException e) {
210             e.printStackTrace();
211         }
212         return map;
213     }
214 
getEnumMap(File path)215     public static Map<String, Map<String, Integer>> getEnumMap(File path) {
216         Map<String, Map<String, Integer>> map = Maps.newHashMap();
217         try {
218             XmlPullParser xmlPullParser = XmlPullParserFactory.newInstance().newPullParser();
219             xmlPullParser.setInput(new FileInputStream(path), null);
220             int eventType = xmlPullParser.getEventType();
221             String attr = null;
222             while (eventType != XmlPullParser.END_DOCUMENT) {
223                 if (eventType == XmlPullParser.START_TAG) {
224                     if (TAG_ATTR.equals(xmlPullParser.getName())) {
225                         attr = xmlPullParser.getAttributeValue(null, ATTR_NAME);
226                     } else if (TAG_ENUM.equals(xmlPullParser.getName())
227                             || TAG_FLAG.equals(xmlPullParser.getName())) {
228                         String name = xmlPullParser.getAttributeValue(null, ATTR_NAME);
229                         String value = xmlPullParser.getAttributeValue(null, ATTR_VALUE);
230                         // Integer.decode cannot handle "ffffffff", see JDK issue 6624867
231                         int i = (int) (long) Long.decode(value);
232                         assert attr != null;
233                         Map<String, Integer> attributeMap = map.get(attr);
234                         if (attributeMap == null) {
235                             attributeMap = Maps.newHashMap();
236                             map.put(attr, attributeMap);
237                         }
238                         attributeMap.put(name, i);
239                     }
240                 } else if (eventType == XmlPullParser.END_TAG) {
241                     if (TAG_ATTR.equals(xmlPullParser.getName())) {
242                         attr = null;
243                     }
244                 }
245                 eventType = xmlPullParser.next();
246             }
247         } catch (XmlPullParserException e) {
248             e.printStackTrace();
249         } catch (IOException e) {
250             e.printStackTrace();
251         }
252         return map;
253     }
254 
255     // Methods to set the configuration values.
256 
setScreenHeight(int height)257     public ConfigGenerator setScreenHeight(int height) {
258         mScreenHeight = height;
259         return this;
260     }
261 
setScreenWidth(int width)262     public ConfigGenerator setScreenWidth(int width) {
263         mScreenWidth = width;
264         return this;
265     }
266 
setXdpi(int xdpi)267     public ConfigGenerator setXdpi(int xdpi) {
268         mXdpi = xdpi;
269         return this;
270     }
271 
setYdpi(int ydpi)272     public ConfigGenerator setYdpi(int ydpi) {
273         mYdpi = ydpi;
274         return this;
275     }
276 
setOrientation(ScreenOrientation orientation)277     public ConfigGenerator setOrientation(ScreenOrientation orientation) {
278         mOrientation = orientation;
279         return this;
280     }
281 
setDensity(Density density)282     public ConfigGenerator setDensity(Density density) {
283         mDensity = density;
284         return this;
285     }
286 
setRatio(ScreenRatio ratio)287     public ConfigGenerator setRatio(ScreenRatio ratio) {
288         mRatio = ratio;
289         return this;
290     }
291 
setSize(ScreenSize size)292     public ConfigGenerator setSize(ScreenSize size) {
293         mSize = size;
294         return this;
295     }
296 
setKeyboard(Keyboard keyboard)297     public ConfigGenerator setKeyboard(Keyboard keyboard) {
298         mKeyboard = keyboard;
299         return this;
300     }
301 
setTouchScreen(TouchScreen touchScreen)302     public ConfigGenerator setTouchScreen(TouchScreen touchScreen) {
303         mTouchScreen = touchScreen;
304         return this;
305     }
306 
setKeyboardState(KeyboardState state)307     public ConfigGenerator setKeyboardState(KeyboardState state) {
308         mKeyboardState = state;
309         return this;
310     }
311 
setSoftButtons(boolean softButtons)312     public ConfigGenerator setSoftButtons(boolean softButtons) {
313         mSoftButtons = softButtons;
314         return this;
315     }
316 
setNavigation(Navigation navigation)317     public ConfigGenerator setNavigation(Navigation navigation) {
318         mNavigation = navigation;
319         return this;
320     }
321 }
322