| /* |
| * Copyright (C) 2012 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.ide.common.rendering; |
| |
| import com.android.annotations.NonNull; |
| import com.android.annotations.Nullable; |
| import com.android.ide.common.rendering.api.HardwareConfig; |
| import com.android.resources.ScreenOrientation; |
| import com.android.sdklib.devices.ButtonType; |
| import com.android.sdklib.devices.Device; |
| import com.android.sdklib.devices.Screen; |
| |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| /** |
| * Helper method to create a {@link HardwareConfig} object. |
| * |
| * The base data comes from a {@link Device} object, with additional data provided on the helper |
| * object. |
| * |
| * Since {@link HardwareConfig} is immutable, this allows creating one in several (optional) |
| * steps more easily. |
| * |
| */ |
| public class HardwareConfigHelper { |
| |
| @NonNull |
| private final Device mDevice; |
| @NonNull |
| private ScreenOrientation mScreenOrientation = ScreenOrientation.PORTRAIT; |
| |
| // optional |
| private int mMaxRenderWidth = -1; |
| private int mMaxRenderHeight = -1; |
| private int mOverrideRenderWidth = -1; |
| private int mOverrideRenderHeight = -1; |
| |
| /** |
| * Creates a new helper for a given device. |
| * @param device the device to provide the base data. |
| */ |
| public HardwareConfigHelper(@NonNull Device device) { |
| mDevice = device; |
| } |
| |
| /** |
| * Sets the orientation of the config. |
| * @param screenOrientation the orientation. |
| * @return this (such that chains of setters can be stringed together) |
| */ |
| @NonNull |
| public HardwareConfigHelper setOrientation(@NonNull ScreenOrientation screenOrientation) { |
| mScreenOrientation = screenOrientation; |
| return this; |
| } |
| |
| /** |
| * Overrides the width and height to be used during rendering. |
| * |
| * A value of -1 will make the rendering use the normal width and height coming from the |
| * {@link Device} object. |
| * |
| * @param overrideRenderWidth the width in pixels of the layout to be rendered |
| * @param overrideRenderHeight the height in pixels of the layout to be rendered |
| * @return this (such that chains of setters can be stringed together) |
| */ |
| @NonNull |
| public HardwareConfigHelper setOverrideRenderSize(int overrideRenderWidth, |
| int overrideRenderHeight) { |
| mOverrideRenderWidth = overrideRenderWidth; |
| mOverrideRenderHeight = overrideRenderHeight; |
| return this; |
| } |
| |
| /** |
| * Sets the max width and height to be used during rendering. |
| * |
| * A value of -1 will make the rendering use the normal width and height coming from the |
| * {@link Device} object. |
| * |
| * @param maxRenderWidth the max width in pixels of the layout to be rendered |
| * @param maxRenderHeight the max height in pixels of the layout to be rendered |
| * @return this (such that chains of setters can be stringed together) |
| */ |
| @NonNull |
| public HardwareConfigHelper setMaxRenderSize(int maxRenderWidth, int maxRenderHeight) { |
| mMaxRenderWidth = maxRenderWidth; |
| mMaxRenderHeight = maxRenderHeight; |
| return this; |
| } |
| |
| /** |
| * Creates and returns the HardwareConfig object. |
| * @return the config |
| */ |
| @SuppressWarnings("SuspiciousNameCombination") // Deliberately swapping orientations |
| @NonNull |
| public HardwareConfig getConfig() { |
| Screen screen = mDevice.getDefaultHardware().getScreen(); |
| |
| // compute width and height to take orientation into account. |
| int x = screen.getXDimension(); |
| int y = screen.getYDimension(); |
| int width, height; |
| |
| if (x > y) { |
| if (mScreenOrientation == ScreenOrientation.LANDSCAPE) { |
| width = x; |
| height = y; |
| } else { |
| width = y; |
| height = x; |
| } |
| } else { |
| if (mScreenOrientation == ScreenOrientation.LANDSCAPE) { |
| width = y; |
| height = x; |
| } else { |
| width = x; |
| height = y; |
| } |
| } |
| |
| if (mOverrideRenderHeight != -1) { |
| width = mOverrideRenderWidth; |
| } |
| |
| if (mOverrideRenderHeight != -1) { |
| height = mOverrideRenderHeight; |
| } |
| |
| if (mMaxRenderWidth != -1) { |
| width = mMaxRenderWidth; |
| } |
| |
| if (mMaxRenderHeight != -1) { |
| height = mMaxRenderHeight; |
| } |
| |
| return new HardwareConfig( |
| width, |
| height, |
| screen.getPixelDensity(), |
| (float) screen.getXdpi(), |
| (float) screen.getYdpi(), |
| screen.getSize(), |
| mScreenOrientation, |
| mDevice.getDefaultHardware().getButtonType() == ButtonType.SOFT); |
| } |
| |
| // ---- Device Display Helpers ---- |
| |
| /** Manufacturer used by the generic devices in the device list */ |
| public static final String MANUFACTURER_GENERIC = "Generic"; //$NON-NLS-1$ |
| private static final String NEXUS = "Nexus"; //$NON-NLS-1$ |
| private static final Pattern GENERIC_PATTERN = |
| Pattern.compile("(\\d+\\.?\\d*)\" (.+?)( \\(.*Nexus.*\\))?"); //$NON-NLS-1$ |
| private static final String ID_PREFIX_WEAR = "wear_"; //$NON-NLS-1$ |
| private static final String ID_PREFIX_WEAR_ROUND = "wear_round"; //$NON-NLS-1$ |
| private static final String ID_PREFIX_TV = "tv_"; //$NON-NLS-1$ |
| |
| /** |
| * Returns a user-displayable description of the given Nexus device |
| * @param device the device to check |
| * @return the label |
| * @see #isNexus(com.android.sdklib.devices.Device) |
| */ |
| @NonNull |
| public static String getNexusLabel(@NonNull Device device) { |
| String name = device.getDisplayName(); |
| Screen screen = device.getDefaultHardware().getScreen(); |
| float length = (float) screen.getDiagonalLength(); |
| // Round dimensions to the nearest tenth |
| length = Math.round(10 * length) / 10.0f; |
| return String.format(Locale.US, "%1$s (%3$s\", %2$s)", |
| name, getResolutionString(device), Float.toString(length)); |
| } |
| |
| /** |
| * Returns a user-displayable description of the given generic device |
| * @param device the device to check |
| * @return the label |
| * @see #isGeneric(com.android.sdklib.devices.Device) |
| */ |
| @NonNull |
| public static String getGenericLabel(@NonNull Device device) { |
| // * Use the same precision for all devices (all but one specify decimals) |
| // * Add some leading space such that the dot ends up roughly in the |
| // same space |
| // * Add in screen resolution and density |
| String name = device.getDisplayName(); |
| Matcher matcher = GENERIC_PATTERN.matcher(name); |
| if (matcher.matches()) { |
| String size = matcher.group(1); |
| String n = matcher.group(2); |
| int dot = size.indexOf('.'); |
| if (dot == -1) { |
| size += ".0"; |
| dot = size.length() - 2; |
| } |
| for (int i = 0; i < 2 - dot; i++) { |
| size = ' ' + size; |
| } |
| name = size + "\" " + n; |
| } |
| |
| return String.format(Locale.US, "%1$s (%2$s)", name, |
| getResolutionString(device)); |
| } |
| |
| /** |
| * Returns a user displayable screen resolution string for the given device |
| * @param device the device to look up the string for |
| * @return a user displayable string |
| */ |
| @NonNull |
| public static String getResolutionString(@NonNull Device device) { |
| Screen screen = device.getDefaultHardware().getScreen(); |
| return String.format(Locale.US, |
| "%1$d \u00D7 %2$d: %3$s", // U+00D7: Unicode multiplication sign |
| screen.getXDimension(), |
| screen.getYDimension(), |
| screen.getPixelDensity().getResourceValue()); |
| } |
| |
| /** |
| * Returns true if the given device is a generic device |
| * @param device the device to check |
| * @return true if the device is generic |
| */ |
| public static boolean isGeneric(@NonNull Device device) { |
| return device.getManufacturer().equals(MANUFACTURER_GENERIC); |
| } |
| |
| /** |
| * Returns true if the given device is a Nexus device |
| * @param device the device to check |
| * @return true if the device is a Nexus |
| */ |
| public static boolean isNexus(@NonNull Device device) { |
| return device.getId().contains(NEXUS); |
| } |
| |
| /** |
| * Whether the given device is a wear device |
| */ |
| public static boolean isWear(@Nullable Device device) { |
| return device != null && device.getId().startsWith(ID_PREFIX_WEAR); |
| } |
| |
| /** |
| * Whether the given device has a round screen |
| */ |
| public static boolean isRound(@Nullable Device device) { |
| return device != null && ID_PREFIX_WEAR_ROUND.equals(device.getId()); |
| } |
| |
| /** |
| * Whether the given device is a TV device |
| */ |
| public static boolean isTv(@Nullable Device device) { |
| return device != null && device.getId().startsWith(ID_PREFIX_TV); |
| } |
| |
| /** |
| * Returns the rank of the given nexus device. This can be used to order |
| * the devices chronologically. |
| * |
| * @param device the device to look up the rank for |
| * @return the rank of the device |
| */ |
| public static int nexusRank(Device device) { |
| String id = device.getId(); |
| if (id.equals("Nexus One")) { //$NON-NLS-1$ |
| return 1; |
| } |
| if (id.equals("Nexus S")) { //$NON-NLS-1$ |
| return 2; |
| } |
| if (id.equals("Galaxy Nexus")) { //$NON-NLS-1$ |
| return 3; |
| } |
| if (id.equals("Nexus 7")) { //$NON-NLS-1$ |
| return 4; // 2012 version |
| } |
| if (id.equals("Nexus 10")) { //$NON-NLS-1$ |
| return 5; |
| } |
| if (id.equals("Nexus 4")) { //$NON-NLS-1$ |
| return 6; |
| } |
| if (id.equals("Nexus 7 2013")) { //$NON-NLS-1$ |
| return 7; |
| } |
| if (id.equals("Nexus 5")) { //$NON-NLS-1$ |
| return 8; |
| } |
| if (id.equals("Nexus 9")) { //$NON-NLS-1$ |
| return 9; |
| } |
| if (id.equals("Nexus 6")) { //$NON-NLS-1$ |
| return 10; |
| } |
| |
| return 100; // devices released in the future? |
| } |
| |
| /** |
| * Sorts the given list of Nexus devices according to rank |
| * @param list the list to sort |
| */ |
| public static void sortNexusList(@NonNull List<Device> list) { |
| Collections.sort(list, new Comparator<Device>() { |
| @Override |
| public int compare(Device device1, Device device2) { |
| // Descending order of age |
| return nexusRank(device2) - nexusRank(device1); |
| } |
| }); |
| } |
| } |