diff options
19 files changed, 697 insertions, 507 deletions
diff --git a/assetstudio/src/com/android/assetstudiolib/ActionBarIconGenerator.java b/assetstudio/src/com/android/assetstudiolib/ActionBarIconGenerator.java index 9ed88e9..3cd6f11 100644 --- a/assetstudio/src/com/android/assetstudiolib/ActionBarIconGenerator.java +++ b/assetstudio/src/com/android/assetstudiolib/ActionBarIconGenerator.java @@ -34,8 +34,11 @@ public class ActionBarIconGenerator extends GraphicGenerator { @Override public BufferedImage generate(GraphicGeneratorContext context, Options options) { + ActionBarOptions actionBarOptions = (ActionBarOptions) options; Rectangle iconSizeMdpi = new Rectangle(0, 0, 32, 32); - Rectangle targetRectMdpi = new Rectangle(4, 4, 24, 24); + Rectangle targetRectMdpi = actionBarOptions.sourceIsClipart + ? new Rectangle(0, 0, 32, 32) + : new Rectangle(4, 4, 24, 24); final float scaleFactor = GraphicGenerator.getMdpiScaleFactor(options.density); Rectangle imageRect = Util.scaleRectangle(iconSizeMdpi, scaleFactor); Rectangle targetRect = Util.scaleRectangle(targetRectMdpi, scaleFactor); @@ -47,7 +50,6 @@ public class ActionBarIconGenerator extends GraphicGenerator { Graphics2D g2 = (Graphics2D) tempImage.getGraphics(); Util.drawCenterInside(g2, options.sourceImage, targetRect); - ActionBarOptions actionBarOptions = (ActionBarOptions) options; if (actionBarOptions.theme == Theme.HOLO_LIGHT) { Util.drawEffects(g, tempImage, 0, 0, new Effect[] { new FillEffect(new Color(0x333333), 0.6), @@ -69,6 +71,9 @@ public class ActionBarIconGenerator extends GraphicGenerator { public static class ActionBarOptions extends GraphicGenerator.Options { /** The theme to generate icons for */ public Theme theme = Theme.HOLO_LIGHT; + + /** Whether or not the source image is a clipart source */ + public boolean sourceIsClipart = false; } /** The themes to generate action bar icons for */ diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureAssetSetPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureAssetSetPage.java index 567ffab..426dbae 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureAssetSetPage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureAssetSetPage.java @@ -1142,6 +1142,7 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen actionBarOptions.theme = mValues.holoDark ? ActionBarIconGenerator.Theme.HOLO_DARK : ActionBarIconGenerator.Theme.HOLO_LIGHT; + actionBarOptions.sourceIsClipart = (mValues.sourceType == SourceType.CLIPART); options = actionBarOptions; break; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java index 899e31e..b5869ce 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java @@ -69,6 +69,7 @@ import com.android.sdklib.IAndroidTarget; import com.android.sdklib.devices.Device; import com.android.sdklib.devices.DeviceManager; import com.android.sdklib.devices.State; +import com.android.sdklib.devices.DeviceManager.DevicesChangeListener; import com.android.sdklib.internal.avd.AvdInfo; import com.android.sdklib.internal.avd.AvdManager; import com.android.sdklib.repository.PkgProps; @@ -97,6 +98,7 @@ import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; @@ -145,7 +147,8 @@ import java.util.TreeMap; * - Target reload. This is when the target used by the project is the edited file has finished<br> * loading.<br> */ -public class ConfigurationComposite extends Composite implements SelectionListener { +public class ConfigurationComposite extends Composite + implements SelectionListener, DevicesChangeListener { public static final String ATTR_CONTEXT = "context"; //$NON-NLS-1$ private static final String ICON_SQUARE = "square"; //$NON-NLS-1$ private static final String ICON_LANDSCAPE = "landscape"; //$NON-NLS-1$ @@ -2669,13 +2672,7 @@ public class ConfigurationComposite extends Composite implements SelectionListen if (sdk != null) { mDeviceList = sdk.getDevices(); DeviceManager manager = sdk.getDeviceManager(); - manager.registerListener(new DeviceManager.DevicesChangeListener() { - @Override - public void onDevicesChange() { - mDeviceList = sdk.getDevices(); - addDeviceMenuListener(mDeviceCombo); - } - }); + manager.registerListener(this); } else { mDeviceList = new ArrayList<Device>(); } @@ -2690,6 +2687,18 @@ public class ConfigurationComposite extends Composite implements SelectionListen selectDevice(null); } } + + @Override + public void onDevicesChange() { + final Sdk sdk = Sdk.getCurrent(); + mDeviceList = sdk.getDevices(); + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + addDeviceMenuListener(mDeviceCombo); + } + }); + } Image getOrientationIcon(ScreenOrientation orientation, boolean flip) { IconFactory icons = IconFactory.getInstance(); diff --git a/files/devices.xml b/files/devices.xml index c9eb890..ec8d936 100644 --- a/files/devices.xml +++ b/files/devices.xml @@ -1,452 +1,407 @@ -<?xml version="1.0"?> -<d:layout-devices - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:d="http://schemas.android.com/sdk/android/layout-devices/1"> +<?xml version="1.0" encoding="UTF-8"?> - <d:device name="2.7in QVGA"> - <d:default> - <d:screen-size>small</d:screen-size> - <d:screen-ratio>notlong</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>ldpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>240</d:size> - <d:size>320</d:size> - </d:screen-dimension> - <d:xdpi>145</d:xdpi> - <d:ydpi>145</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> +<d:devices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:d="http://schemas.android.com/sdk/devices/1"> - <d:device name="2.7in QVGA slider"> - <d:default> - <d:screen-size>small</d:screen-size> - <d:screen-ratio>notlong</d:screen-ratio> + <d:device> + <d:name>Nexus One</d:name> + <d:manufacturer>HTC</d:manufacturer> + <d:hardware> + <d:screen> + <d:screen-size>normal</d:screen-size> + <d:diagonal-length>3.7</d:diagonal-length> + <d:pixel-density>hdpi</d:pixel-density> + <d:screen-ratio>long</d:screen-ratio> + <d:dimensions> + <d:x-dimension>480</d:x-dimension> + <d:y-dimension>720</d:y-dimension> + </d:dimensions> + <d:xdpi>254</d:xdpi> + <d:ydpi>254</d:ydpi> + <d:touch> + <d:multitouch>basic</d:multitouch> + <d:mechanism>finger</d:mechanism> + <d:screen-type>capacitive</d:screen-type> + </d:touch> + </d:screen> + <d:networking> + Wifi + Bluetooth + </d:networking> + <d:sensors> + Accelerometer + Compass + GPS + LightSensor + ProximitySensor + </d:sensors> + <d:mic>true</d:mic> + <d:camera> + <d:location>back</d:location> + <d:autofocus>true</d:autofocus> + <d:flash>true</d:flash> + </d:camera> + <d:keyboard>nokeys</d:keyboard> + <d:nav>trackball</d:nav> + <d:ram unit="MiB">512</d:ram> + <d:buttons>hard</d:buttons> + <d:internal-storage unit="MiB">503</d:internal-storage> + <d:removable-storage unit="MiB">0</d:removable-storage> + <d:cpu>Qualcomm Scorpion</d:cpu> + <d:gpu>Qualcomm Adreno 200</d:gpu> + <d:abi> + armeabi-v7a + armeabi + </d:abi> + <d:dock> </d:dock> + <d:power-type>plugged-in</d:power-type> + </d:hardware> + <d:software> + <d:api-level>7-10</d:api-level> + <d:live-wallpaper-support>true</d:live-wallpaper-support> + <d:bluetooth-profiles> </d:bluetooth-profiles> + <d:gl-version>2.0</d:gl-version> + <d:gl-extensions> + </d:gl-extensions> + <d:status-bar>true</d:status-bar> + </d:software> + <d:state name="Portrait" default="true"> + <d:description>The phone in portrait view</d:description> <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>ldpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:text-input-method>qwerty</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>240</d:size> - <d:size>320</d:size> - </d:screen-dimension> - <d:xdpi>145</d:xdpi> - <d:ydpi>145</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape, closed"> <d:keyboard-state>keyssoft</d:keyboard-state> + <d:nav-state>nonav</d:nav-state> + </d:state> + <d:state name="Landscape"> + <d:description>The phone in landscape view</d:description> <d:screen-orientation>land</d:screen-orientation> - </d:config> - <d:config name="Landscape, open"> - <d:keyboard-state>keysexposed</d:keyboard-state> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> - - <d:device name="3.2in HVGA slider (ADP1)"> - <d:default> - <d:screen-size>normal</d:screen-size> - <d:screen-ratio>notlong</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>mdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:text-input-method>qwerty</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>trackball</d:nav-method> - <d:screen-dimension> - <d:size>320</d:size> - <d:size>480</d:size> - </d:screen-dimension> - <d:xdpi>180.6</d:xdpi> - <d:ydpi>182</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape, closed"> <d:keyboard-state>keyssoft</d:keyboard-state> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - <d:config name="Landscape, open"> - <d:keyboard-state>keysexposed</d:keyboard-state> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> - - <d:device name="3.2in HVGA (ADP2)"> - <d:default> - <d:screen-size>normal</d:screen-size> - <d:screen-ratio>notlong</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>mdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>trackball</d:nav-method> - <d:screen-dimension> - <d:size>320</d:size> - <d:size>480</d:size> - </d:screen-dimension> - <d:xdpi>180.6</d:xdpi> - <d:ydpi>182</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> + <d:nav-state>nonav</d:nav-state> + </d:state> </d:device> - - <d:device name="3.3in WQVGA"> - <d:default> - <d:screen-size>normal</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> + <d:device> + <d:name>Nexus S</d:name> + <d:manufacturer>Samsung</d:manufacturer> + <d:hardware> + <d:screen> + <d:screen-size>normal</d:screen-size> + <d:diagonal-length>4</d:diagonal-length> + <d:pixel-density>hdpi</d:pixel-density> + <d:screen-ratio>long</d:screen-ratio> + <d:dimensions> + <d:x-dimension>480</d:x-dimension> + <d:y-dimension>800</d:y-dimension> + </d:dimensions> + <d:xdpi>235</d:xdpi> + <d:ydpi>235</d:ydpi> + <d:touch> + <d:multitouch>jazz-hands</d:multitouch> + <d:mechanism>finger</d:mechanism> + <d:screen-type>capacitive</d:screen-type> + </d:touch> + </d:screen> + <d:networking> + Wifi + Bluetooth + NFC + </d:networking> + <d:sensors> + Accelerometer + Compass + GPS + Gyroscope + LightSensor + ProximitySensor + </d:sensors> + <d:mic>true</d:mic> + <d:camera> + <d:location>back</d:location> + <d:autofocus>true</d:autofocus> + <d:flash>true</d:flash> + </d:camera> + <d:camera> + <d:location>front</d:location> + <d:autofocus>false</d:autofocus> + <d:flash>false</d:flash> + </d:camera> + <d:keyboard>nokeys</d:keyboard> + <d:nav>nonav</d:nav> + <d:ram unit="KiB">351428</d:ram> + <d:buttons>hard</d:buttons> + <d:internal-storage unit="MiB">503</d:internal-storage> + <d:removable-storage unit="MiB">0</d:removable-storage> + <d:cpu>Samsung Exynos 3110</d:cpu> + <d:gpu>PowerVR SGX 540</d:gpu> + <d:abi> + armeabi-v7a + armeabi + </d:abi> + <d:dock> </d:dock> + <d:power-type>plugged-in</d:power-type> + </d:hardware> + <d:software> + <d:api-level>9-16</d:api-level> + <d:live-wallpaper-support>true</d:live-wallpaper-support> + <d:bluetooth-profiles> </d:bluetooth-profiles> + <d:gl-version>2.0</d:gl-version> + <d:gl-extensions> + GL_EXT_debug_marker + GL_OES_rgb8_rgba8 + GL_OES_depth24 + GL_OES_vertex_half_float + GL_OES_texture_float + GL_OES_texture_half_float + GL_OES_element_index_uint + GL_OES_mapbuffer + GL_OES_fragment_precision_high + GL_OES_compressed_ETC1_RGB8_texture + GL_OES_EGL_image + GL_OES_EGL_image_external + GL_OES_required_internalformat + GL_OES_depth_texture + GL_OES_get_program_binary + GL_OES_packed_depth_stencil + GL_OES_standard_derivatives + GL_OES_vertex_array_object + GL_OES_egl_sync + GL_EXT_multi_draw_arrays + GL_EXT_texture_format_BGRA8888 + GL_EXT_discard_framebuffer + GL_EXT_shader_texture_lod + GL_IMG_shader_binary + GL_IMG_texture_compression_pvrtc + GL_IMG_texture_npot + GL_IMG_texture_format_BGRA8888 + GL_IMG_read_format + GL_IMG_program_binary + GL_IMG_multisampled_render_to_texture + </d:gl-extensions> + <d:status-bar>true</d:status-bar> + </d:software> + <d:state name="Portrait" default="true"> + <d:description>The phone in portrait view</d:description> <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>ldpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>240</d:size> - <d:size>400</d:size> - </d:screen-dimension> - <d:xdpi>141</d:xdpi> - <d:ydpi>141</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> + <d:nav-state>nonav</d:nav-state> + </d:state> + <d:state name="Landscape"> + <d:description>The phone in landscape view</d:description> <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> - <d:device name="3.4in FWQVGA"> - <d:default> - <d:screen-size>normal</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>ldpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>240</d:size> - <d:size>432</d:size> - </d:screen-dimension> - <d:xdpi>145</d:xdpi> - <d:ydpi>145</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> + <d:nav-state>nonav</d:nav-state> + </d:state> </d:device> - <d:device name="3.7in WVGA (Nexus One)"> - <d:default> - <d:screen-size>normal</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> + <d:device> + <d:name> + Galaxy Nexus + </d:name> + <d:manufacturer> + Samsung + </d:manufacturer> + <d:hardware> + <d:screen> + <d:screen-size>normal</d:screen-size> + <d:diagonal-length>4.65</d:diagonal-length> <!-- In inches --> + <d:pixel-density>xhdpi</d:pixel-density> + <d:screen-ratio>long</d:screen-ratio> + <d:dimensions> + <d:x-dimension>720</d:x-dimension> + <d:y-dimension>1280</d:y-dimension> + </d:dimensions> + <d:xdpi>316</d:xdpi> + <d:ydpi>316</d:ydpi> + <d:touch> + <d:multitouch>jazz-hands</d:multitouch> + <d:mechanism>finger</d:mechanism> + <d:screen-type>capacitive</d:screen-type> + </d:touch> + </d:screen> + <d:networking> + Bluetooth + Wifi + NFC + </d:networking> + <d:sensors> + Accelerometer + Barometer + Gyroscope + Compass + GPS + ProximitySensor + </d:sensors> + <d:mic>true</d:mic> + <d:camera> + <d:location>front</d:location> + <d:autofocus>true</d:autofocus> + <d:flash>false</d:flash> + </d:camera> + <d:camera> + <d:location>back</d:location> + <d:autofocus>true</d:autofocus> + <d:flash>true</d:flash> + </d:camera> + <d:keyboard>nokeys</d:keyboard> + <d:nav>nonav</d:nav> + <d:ram unit="GiB">1</d:ram> + <d:buttons>soft</d:buttons> + <d:internal-storage unit="GiB">16</d:internal-storage> + <d:removable-storage unit="KiB"></d:removable-storage> + <d:cpu>OMAP 4460</d:cpu> <!-- cpu type (Tegra3) freeform --> + <d:gpu>PowerVR SGX540</d:gpu> + <d:abi> + armeabi + armeabi-v7a + </d:abi> + <!--dock (car, desk, tv, none)--> + <d:dock> + </d:dock> + <!-- plugged in (never, charge, always) --> + <d:power-type>battery</d:power-type> + </d:hardware> + <d:software> + <d:api-level>14-</d:api-level> + <d:live-wallpaper-support>true</d:live-wallpaper-support> + <d:bluetooth-profiles> + HSP + HFP + SPP + A2DP + AVRCP + OPP + PBAP + GAVDP + AVDTP + HID + HDP + PAN + </d:bluetooth-profiles> + <d:gl-version>2.0</d:gl-version> + <!-- + These can be gotten via + javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS); + --> + <d:gl-extensions> + GL_EXT_discard_framebuffer + GL_EXT_multi_draw_arrays + GL_EXT_shader_texture_lod + GL_EXT_texture_format_BGRA8888 + GL_IMG_multisampled_render_to_texture + GL_IMG_program_binary + GL_IMG_read_format + GL_IMG_shader_binary + GL_IMG_texture_compression_pvrtc + GL_IMG_texture_format_BGRA8888 + GL_IMG_texture_npot + GL_OES_compressed_ETC1_RGB8_texture + GL_OES_depth_texture + GL_OES_depth24 + GL_OES_EGL_image + GL_OES_EGL_image_external + GL_OES_egl_sync + GL_OES_element_index_uint + GL_OES_fragment_precision_high + GL_OES_get_program_binary + GL_OES_mapbuffer + GL_OES_packed_depth_stencil + GL_OES_required_internalformat + GL_OES_rgb8_rgba8 + GL_OES_standard_derivatives + GL_OES_texture_float + GL_OES_texture_half_float + GL_OES_vertex_array_object + GL_OES_vertex_half_float + </d:gl-extensions> + <d:status-bar>true</d:status-bar> + </d:software> + <d:state name="Portrait" default="true"> + <d:description>The phone in portrait view</d:description> <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>hdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>trackball</d:nav-method> - <d:screen-dimension> - <d:size>480</d:size> - <d:size>800</d:size> - </d:screen-dimension> - <d:xdpi>254</d:xdpi> - <d:ydpi>254</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> + <d:nav-state>nonav</d:nav-state> + </d:state> + <d:state name="Landscape"> + <d:description>The phone in landscape view</d:description> <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> - - <d:device name="3.7in FWVGA slider"> - <d:default> - <d:screen-size>normal</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>hdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:text-input-method>qwerty</d:text-input-method> - <d:nav-state>navhidden</d:nav-state> - <d:nav-method>dpad</d:nav-method> - <d:screen-dimension> - <d:size>480</d:size> - <d:size>854</d:size> - </d:screen-dimension> - <d:xdpi>265</d:xdpi> - <d:ydpi>265</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape, closed"> <d:keyboard-state>keyssoft</d:keyboard-state> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - <d:config name="Landscape, open"> - <d:keyboard-state>keysexposed</d:keyboard-state> - <d:screen-orientation>land</d:screen-orientation> - <d:nav-state>navexposed</d:nav-state> - </d:config> + <d:nav-state>nonav</d:nav-state> + </d:state> </d:device> + <d:device> + <d:name>Nexus 7</d:name> + <d:manufacturer>Asus</d:manufacturer> + <d:hardware> + <d:screen> + <d:screen-size>large</d:screen-size> + <d:diagonal-length>7.27</d:diagonal-length> + <d:pixel-density>tvdpi</d:pixel-density> + <d:screen-ratio>notlong</d:screen-ratio> + <d:dimensions> + <d:x-dimension>800</d:x-dimension> + <d:y-dimension>1280</d:y-dimension> + </d:dimensions> + <d:xdpi>195</d:xdpi> + <d:ydpi>200</d:ydpi> + <d:touch> + <d:multitouch>jazz-hands</d:multitouch> + <d:mechanism>finger</d:mechanism> + <d:screen-type>capacitive</d:screen-type> + </d:touch> + </d:screen> + <d:networking> + Wifi + Bluetooth + NFC + </d:networking> + <d:sensors> + Accelerometer + Compass + GPS + Gyroscope + LightSensor + </d:sensors> + <d:mic>true</d:mic> + <d:camera> + <d:location>front</d:location> + <d:autofocus>false</d:autofocus> + <d:flash>false</d:flash> + </d:camera> + <d:keyboard>nokeys</d:keyboard> + <d:nav>nonav</d:nav> + <d:ram unit="GiB">1</d:ram> + <d:buttons>soft</d:buttons> + <d:internal-storage unit="GiB">8</d:internal-storage> + <d:removable-storage unit="MiB"> </d:removable-storage> + <d:cpu> Tegra3 </d:cpu> + <d:gpu> Tegra3 </d:gpu> + <d:abi> + armeabi-v7a + armeabi + </d:abi> + <d:dock> </d:dock> + <d:power-type>battery</d:power-type> + </d:hardware> - <d:device name="4in WVGA (Nexus S)"> - <d:default> - <d:screen-size>normal</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>hdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>480</d:size> - <d:size>800</d:size> - </d:screen-dimension> - <d:xdpi>235</d:xdpi> - <d:ydpi>235</d:ydpi> - </d:default> + <d:software> + <d:api-level>16</d:api-level> + <d:live-wallpaper-support>true</d:live-wallpaper-support> + <d:bluetooth-profiles> </d:bluetooth-profiles> + <d:gl-version>2.0</d:gl-version> + <d:gl-extensions> </d:gl-extensions> + <d:status-bar>true</d:status-bar> + </d:software> - <d:config name="Portrait"> + <d:state name="Portrait" default="true"> + <d:description>The phone in portrait view</d:description> <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> - - <d:device name="4.65in 720p (Galaxy Nexus)"> - <d:default> - <d:screen-size>normal</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>xhdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>720</d:size> - <d:size>1280</d:size> - </d:screen-dimension> - <d:xdpi>316</d:xdpi> - <d:ydpi>316</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> + <d:nav-state>nonav</d:nav-state> + </d:state> + <d:state name="Landscape"> + <d:description>The phone in landscape view</d:description> <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> - - <d:device name="4.7in WXGA"> - <d:default> - <d:screen-size>normal</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>xhdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>1280</d:size> - <d:size>720</d:size> - </d:screen-dimension> - <d:xdpi>320</d:xdpi> - <d:ydpi>320</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> + <d:nav-state>nonav</d:nav-state> + </d:state> - <d:device name="5.1in WVGA"> - <d:default> - <d:screen-size>large</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>mdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>480</d:size> - <d:size>800</d:size> - </d:screen-dimension> - <d:xdpi>183</d:xdpi> - <d:ydpi>183</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> - - <d:device name="5.4in FWVGA"> - <d:default> - <d:screen-size>large</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>port</d:screen-orientation> - <d:pixel-density>mdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>480</d:size> - <d:size>854</d:size> - </d:screen-dimension> - <d:xdpi>181</d:xdpi> - <d:ydpi>181</d:ydpi> - </d:default> - - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - </d:device> - - <d:device name="7in WSVGA (Tablet)"> - <d:default> - <d:screen-size>large</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>land</d:screen-orientation> - <d:pixel-density>mdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>1024</d:size> - <d:size>600</d:size> - </d:screen-dimension> - <d:xdpi>169</d:xdpi> - <d:ydpi>169</d:ydpi> - </d:default> - - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - </d:device> - - <d:device name="7in WXGA (Nexus 7)"> - <d:default> - <d:screen-size>large</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>land</d:screen-orientation> - <d:pixel-density>tvdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>1280</d:size> - <d:size>800</d:size> - </d:screen-dimension> - <d:xdpi>195</d:xdpi> - <d:ydpi>200</d:ydpi> - </d:default> - - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> - </d:device> - - <d:device name="10.1in WXGA (Tablet)"> - <d:default> - <d:screen-size>xlarge</d:screen-size> - <d:screen-ratio>long</d:screen-ratio> - <d:screen-orientation>land</d:screen-orientation> - <d:pixel-density>mdpi</d:pixel-density> - <d:touch-type>finger</d:touch-type> - <d:keyboard-state>keyssoft</d:keyboard-state> - <d:text-input-method>nokeys</d:text-input-method> - <d:nav-state>navexposed</d:nav-state> - <d:nav-method>nonav</d:nav-method> - <d:screen-dimension> - <d:size>1280</d:size> - <d:size>800</d:size> - </d:screen-dimension> - <d:xdpi>149</d:xdpi> - <d:ydpi>149</d:ydpi> - </d:default> - - <d:config name="Landscape"> - <d:screen-orientation>land</d:screen-orientation> - </d:config> - <d:config name="Portrait"> - <d:screen-orientation>port</d:screen-orientation> - </d:config> </d:device> -</d:layout-devices> +</d:devices> diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Camera.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Camera.java index 4f26994..d7d33fe 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Camera.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Camera.java @@ -99,7 +99,7 @@ public class Camera { @Override public int hashCode() { int hash = 17; - hash = 31 * hash + mLocation.hashCode(); + hash = 31 * hash + mLocation.ordinal(); hash = 31 * hash + (mAutofocus ? 1 : 0); hash = 31 * hash + (mFlash ? 1 : 0); return hash; diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Device.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Device.java index e4da52e..dcd82a2 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Device.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Device.java @@ -16,13 +16,13 @@ package com.android.sdklib.devices; +import com.android.dvlib.DeviceSchema; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import com.android.dvlib.DeviceSchema; - /** * Instances of this class contain the specifications for a device. Use the * {@link Builder} class to construct a Device object, or the @@ -272,10 +272,15 @@ public final class Device { } @Override + /** A hash that's stable across JVM instances */ public int hashCode() { int hash = 17; - hash = 31 * hash + mName.hashCode(); - hash = 31 * hash + mManufacturer.hashCode(); + for (Character c : mName.toCharArray()) { + hash = 31 * hash + c; + } + for (Character c : mManufacturer.toCharArray()) { + hash = 31 * hash + c; + } hash = 31 * hash + mSoftware.hashCode(); hash = 31 * hash + mState.hashCode(); hash = 31 * hash + mMeta.hashCode(); diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceManager.java index 9cf0378..8bf45fc 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceManager.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceManager.java @@ -16,6 +16,7 @@ package com.android.sdklib.devices; +import com.android.annotations.Nullable; import com.android.prefs.AndroidLocation; import com.android.prefs.AndroidLocation.AndroidLocationException; import com.android.resources.Keyboard; @@ -23,7 +24,6 @@ import com.android.resources.KeyboardState; import com.android.resources.Navigation; import com.android.sdklib.ISdkLog; import com.android.sdklib.SdkConstants; -import com.android.sdklib.devices.Storage.Unit; import com.android.sdklib.internal.avd.AvdManager; import com.android.sdklib.internal.avd.HardwareProperties; import com.android.sdklib.repository.PkgProps; @@ -71,6 +71,21 @@ public class DeviceManager { private static final List<DevicesChangeListener> listeners = Collections.synchronizedList(new ArrayList<DevicesChangeListener>()); + public static enum DeviceStatus { + /** + * The device exists unchanged from the given configuration + */ + EXISTS, + /** + * A device exists with the given name and manufacturer, but has a different configuration + */ + CHANGED, + /** + * There is no device with the given name and manufacturer + */ + MISSING; + } + // TODO: Refactor this to look more like AvdManager so that we don't have // multiple instances // in the same application, which forces us to parse the XML multiple times @@ -104,8 +119,34 @@ public class DeviceManager { * notifications when modifications to the {@link Device} list occur. * @param listener The listener to remove. */ - public void unregisterListener(DevicesChangeListener listener) { - listeners.remove(listener); + public boolean unregisterListener(DevicesChangeListener listener) { + return listeners.remove(listener); + } + + public DeviceStatus getDeviceStatus( + @Nullable String sdkLocation, String name, String manufacturer, int hashCode) { + Device d = getDevice(sdkLocation, name, manufacturer); + if (d == null) { + return DeviceStatus.MISSING; + } else { + return d.hashCode() == hashCode ? DeviceStatus.EXISTS : DeviceStatus.CHANGED; + } + } + + public Device getDevice(@Nullable String sdkLocation, String name, String manufacturer) { + List<Device> devices; + if (sdkLocation != null) { + devices = getDevices(sdkLocation); + } else { + devices = new ArrayList<Device>(getDefaultDevices()); + devices.addAll(getUserDevices()); + } + for (Device d : devices) { + if (d.getName().equals(name) && d.getManufacturer().equals(manufacturer)) { + return d; + } + } + return null; } /** @@ -158,6 +199,15 @@ public class DeviceManager { if (mVendorDevices == null || !mVendorDevicesLocation.equals(sdkLocation)) { mVendorDevicesLocation = sdkLocation; List<Device> devices = new ArrayList<Device>(); + + // Load devices from tools folder + File toolsDevices = new File(sdkLocation, SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + + File.separator + SdkConstants.FN_DEVICES_XML); + if (toolsDevices.isFile()) { + devices.addAll(loadDevices(toolsDevices)); + } + + // Load devices from vendor extras File extrasFolder = new File(sdkLocation, SdkConstants.FD_EXTRAS); List<File> deviceDirs = getExtraDirs(extrasFolder); for (File deviceDir : deviceDirs) { @@ -290,7 +340,6 @@ public class DeviceManager { public static Map<String, String> getHardwareProperties(State s) { Hardware hw = s.getHardware(); Map<String, String> props = new HashMap<String, String>(); - props.put("hw.ramSize", Long.toString(hw.getRam().getSizeAsUnit(Unit.MiB))); props.put("hw.mainKeys", getBooleanVal(hw.getButtonType().equals(ButtonType.HARD))); props.put("hw.trackBall", getBooleanVal(hw.getNav().equals(Navigation.TRACKBALL))); props.put("hw.keyboard", getBooleanVal(hw.getKeyboard().equals(Keyboard.QWERTY))); @@ -302,7 +351,6 @@ public class DeviceManager { props.put("hw.sensors.orientation", getBooleanVal(sensors.contains(Sensor.GYROSCOPE))); props.put("hw.audioInput", getBooleanVal(hw.hasMic())); props.put("hw.sdCard", getBooleanVal(hw.getRemovableStorage().size() > 0)); - props.put("hw.sdCard", getBooleanVal(hw.getRemovableStorage().size() > 0)); props.put("hw.lcd.density", Integer.toString(hw.getScreen().getPixelDensity().getDpiValue())); props.put("hw.sensors.proximity", @@ -324,6 +372,9 @@ public class DeviceManager { props.put("hw.keyboard.lid", getBooleanVal(true)); } } + props.put(AvdManager.AVD_INI_DEVICE_HASH, Integer.toString(d.hashCode())); + props.put(AvdManager.AVD_INI_DEVICE_NAME, d.getName()); + props.put(AvdManager.AVD_INI_DEVICE_MANUFACTURER, d.getManufacturer()); return props; } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Hardware.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Hardware.java index 8993cd6..b12f11d 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Hardware.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Hardware.java @@ -282,21 +282,50 @@ public class Hardware { public int hashCode() { int hash = 17; hash = 31 * hash + mScreen.hashCode(); - hash = 31 * hash + mNetworking.hashCode(); - hash = 31 * hash + mSensors.hashCode(); + + // Since sets have no defined order, we need to hash them in such a way that order doesn't + // matter. + int temp = 0; + for (Network n : mNetworking) { + temp |= 1 << n.ordinal(); + } + hash = 31 * hash + temp; + + temp = 0; + for (Sensor s : mSensors) { + temp |= 1 << s.ordinal(); + } + + hash = 31 * hash + temp; hash = 31 * hash + (mMic ? 1 : 0); - hash = 31 * hash + mCameras.hashCode(); - hash = 31 * hash + mKeyboard.hashCode(); - hash = 31 * hash + mNav.hashCode(); + hash = mCameras.hashCode(); + hash = 31 * hash + mKeyboard.ordinal(); + hash = 31 * hash + mNav.ordinal(); hash = 31 * hash + mRam.hashCode(); - hash = 31 * hash + mButtons.hashCode(); + hash = 31 * hash + mButtons.ordinal(); hash = 31 * hash + mInternalStorage.hashCode(); hash = 31 * hash + mRemovableStorage.hashCode(); - hash = 31 * hash + mCpu.hashCode(); - hash = 31 * hash + mGpu.hashCode(); - hash = 31 * hash + mAbis.hashCode(); - hash = 31 * hash + mUiModes.hashCode(); - hash = 31 * hash + mPluggedIn.hashCode(); + + for (Character c : mCpu.toCharArray()) { + hash = 31 * hash + c; + } + + for (Character c : mGpu.toCharArray()) { + hash = 31 * hash + c; + } + + temp = 0; + for (Abi a : mAbis) { + temp |= 1 << a.ordinal(); + } + hash = 31 * hash + temp; + + temp = 0; + for (UiMode ui : mUiModes) { + temp |= 1 << ui.ordinal(); + } + hash = 31 * hash + temp; + return hash; } } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Meta.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Meta.java index 911c286..4c19f3f 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Meta.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Meta.java @@ -143,19 +143,27 @@ public class Meta { public int hashCode() { int hash = 17; if(mIconSixteen != null){ - hash = 31 * hash + mIconSixteen.hashCode(); + for (Character c : mIconSixteen.getAbsolutePath().toCharArray()) { + hash = 31 * hash + c; + } } if(mIconSixtyFour != null){ - hash = 31 * hash + mIconSixtyFour.hashCode(); + for (Character c : mIconSixtyFour.getAbsolutePath().toCharArray()) { + hash = 31 * hash + c; + } } if(mFrame != null){ - hash = 31 * hash + mFrame.hashCode(); + for (Character c : mFrame.getAbsolutePath().toCharArray()) { + hash = 31 * hash + c; + } } if(mFrameOffsetLandscape != null){ - hash = 31 * hash + mFrameOffsetLandscape.hashCode(); + hash = 31 * hash + mFrameOffsetLandscape.x; + hash = 31 * hash + mFrameOffsetLandscape.y; } if(mFrameOffsetPortrait != null){ - hash = 31 * hash + mFrameOffsetPortrait.hashCode(); + hash = 31 * hash + mFrameOffsetPortrait.x; + hash = 31 * hash + mFrameOffsetPortrait.y; } return hash; } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Screen.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Screen.java index 958219d..a7f4334 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Screen.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Screen.java @@ -170,20 +170,20 @@ public class Screen { @Override public int hashCode() { int hash = 17; - hash = 31 * hash + mScreenSize.hashCode(); + hash = 31 * hash + mScreenSize.ordinal(); long f = Double.doubleToLongBits(mDiagonalLength); hash = 31 * hash + (int) (f ^ (f >>> 32)); - hash = 31 * hash + mPixelDensity.hashCode(); - hash = 31 * hash + mScreenRatio.hashCode(); + hash = 31 * hash + mPixelDensity.ordinal(); + hash = 31 * hash + mScreenRatio.ordinal(); hash = 31 * hash + mXDimension; hash = 31 * hash + mYDimension; f = Double.doubleToLongBits(mXdpi); hash = 31 * hash + (int) (f ^ (f >>> 32)); f = Double.doubleToLongBits(mYdpi); hash = 31 * hash + (int) (f ^ (f >>> 32)); - hash = 31 * hash + mMultitouch.hashCode(); - hash = 31 * hash + mMechanism.hashCode(); - hash = 31 * hash + mScreenType.hashCode(); + hash = 31 * hash + mMultitouch.ordinal(); + hash = 31 * hash + mMechanism.ordinal(); + hash = 31 * hash + mScreenType.ordinal(); return hash; } } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Software.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Software.java index a452b6e..58f13b0 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Software.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Software.java @@ -125,14 +125,23 @@ public class Software { } @Override + /** A stable hash across JVM instances */ public int hashCode() { int hash = 17; hash = 31 * hash + mMinSdkLevel; hash = 31 * hash + mMaxSdkLevel; hash = 31 * hash + (mLiveWallpaperSupport ? 1 : 0); - hash = 31 * hash + mBluetoothProfiles.hashCode(); - hash = 31 * hash + mGlVersion.hashCode(); - hash = 31 * hash + mGlExtensions.hashCode(); + for (BluetoothProfile bp : mBluetoothProfiles) { + hash = 31 * hash + bp.ordinal(); + } + for (Character c : mGlVersion.toCharArray()) { + hash = 31 * hash + c; + } + for (String glExtension : mGlExtensions) { + for (Character c : glExtension.toCharArray()) { + hash = 31 * hash + c; + } + } hash = 31 * hash + (mStatusBar ? 1 : 0); return hash; } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/State.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/State.java index eb75605..1dc6961 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/State.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/State.java @@ -125,12 +125,17 @@ public class State { public int hashCode() { int hash = 17; hash = 31 * hash + (mDefaultState ? 1 : 0); - hash = 31 * hash + mName.hashCode(); - hash = 31 * hash + mDescription.hashCode(); - hash = 31 * hash + mOrientation.hashCode(); - hash = 31 * hash + mKeyState.hashCode(); - hash = 31 * hash + mNavState.hashCode(); + for (Character c : mName.toCharArray()) { + hash = 31 * hash + c; + } + for (Character c : mDescription.toCharArray()) { + hash = 31 * hash + c; + } + hash = 31 * hash + mOrientation.ordinal(); + hash = 31 * hash + mKeyState.ordinal(); + hash = 31 * hash + mNavState.ordinal(); hash = 31 * hash + mHardwareOverride.hashCode(); return hash; } + } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java index 54e2fa7..d2ec9db 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java @@ -46,7 +46,11 @@ public final class AvdInfo implements Comparable<AvdInfo> { /** Unable to parse config.ini */ ERROR_PROPERTIES, /** System Image folder in config.ini doesn't exist */ - ERROR_IMAGE_DIR; + 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; } private final String mName; @@ -284,6 +288,14 @@ public final class AvdInfo implements Comparable<AvdInfo> { return String.format( "Invalid value in image.sysdir. Run 'android update avd -n %1$s'", 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; diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java index 1a13a5e..52ce5d6 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java @@ -25,6 +25,8 @@ import com.android.sdklib.ISdkLog; import com.android.sdklib.ISystemImage; import com.android.sdklib.SdkConstants; import com.android.sdklib.SdkManager; +import com.android.sdklib.devices.DeviceManager; +import com.android.sdklib.devices.DeviceManager.DeviceStatus; import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; import com.android.sdklib.internal.project.ProjectProperties; import com.android.sdklib.util.GrabProcessOutput; @@ -182,6 +184,11 @@ public class AvdManager { public final static String AVD_INI_DATA_PARTITION_SIZE = "disk.dataPartition.size"; /** + * AVD/config.ini key name representing the hash of the device this AVD is based on + */ + public final static String AVD_INI_DEVICE_HASH = "hw.device.hash"; + + /** * Pattern to match pixel-sized skin "names", e.g. "320x480". */ public final static Pattern NUMERIC_SKIN_SIZE = Pattern.compile("([0-9]{2,})x([0-9]{2,})"); //$NON-NLS-1$ @@ -1389,6 +1396,20 @@ public class AvdManager { } } + // Get the device status if this AVD is associated with a device + DeviceStatus deviceStatus = null; + if (properties != null) { + String deviceName = properties.get(AVD_INI_DEVICE_NAME); + String deviceMfctr = properties.get(AVD_INI_DEVICE_MANUFACTURER); + String hash = properties.get(AVD_INI_DEVICE_HASH); + if (deviceName != null && deviceMfctr != null && hash != null) { + int deviceHash = Integer.parseInt(hash); + deviceStatus = (new DeviceManager(log)).getDeviceStatus( + mSdkManager.getLocation(), deviceName, deviceMfctr, deviceHash); + } + } + + // TODO: What about missing sdcard, skins, etc? AvdStatus status; @@ -1405,6 +1426,10 @@ public class AvdManager { status = AvdStatus.ERROR_PROPERTIES; } else if (validImageSysdir == false) { status = AvdStatus.ERROR_IMAGE_DIR; + } else if (deviceStatus == DeviceStatus.CHANGED) { + status = AvdStatus.ERROR_DEVICE_CHANGED; + } else if (deviceStatus == DeviceStatus.MISSING) { + status = AvdStatus.ERROR_DEVICE_MISSING; } else { status = AvdStatus.OK; } @@ -1579,10 +1604,16 @@ public class AvdManager { //FIXME: display paths to empty image folders? status = AvdStatus.ERROR_IMAGE_DIR; } + updateAvd(avd, properties, status, log); + } + public void updateAvd(AvdInfo avd, + Map<String, String> newProperties, + AvdStatus status, + ISdkLog log) throws IOException { // now write the config file File configIniFile = new File(avd.getDataFolderPath(), CONFIG_INI); - writeIniFile(configIniFile, properties); + writeIniFile(configIniFile, newProperties); // finally create a new AvdInfo for this unbroken avd and add it to the list. // instead of creating the AvdInfo object directly we reparse it, to detect other possible @@ -1595,8 +1626,7 @@ public class AvdManager { avd.getTargetHash(), avd.getTarget(), avd.getAbiType(), - properties, - status); + newProperties); replaceAvd(avd, newAvd); } diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman1/AvdManagerPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman1/AvdManagerPage.java index 63c53e0..6408a27 100755 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman1/AvdManagerPage.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman1/AvdManagerPage.java @@ -17,6 +17,8 @@ package com.android.sdkuilib.internal.repository.sdkman1; import com.android.prefs.AndroidLocation.AndroidLocationException; +import com.android.sdklib.devices.DeviceManager; +import com.android.sdklib.devices.DeviceManager.DevicesChangeListener; import com.android.sdkuilib.internal.repository.UpdaterData; import com.android.sdkuilib.internal.repository.UpdaterPage; import com.android.sdkuilib.internal.widgets.AvdSelector; @@ -29,23 +31,29 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; -public class AvdManagerPage extends UpdaterPage implements ISdkChangeListener { +public class AvdManagerPage extends UpdaterPage implements ISdkChangeListener, DevicesChangeListener { private AvdSelector mAvdSelector; private final UpdaterData mUpdaterData; - + private final DeviceManager mDeviceManager; /** * Create the composite. * @param parent The parent of the composite. * @param updaterData An instance of {@link UpdaterData}. */ - public AvdManagerPage(Composite parent, int swtStyle, UpdaterData updaterData) { + public AvdManagerPage(Composite parent, + int swtStyle, + UpdaterData updaterData, + DeviceManager deviceManager) { super(parent, swtStyle); mUpdaterData = updaterData; mUpdaterData.addListeners(this); + mDeviceManager = deviceManager; + mDeviceManager.registerListener(this); + createContents(this); postCreate(); //$hide$ } @@ -79,6 +87,7 @@ public class AvdManagerPage extends UpdaterPage implements ISdkChangeListener { @Override public void dispose() { mUpdaterData.removeListener(this); + mDeviceManager.unregisterListener(this); super.dispose(); } @@ -120,6 +129,14 @@ public class AvdManagerPage extends UpdaterPage implements ISdkChangeListener { // nothing to be done for now. } + // --- Implementation of DevicesChangeListener + + @Override + public void onDevicesChange() { + mAvdSelector.refresh(false /*reload*/); + } + + // End of hiding from SWT Designer //$hide<<$ } diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AvdManagerWindowImpl1.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AvdManagerWindowImpl1.java index 06cdc74..8a04b51 100755 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AvdManagerWindowImpl1.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AvdManagerWindowImpl1.java @@ -69,6 +69,8 @@ public class AvdManagerWindowImpl1 { private final UpdaterData mUpdaterData; /** True if this window created the UpdaterData, in which case it needs to dispose it. */ private final boolean mOwnUpdaterData; + private final DeviceManager mDeviceManager; + // --- UI members --- @@ -94,6 +96,7 @@ public class AvdManagerWindowImpl1 { mContext = context; mUpdaterData = new UpdaterData(osSdkRoot, sdkLog); mOwnUpdaterData = true; + mDeviceManager = new DeviceManager(sdkLog); } /** @@ -115,6 +118,7 @@ public class AvdManagerWindowImpl1 { mContext = context; mUpdaterData = updaterData; mOwnUpdaterData = false; + mDeviceManager = new DeviceManager(mUpdaterData.getSdkLog()); } /** @@ -161,6 +165,7 @@ public class AvdManagerWindowImpl1 { public void widgetDisposed(DisposeEvent e) { ShellSizeAndPos.saveSizeAndPos(mShell, SIZE_POS_PREFIX); //$hide$ onAndroidSdkUpdaterDispose(); //$hide$ + mAvdPage.dispose(); //$hide$ } }); @@ -180,7 +185,7 @@ public class AvdManagerWindowImpl1 { private void createContents() { - mAvdPage = new AvdManagerPage(mShell, SWT.NONE, mUpdaterData); + mAvdPage = new AvdManagerPage(mShell, SWT.NONE, mUpdaterData, mDeviceManager); mAvdPage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); } @@ -353,15 +358,13 @@ public class AvdManagerWindowImpl1 { Menu menuDevices = new Menu(menuBarDevices); menuBarDevices.setMenu(menuDevices); - final DeviceManager manager = new DeviceManager(mUpdaterData.getSdkLog()); - MenuItem createDevice = new MenuItem(menuDevices, SWT.NONE); createDevice.setText("Create New Device"); createDevice.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DeviceCreationDialog dlg = new DeviceCreationDialog( - mShell, manager, mUpdaterData.getImageFactory(), null); + mShell, mDeviceManager, mUpdaterData.getImageFactory(), null); if (dlg.open() == Window.OK) { setupDevices(menuBarDevices); } @@ -370,7 +373,7 @@ public class AvdManagerWindowImpl1 { new MenuItem(menuDevices, SWT.SEPARATOR); Map<String, List<Device>> devices = new HashMap<String, List<Device>>(); - for (Device d : manager.getDevices(mUpdaterData.getOsSdkRoot())) { + for (Device d : mDeviceManager.getDevices(mUpdaterData.getOsSdkRoot())) { List<Device> l; if (devices.containsKey(d.getManufacturer())) { l = devices.get(d.getManufacturer()); @@ -393,7 +396,7 @@ public class AvdManagerWindowImpl1 { @Override public void widgetSelected(SelectionEvent e) { DeviceCreationDialog dlg = new DeviceCreationDialog( - mShell, manager, mUpdaterData.getImageFactory(), d); + mShell, mDeviceManager, mUpdaterData.getImageFactory(), d); if(dlg.open() == Window.OK) { setupDevices(menuBarDevices); } diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java index baf8a26..24e3209 100644 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java @@ -878,9 +878,6 @@ public class AvdCreationDialog extends GridDialog { return false; } - hwProps.put(AvdManager.AVD_INI_DEVICE_MANUFACTURER, mDeviceManufacturer.getText()); - hwProps.put(AvdManager.AVD_INI_DEVICE_NAME, mDeviceName.getText()); - // Although the device has this information, some devices have more RAM than we'd want to // allocate to an emulator. hwProps.put(AvdManager.AVD_INI_RAM_SIZE, mRam.getText()); diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java index 58bacec..c447c89 100644 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java @@ -22,6 +22,8 @@ import com.android.sdklib.IAndroidTarget; import com.android.sdklib.ISdkLog; import com.android.sdklib.NullSdkLog; import com.android.sdklib.SdkConstants; +import com.android.sdklib.devices.Device; +import com.android.sdklib.devices.DeviceManager; import com.android.sdklib.internal.avd.AvdInfo; import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; import com.android.sdklib.internal.avd.AvdManager; @@ -66,7 +68,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.Formatter; +import java.util.HashMap; +import java.util.List; import java.util.Locale; +import java.util.Map; /** @@ -1000,21 +1005,49 @@ public final class AvdSelector { false /*logErrorsOnly*/); } - // delete the AVD - try { - mAvdManager.updateAvd(avdInfo, log); + boolean success = true; - // display the result - if (log instanceof MessageBoxLog) { - ((MessageBoxLog) log).displayResult(true /* success */); + if (avdInfo.getStatus() == AvdStatus.ERROR_IMAGE_DIR) { + // delete the AVD + try { + mAvdManager.updateAvd(avdInfo, log); + refresh(false /*reload*/); + } catch (IOException e) { + log.error(e, null); + success = false; + } + } else if (avdInfo.getStatus() == AvdStatus.ERROR_DEVICE_CHANGED) { + // Overwrite the properties derived from the device and nothing else + Map<String, String> properties = new HashMap<String, String>(avdInfo.getProperties()); + + List<Device> devices = (new DeviceManager(mSdkLog)).getDevices(mOsSdkPath); + String name = properties.get(AvdManager.AVD_INI_DEVICE_NAME); + String manufacturer = properties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER); + + if (properties != null && devices != null && name != null && manufacturer != null) { + for (Device d : devices) { + if (d.getName().equals(name) && d.getManufacturer().equals(manufacturer)) { + properties.putAll(DeviceManager.getHardwareProperties(d)); + try { + mAvdManager.updateAvd(avdInfo, properties, AvdStatus.OK, log); + } catch (IOException e) { + log.error(e,null); + success = false; + } + } + } + } else { + log.error(null, "Base device information incomplete or missing."); + success = false; } - refresh(false /*reload*/); - } catch (IOException e) { - log.error(e, null); + // display the result if (log instanceof MessageBoxLog) { - ((MessageBoxLog) log).displayResult(false /* success */); + ((MessageBoxLog) log).displayResult(success); } + refresh(false /*reload*/); + } else if (avdInfo.getStatus() == AvdStatus.ERROR_DEVICE_MISSING) { + onEdit(); } } @@ -1056,7 +1089,7 @@ public final class AvdSelector { } AvdStartDialog dialog = new AvdStartDialog(mTable.getShell(), avdInfo, mOsSdkPath, - mController); + mController, mSdkLog); if (dialog.open() == Window.OK) { String path = mOsSdkPath + File.separator + SdkConstants.OS_SDK_TOOLS_FOLDER @@ -1200,6 +1233,8 @@ public final class AvdSelector { } private boolean isAvdRepairable(AvdStatus avdStatus) { - return avdStatus == AvdStatus.ERROR_IMAGE_DIR; + return avdStatus == AvdStatus.ERROR_IMAGE_DIR + || avdStatus == AvdStatus.ERROR_DEVICE_CHANGED + || avdStatus == AvdStatus.ERROR_DEVICE_MISSING; } } diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java index 63787f9..9649f95 100644 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java @@ -16,6 +16,9 @@ package com.android.sdkuilib.internal.widgets; +import com.android.sdklib.ISdkLog; +import com.android.sdklib.devices.Device; +import com.android.sdklib.devices.DeviceManager; import com.android.sdklib.internal.avd.AvdInfo; import com.android.sdklib.internal.avd.AvdManager; import com.android.sdkuilib.internal.repository.SettingsController; @@ -72,6 +75,7 @@ final class AvdStartDialog extends GridDialog { private final AvdInfo mAvd; private final String mSdkLocation; private final SettingsController mSettingsController; + private final DeviceManager mDeviceManager; private Text mScreenSize; private Text mMonitorDpi; @@ -91,11 +95,12 @@ final class AvdStartDialog extends GridDialog { private Button mSnapshotLaunchCheckbox; AvdStartDialog(Shell parentShell, AvdInfo avd, String sdkLocation, - SettingsController settingsController) { + SettingsController settingsController, ISdkLog sdkLog) { super(parentShell, 2, false); mAvd = avd; mSdkLocation = sdkLocation; mSettingsController = settingsController; + mDeviceManager = new DeviceManager(sdkLog); if (mAvd == null) { throw new IllegalArgumentException("avd cannot be null"); } @@ -430,7 +435,8 @@ final class AvdStartDialog extends GridDialog { /** * Returns the screen size to start with. * <p/>If an emulator with the same skin was already launched, scaled, the size used is reused. - * <p/>Otherwise the default is returned (3) + * <p/>If one hasn't been launched and the AVD is based on a device, use the device's screen + * size. Otherwise, use the default (3). */ private String getScreenSize() { String size = sSkinScaling.get(mAvd.getName()); @@ -438,6 +444,20 @@ final class AvdStartDialog extends GridDialog { return size; } + Map<String, String> properties = mAvd.getProperties(); + if (properties != null) { + String name = properties.get(AvdManager.AVD_INI_DEVICE_NAME); + String mfctr = properties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER); + if (name != null && mfctr != null) { + Device d = mDeviceManager.getDevice(mSdkLocation, name, mfctr); + if (d != null) { + double screenSize = + d.getDefaultHardware().getScreen().getDiagonalLength(); + return String.format("%.1f", screenSize); + } + } + } + return "3"; } @@ -607,5 +627,4 @@ final class AvdStartDialog extends GridDialog { mSnapshotLaunch = enabled && sSnapshotLaunch; mSnapshotLaunchCheckbox.setSelection(mSnapshotLaunch); } - } |
