1 /* 2 * Copyright (c) 2017 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you 5 * may not use this file except in compliance with the License. You may 6 * 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 13 * implied. See the License for the specific language governing 14 * permissions and limitations under the License. 15 */ 16 17 package com.android.vts.entity; 18 19 import com.android.vts.proto.VtsReportMessage.AndroidDeviceInfoMessage; 20 import com.google.appengine.api.datastore.Entity; 21 import com.google.appengine.api.datastore.Key; 22 import java.util.logging.Level; 23 import java.util.logging.Logger; 24 25 /** Class describing a device used for a test run. */ 26 public class DeviceInfoEntity implements DashboardEntity { 27 protected static final Logger logger = Logger.getLogger(DeviceInfoEntity.class.getName()); 28 29 public static final String KIND = "DeviceInfo"; 30 31 // Property keys 32 public static final String BRANCH = "branch"; 33 public static final String PRODUCT = "product"; 34 public static final String BUILD_FLAVOR = "buildFlavor"; 35 public static final String BUILD_ID = "buildId"; 36 public static final String ABI_BITNESS = "abiBitness"; 37 public static final String ABI_NAME = "abiName"; 38 39 private final Key parentKey; 40 41 public final String branch; 42 public final String product; 43 public final String buildFlavor; 44 public final String buildId; 45 public final String abiBitness; 46 public final String abiName; 47 48 /** 49 * Create a DeviceInfoEntity object. 50 * 51 * @param parentKey The key for the parent entity in the database. 52 * @param branch The build branch. 53 * @param product The device product. 54 * @param buildFlavor The device build flavor. 55 * @param buildID The device build ID. 56 * @param abiBitness The abi bitness of the device. 57 * @param abiName The name of the abi. 58 */ 59 public DeviceInfoEntity(Key parentKey, String branch, String product, String buildFlavor, 60 String buildID, String abiBitness, String abiName) { 61 this.parentKey = parentKey; 62 this.branch = branch; 63 this.product = product; 64 this.buildFlavor = buildFlavor; 65 this.buildId = buildID; 66 this.abiBitness = abiBitness; 67 this.abiName = abiName; 68 } 69 70 @Override 71 public Entity toEntity() { 72 Entity deviceEntity = new Entity(KIND, this.parentKey); 73 deviceEntity.setProperty(BRANCH, this.branch.toLowerCase()); 74 deviceEntity.setProperty(PRODUCT, this.product.toLowerCase()); 75 deviceEntity.setProperty(BUILD_FLAVOR, this.buildFlavor.toLowerCase()); 76 deviceEntity.setProperty(BUILD_ID, this.buildId.toLowerCase()); 77 if (this.abiBitness != null && this.abiName != null) { 78 deviceEntity.setUnindexedProperty(ABI_BITNESS, this.abiBitness.toLowerCase()); 79 deviceEntity.setUnindexedProperty(ABI_NAME, this.abiName.toLowerCase()); 80 } 81 82 return deviceEntity; 83 } 84 85 /** 86 * Convert an Entity object to a DeviceInfoEntity. 87 * 88 * @param e The entity to process. 89 * @return DeviceInfoEntity object with the properties from e, or null if incompatible. 90 */ 91 public static DeviceInfoEntity fromEntity(Entity e) { 92 if (!e.getKind().equals(KIND) || !e.hasProperty(BRANCH) || !e.hasProperty(PRODUCT) 93 || !e.hasProperty(BUILD_FLAVOR) || !e.hasProperty(BUILD_ID) 94 || !e.hasProperty(ABI_BITNESS) || !e.hasProperty(ABI_NAME)) { 95 logger.log(Level.WARNING, "Missing device info attributes in entity: " + e.toString()); 96 return null; 97 } 98 try { 99 Key parentKey = e.getKey().getParent(); 100 String branch = (String) e.getProperty(BRANCH); 101 String product = (String) e.getProperty(PRODUCT); 102 String buildFlavor = (String) e.getProperty(BUILD_FLAVOR); 103 String buildId = (String) e.getProperty(BUILD_ID); 104 String abiBitness = null; 105 String abiName = null; 106 if (e.hasProperty(ABI_BITNESS) && e.hasProperty(ABI_NAME)) { 107 abiBitness = (String) e.getProperty(ABI_BITNESS); 108 abiName = (String) e.getProperty(ABI_NAME); 109 } 110 return new DeviceInfoEntity( 111 parentKey, branch, product, buildFlavor, buildId, abiBitness, abiName); 112 } catch (ClassCastException exception) { 113 // Invalid cast 114 logger.log(Level.WARNING, "Error parsing device info entity.", exception); 115 } 116 return null; 117 } 118 119 /** 120 * Convert a device info message to a DeviceInfoEntity. 121 * 122 * @param parentKey The ancestor key for the device entity. 123 * @param device The device info report describing the target Android device. 124 * @return The DeviceInfoEntity for the target device, or null if incompatible 125 */ 126 public static DeviceInfoEntity fromDeviceInfoMessage( 127 Key parentKey, AndroidDeviceInfoMessage device) { 128 if (!device.hasBuildAlias() || !device.hasBuildFlavor() || !device.hasProductVariant() 129 || !device.hasBuildId()) { 130 return null; 131 } 132 String branch = device.getBuildAlias().toStringUtf8(); 133 String buildFlavor = device.getBuildFlavor().toStringUtf8(); 134 String product = device.getProductVariant().toStringUtf8(); 135 String buildId = device.getBuildId().toStringUtf8(); 136 String abiBitness = device.getAbiBitness().toStringUtf8(); 137 String abiName = device.getAbiName().toStringUtf8(); 138 return new DeviceInfoEntity( 139 parentKey, branch, product, buildFlavor, buildId, abiBitness, abiName); 140 } 141 142 @Override 143 public boolean equals(Object obj) { 144 if (!(obj instanceof DeviceInfoEntity)) { 145 return false; 146 } 147 DeviceInfoEntity device2 = (DeviceInfoEntity) obj; 148 if (!this.branch.equals(device2.branch) || !this.product.equals(device2.product) 149 || !this.buildFlavor.equals(device2.buildFlavor) 150 || !this.buildId.equals(device2.buildId)) { 151 return false; 152 } 153 return true; 154 } 155 156 @Override 157 public int hashCode() { 158 String deviceId = this.branch + this.product + this.buildFlavor + this.buildId; 159 return deviceId.hashCode(); 160 } 161 162 /** 163 * Create a copy of the device info under a near parent. 164 * @param parentKey The new parent key. 165 * @return A copy of the DeviceInfoEntity with the specified parent. 166 */ 167 public DeviceInfoEntity copyWithParent(Key parentKey) { 168 return new DeviceInfoEntity(parentKey, this.branch, this.product, this.buildFlavor, 169 this.buildId, this.abiBitness, this.abiName); 170 } 171 172 /** 173 * Create a string representation of the device build information. 174 * @return A String fingerprint of the format: branch/buildFlavor (build ID) 175 */ 176 public String getFingerprint() { 177 return this.branch + "/" + this.buildFlavor + " (" + this.buildId + ")"; 178 } 179 } 180