All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.android.sdklib.internal.avd.AvdInfo Maven / Gradle / Ivy

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.sdklib.internal.avd;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISystemImage;
import com.android.sdklib.SystemImage;
import com.android.sdklib.devices.Abi;
import com.android.sdklib.devices.Device;
import com.android.sdklib.repository.descriptors.IdDisplay;
import com.google.common.base.Charsets;
import com.google.common.io.Files;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;

/**
 * An immutable structure describing an Android Virtual Device.
 */
public final class AvdInfo implements Comparable {

    /**
     * Status for an {@link AvdInfo}. Indicates whether or not this AVD is valid.
     */
    public enum AvdStatus {
        /** No error */
        OK,
        /** Missing 'path' property in the ini file */
        ERROR_PATH,
        /** Missing config.ini file in the AVD data folder */
        ERROR_CONFIG,
        /** Missing 'target' property in the ini file */
        ERROR_TARGET_HASH,
        /** Target was not resolved from its hash */
        ERROR_TARGET,
        /** Unable to parse config.ini */
        ERROR_PROPERTIES,
        /** System Image folder in config.ini doesn't exist */
        ERROR_IMAGE_DIR,
        /** The {@link Device} this AVD is based on has changed from its original configuration*/
        ERROR_DEVICE_CHANGED,
        /** The {@link Device} this AVD is based on is no longer available */
        ERROR_DEVICE_MISSING,
        /** the {@link SystemImage} this AVD is based on is no longer available */
        ERROR_IMAGE_MISSING
    }

    private final String mName;
    private final File mIniFile;
    private final String mFolderPath;
    private final String mTargetHash;
    private final IAndroidTarget mTarget;
    private final String mAbiType;
    /** An immutable map of properties. This must not be modified. Map can be empty. Never null. */
    private final Map mProperties;
    private final AvdStatus mStatus;
    private final IdDisplay mTag;

    /**
     * Creates a new valid AVD info. Values are immutable.
     * 

* Such an AVD is available and can be used. * The error string is set to null. * * @param name The name of the AVD (for display or reference) * @param iniFile The path to the config.ini file * @param folderPath The path to the data directory * @param targetHash the target hash * @param target The target. Can be null, if the target was not resolved. * @param tag The tag id/display. * @param abiType Name of the abi. * @param properties The property map. If null, an empty map will be created. */ public AvdInfo(@NonNull String name, @NonNull File iniFile, @NonNull String folderPath, @NonNull String targetHash, @Nullable IAndroidTarget target, @NonNull IdDisplay tag, @NonNull String abiType, @Nullable Map properties) { this(name, iniFile, folderPath, targetHash, target, tag, abiType, properties, AvdStatus.OK); } /** * Creates a new invalid AVD info. Values are immutable. *

* Such an AVD is not complete and cannot be used. * The error string must be non-null. * * @param name The name of the AVD (for display or reference) * @param iniFile The path to the config.ini file * @param folderPath The path to the data directory * @param targetHash the target hash * @param target The target. Can be null, if the target was not resolved. * @param tag The tag id/display. * @param abiType Name of the abi. * @param properties The property map. If null, an empty map will be created. * @param status The {@link AvdStatus} of this AVD. Cannot be null. */ public AvdInfo(@NonNull String name, @NonNull File iniFile, @NonNull String folderPath, @NonNull String targetHash, @Nullable IAndroidTarget target, @NonNull IdDisplay tag, @NonNull String abiType, @Nullable Map properties, @NonNull AvdStatus status) { mName = name; mIniFile = iniFile; mFolderPath = folderPath; mTargetHash = targetHash; mTarget = target; mTag = tag; mAbiType = abiType; mProperties = properties == null ? Collections.emptyMap() : Collections.unmodifiableMap(properties); mStatus = status; } /** Returns the name of the AVD. */ @NonNull public String getName() { return mName; } /** Returns the path of the AVD data directory. */ @NonNull public String getDataFolderPath() { return mFolderPath; } /** Returns the tag id/display of the AVD. */ @NonNull public IdDisplay getTag() { return mTag; } /** Returns the processor type of the AVD. */ @NonNull public String getAbiType() { return mAbiType; } @NonNull public String getCpuArch() { String cpuArch = mProperties.get(AvdManager.AVD_INI_CPU_ARCH); if (cpuArch != null) { return cpuArch; } // legacy return SdkConstants.CPU_ARCH_ARM; } @NonNull public String getDeviceManufacturer() { String deviceManufacturer = mProperties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER); if (deviceManufacturer != null && !deviceManufacturer.isEmpty()) { return deviceManufacturer; } return ""; // $NON-NLS-1$ } @NonNull public String getDeviceName() { String deviceName = mProperties.get(AvdManager.AVD_INI_DEVICE_NAME); if (deviceName != null && !deviceName.isEmpty()) { return deviceName; } return ""; // $NON-NLS-1$ } /** Convenience function to return a more user friendly name of the abi type. */ @NonNull public static String getPrettyAbiType(@NonNull AvdInfo avdInfo) { return getPrettyAbiType(avdInfo.getTag(), avdInfo.getAbiType()); } /** Convenience function to return a more user friendly name of the abi type. */ @NonNull public static String getPrettyAbiType(@NonNull ISystemImage sysImg) { return getPrettyAbiType(sysImg.getTag(), sysImg.getAbiType()); } /** Convenience function to return a more user friendly name of the abi type. */ @NonNull public static String getPrettyAbiType(@NonNull IdDisplay tag, @NonNull String rawAbi) { String s = ""; // $NON-NLS-1$ if (!SystemImage.DEFAULT_TAG.equals(tag)) { s = tag.getDisplay() + ' '; } Abi abi = Abi.getEnum(rawAbi); s += (abi == null ? rawAbi : abi.getDisplayName()) + " (" + rawAbi + ')'; return s; } /** * Returns the target hash string. */ @NonNull public String getTargetHash() { return mTargetHash; } /** Returns the target of the AVD, or null if it has not been resolved. */ @Nullable public IAndroidTarget getTarget() { return mTarget; } /** Returns the {@link AvdStatus} of the receiver. */ @NonNull public AvdStatus getStatus() { return mStatus; } /** * Helper method that returns the default AVD folder that would be used for a given * AVD name if and only if the AVD was created with the default choice. *

* Callers must NOT use this to "guess" the actual folder from an actual AVD since * the purpose of the AVD .ini file is to be able to change this folder. Callers * should however use this to create a new {@link AvdInfo} to setup its data folder * to the default. *

* The default is {@code getDefaultAvdFolder()/avdname.avd/}. *

* For an actual existing AVD, callers must use {@link #getDataFolderPath()} instead. * * @param manager The AVD Manager, used to get the AVD storage path. * @param avdName The name of the desired AVD. * @param unique Whether to return the default or a unique variation of the default. * @throws AndroidLocationException if there's a problem getting android root directory. */ @NonNull public static File getDefaultAvdFolder(@NonNull AvdManager manager, @NonNull String avdName, boolean unique) throws AndroidLocationException { String base = manager.getBaseAvdFolder(); File result = new File(base, avdName + AvdManager.AVD_FOLDER_EXTENSION); if (unique) { int suffix = 0; while (result.exists()) { result = new File(base, String.format("%s_%d%s", avdName, (++suffix), AvdManager.AVD_FOLDER_EXTENSION)); } } return result; } /** Compatibility forwarding until the usages in tools/swt are updated */ @Deprecated @NonNull public static File getDefaultAvdFolder(@NonNull AvdManager manager, @NonNull String avdName) throws AndroidLocationException{ return getDefaultAvdFolder(manager, avdName, false); } /** * Helper method that returns the .ini {@link File} for a given AVD name. *

* The default is {@code getDefaultAvdFolder()/avdname.ini}. * * @param manager The AVD Manager, used to get the AVD storage path. * @param avdName The name of the desired AVD. * @throws AndroidLocationException if there's a problem getting android root directory. */ @NonNull public static File getDefaultIniFile(@NonNull AvdManager manager, @NonNull String avdName) throws AndroidLocationException { String avdRoot = manager.getBaseAvdFolder(); return new File(avdRoot, avdName + AvdManager.INI_EXTENSION); } /** * Returns the .ini {@link File} for this AVD. */ @NonNull public File getIniFile() { return mIniFile; } /** * Helper method that returns the Config {@link File} for a given AVD name. */ @NonNull public static File getConfigFile(@NonNull String path) { return new File(path, AvdManager.CONFIG_INI); } /** * Returns the Config {@link File} for this AVD. */ @NonNull public File getConfigFile() { return getConfigFile(mFolderPath); } /** * Returns an unmodifiable map of properties for the AVD. * This can be empty but not null. * Callers must NOT try to modify this immutable map. */ @NonNull public Map getProperties() { return mProperties; } /** * Returns the error message for the AVD or null if {@link #getStatus()} * returns {@link AvdStatus#OK} */ @Nullable public String getErrorMessage() { switch (mStatus) { case ERROR_PATH: return String.format("Missing AVD 'path' property in %1$s", getIniFile()); case ERROR_CONFIG: return String.format("Missing config.ini file in %1$s", mFolderPath); case ERROR_TARGET_HASH: return String.format("Missing 'target' property in %1$s", getIniFile()); case ERROR_TARGET: return String.format("Unknown target '%1$s' in %2$s", mTargetHash, getIniFile()); case ERROR_PROPERTIES: return String.format("Failed to parse properties from %1$s", getConfigFile()); case ERROR_IMAGE_DIR: return String.format( "Missing system image for %1$s%2$s %3$s. Run 'android update avd -n %4$s'", SystemImage.DEFAULT_TAG.equals(mTag) ? "" : (mTag.getDisplay() + " "), mAbiType, mTarget.getFullName(), mName); case ERROR_DEVICE_CHANGED: return String.format("%1$s %2$s configuration has changed since AVD creation", mProperties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER), mProperties.get(AvdManager.AVD_INI_DEVICE_NAME)); case ERROR_DEVICE_MISSING: return String.format("%1$s %2$s no longer exists as a device", mProperties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER), mProperties.get(AvdManager.AVD_INI_DEVICE_NAME)); case OK: assert false; return null; } return null; } /** * Compares this object with the specified object for order. Returns a * negative integer, zero, or a positive integer as this object is less * than, equal to, or greater than the specified object. * * @param o the Object to be compared. * @return a negative integer, zero, or a positive integer as this object is * less than, equal to, or greater than the specified object. */ @Override public int compareTo(AvdInfo o) { // first handle possible missing targets (if the AVD failed to load for unresolved targets) if (mTarget == null && o != null && o.mTarget == null) { return 0; } if (mTarget == null) { return +1; } else if (o == null || o.mTarget == null) { return -1; } // then compare the targets int targetDiff = mTarget.compareTo(o.mTarget); if (targetDiff == 0) { // same target? compare on the avd name return mName.compareTo(o.mName); } return targetDiff; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy