Home | History | Annotate | Download | only in avd
      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      */
     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      */
    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. */
    119     public String getName() {
    120         return mName;
    121     }
    122 
    123     /** Returns the path of the AVD data directory. */
    124     public String getDataFolderPath() {
    125         return mFolderPath;
    126     }
    127 
    128     /** Returns the processor type of the AVD. */
    129     public String getAbiType() {
    130         return mAbiType;
    131     }
    132 
    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. */
    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      */
    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. */
    172     public IAndroidTarget getTarget() {
    173         return mTarget;
    174     }
    175 
    176     /** Returns the {@link AvdStatus} of the receiver. */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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
    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