• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.sdklib.internal.avd;
18 
19 import com.android.prefs.AndroidLocation.AndroidLocationException;
20 import com.android.sdklib.IAndroidTarget;
21 import com.android.sdklib.SdkConstants;
22 
23 import java.io.File;
24 import java.util.Collections;
25 import java.util.Map;
26 
27 /**
28  * An immutable structure describing an Android Virtual Device.
29  */
30 public final class AvdInfo implements Comparable<AvdInfo> {
31 
32     /**
33      * Status for an {@link AvdInfo}. Indicates whether or not this AVD is valid.
34      */
35     public static enum AvdStatus {
36         /** No error */
37         OK,
38         /** Missing 'path' property in the ini file */
39         ERROR_PATH,
40         /** Missing config.ini file in the AVD data folder */
41         ERROR_CONFIG,
42         /** Missing 'target' property in the ini file */
43         ERROR_TARGET_HASH,
44         /** Target was not resolved from its hash */
45         ERROR_TARGET,
46         /** Unable to parse config.ini */
47         ERROR_PROPERTIES,
48         /** System Image folder in config.ini doesn't exist */
49         ERROR_IMAGE_DIR;
50     }
51 
52     private final String mName;
53     private final File mIniFile;
54     private final String mFolderPath;
55     private final String mTargetHash;
56     private final IAndroidTarget mTarget;
57     private final String mAbiType;
58     private final Map<String, String> mProperties;
59     private final AvdStatus mStatus;
60 
61     /**
62      * Creates a new valid AVD info. Values are immutable.
63      * <p/>
64      * Such an AVD is available and can be used.
65      * The error string is set to null.
66      *
67      * @param name The name of the AVD (for display or reference)
68      * @param iniFile The path to the config.ini file
69      * @param folderPath The path to the data directory
70      * @param targetHash the target hash
71      * @param target The target. Can be null, if the target was not resolved.
72      * @param abiType Name of the abi.
73      * @param properties The property map. Cannot be null.
74      */
AvdInfo(String name, File iniFile, String folderPath, String targetHash, IAndroidTarget target, String abiType, Map<String, String> properties)75     public AvdInfo(String name,
76             File iniFile,
77             String folderPath,
78             String targetHash,
79             IAndroidTarget target,
80             String abiType,
81             Map<String, String> properties) {
82          this(name, iniFile, folderPath, targetHash, target, abiType, properties, AvdStatus.OK);
83     }
84 
85     /**
86      * Creates a new <em>invalid</em> AVD info. Values are immutable.
87      * <p/>
88      * Such an AVD is not complete and cannot be used.
89      * The error string must be non-null.
90      *
91      * @param name The name of the AVD (for display or reference)
92      * @param iniFile The path to the config.ini file
93      * @param folderPath The path to the data directory
94      * @param targetHash the target hash
95      * @param target The target. Can be null, if the target was not resolved.
96      * @param abiType Name of the abi.
97      * @param properties The property map. Can be null.
98      * @param status The {@link AvdStatus} of this AVD. Cannot be null.
99      */
AvdInfo(String name, File iniFile, String folderPath, String targetHash, IAndroidTarget target, String abiType, Map<String, String> properties, AvdStatus status)100     public AvdInfo(String name,
101             File iniFile,
102             String folderPath,
103             String targetHash,
104             IAndroidTarget target,
105             String abiType,
106             Map<String, String> properties,
107             AvdStatus status) {
108         mName = name;
109         mIniFile = iniFile;
110         mFolderPath = folderPath;
111         mTargetHash = targetHash;
112         mTarget = target;
113         mAbiType = abiType;
114         mProperties = properties == null ? null : Collections.unmodifiableMap(properties);
115         mStatus = status;
116     }
117 
118     /** Returns the name of the AVD. */
getName()119     public String getName() {
120         return mName;
121     }
122 
123     /** Returns the path of the AVD data directory. */
getDataFolderPath()124     public String getDataFolderPath() {
125         return mFolderPath;
126     }
127 
128     /** Returns the processor type of the AVD. */
getAbiType()129     public String getAbiType() {
130         return mAbiType;
131     }
132 
getCpuArch()133     public String getCpuArch() {
134         String cpuArch = mProperties.get(AvdManager.AVD_INI_CPU_ARCH);
135         if (cpuArch != null) {
136             return cpuArch;
137         }
138 
139         // legacy
140         return SdkConstants.CPU_ARCH_ARM;
141     }
142 
143     /** Convenience function to return a more user friendly name of the abi type. */
getPrettyAbiType(String raw)144     public static String getPrettyAbiType(String raw) {
145         String s = null;
146         if (raw.equalsIgnoreCase(SdkConstants.ABI_ARMEABI)) {
147             s = "ARM (" + SdkConstants.ABI_ARMEABI + ")";
148 
149         } else if (raw.equalsIgnoreCase(SdkConstants.ABI_ARMEABI_V7A)) {
150             s = "ARM (" + SdkConstants.ABI_ARMEABI_V7A + ")";
151 
152         } else if (raw.equalsIgnoreCase(SdkConstants.ABI_INTEL_ATOM)) {
153             s = "Intel Atom (" + SdkConstants.ABI_INTEL_ATOM + ")";
154 
155         } else if (raw.equalsIgnoreCase(SdkConstants.ABI_MIPS)) {
156             s = "Mips (" + SdkConstants.ABI_MIPS + ")";
157 
158         } else {
159             s = raw + " (" + raw + ")";
160         }
161         return s;
162     }
163 
164     /**
165      * Returns the target hash string.
166      */
getTargetHash()167     public String getTargetHash() {
168         return mTargetHash;
169     }
170 
171     /** Returns the target of the AVD, or <code>null</code> if it has not been resolved. */
getTarget()172     public IAndroidTarget getTarget() {
173         return mTarget;
174     }
175 
176     /** Returns the {@link AvdStatus} of the receiver. */
getStatus()177     public AvdStatus getStatus() {
178         return mStatus;
179     }
180 
181     /**
182      * Helper method that returns the default AVD folder that would be used for a given
183      * AVD name <em>if and only if</em> the AVD was created with the default choice.
184      * <p/>
185      * Callers must NOT use this to "guess" the actual folder from an actual AVD since
186      * the purpose of the AVD .ini file is to be able to change this folder. Callers
187      * should however use this to create a new {@link AvdInfo} to setup its data folder
188      * to the default.
189      * <p/>
190      * The default is {@code getDefaultAvdFolder()/avdname.avd/}.
191      * <p/>
192      * For an actual existing AVD, callers must use {@link #getDataFolderPath()} instead.
193      *
194      * @param manager The AVD Manager, used to get the AVD storage path.
195      * @param avdName The name of the desired AVD.
196      * @throws AndroidLocationException if there's a problem getting android root directory.
197      */
getDefaultAvdFolder(AvdManager manager, String avdName)198     public static File getDefaultAvdFolder(AvdManager manager, String avdName)
199             throws AndroidLocationException {
200         return new File(manager.getBaseAvdFolder(),
201                         avdName + AvdManager.AVD_FOLDER_EXTENSION);
202     }
203 
204     /**
205      * Helper method that returns the .ini {@link File} for a given AVD name.
206      * <p/>
207      * The default is {@code getDefaultAvdFolder()/avdname.ini}.
208      *
209      * @param manager The AVD Manager, used to get the AVD storage path.
210      * @param avdName The name of the desired AVD.
211      * @throws AndroidLocationException if there's a problem getting android root directory.
212      */
getDefaultIniFile(AvdManager manager, String avdName)213     public static File getDefaultIniFile(AvdManager manager, String avdName)
214             throws AndroidLocationException {
215         String avdRoot = manager.getBaseAvdFolder();
216         return new File(avdRoot, avdName + AvdManager.INI_EXTENSION);
217     }
218 
219     /**
220      * Returns the .ini {@link File} for this AVD.
221      */
getIniFile()222     public File getIniFile() {
223         return mIniFile;
224     }
225 
226     /**
227      * Helper method that returns the Config {@link File} for a given AVD name.
228      */
getConfigFile(String path)229     public static File getConfigFile(String path) {
230         return new File(path, AvdManager.CONFIG_INI);
231     }
232 
233     /**
234      * Returns the Config {@link File} for this AVD.
235      */
getConfigFile()236     public File getConfigFile() {
237         return getConfigFile(mFolderPath);
238     }
239 
240     /**
241      * Returns an unmodifiable map of properties for the AVD. This can be null.
242      */
getProperties()243     public Map<String, String> getProperties() {
244         return mProperties;
245     }
246 
247     /**
248      * Returns the error message for the AVD or <code>null</code> if {@link #getStatus()}
249      * returns {@link AvdStatus#OK}
250      */
getErrorMessage()251     public String getErrorMessage() {
252         switch (mStatus) {
253             case ERROR_PATH:
254                 return String.format("Missing AVD 'path' property in %1$s", getIniFile());
255             case ERROR_CONFIG:
256                 return String.format("Missing config.ini file in %1$s", mFolderPath);
257             case ERROR_TARGET_HASH:
258                 return String.format("Missing 'target' property in %1$s", getIniFile());
259             case ERROR_TARGET:
260                 return String.format("Unknown target '%1$s' in %2$s",
261                         mTargetHash, getIniFile());
262             case ERROR_PROPERTIES:
263                 return String.format("Failed to parse properties from %1$s",
264                         getConfigFile());
265             case ERROR_IMAGE_DIR:
266                 return String.format(
267                         "Invalid value in image.sysdir. Run 'android update avd -n %1$s'",
268                         mName);
269             case OK:
270                 assert false;
271                 return null;
272         }
273 
274         return null;
275     }
276 
277     /**
278      * Returns whether an emulator is currently running the AVD.
279      */
isRunning()280     public boolean isRunning() {
281         File f = new File(mFolderPath, "userdata-qemu.img.lock");   //$NON-NLS-1$
282         return f.isFile();
283     }
284 
285     /**
286      * Compares this object with the specified object for order. Returns a
287      * negative integer, zero, or a positive integer as this object is less
288      * than, equal to, or greater than the specified object.
289      *
290      * @param o the Object to be compared.
291      * @return a negative integer, zero, or a positive integer as this object is
292      *         less than, equal to, or greater than the specified object.
293      */
294     @Override
compareTo(AvdInfo o)295     public int compareTo(AvdInfo o) {
296         // first handle possible missing targets (if the AVD failed to load for unresolved targets)
297         if (mTarget == null && o != null && o.mTarget == null) {
298             return 0;
299         } if (mTarget == null) {
300             return +1;
301         } else if (o == null || o.mTarget == null) {
302             return -1;
303         }
304 
305         // then compare the targets
306         int targetDiff = mTarget.compareTo(o.mTarget);
307 
308         if (targetDiff == 0) {
309             // same target? compare on the avd name
310             return mName.compareTo(o.mName);
311         }
312 
313         return targetDiff;
314     }
315 }
316