Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2017 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 package com.android.compatibility.common.util;
     17 
     18 import com.android.tradefed.device.DeviceNotAvailableException;
     19 import com.android.tradefed.device.ITestDevice;
     20 
     21 import java.util.HashMap;
     22 import java.util.Map;
     23 import java.util.regex.Matcher;
     24 import java.util.regex.Pattern;
     25 
     26 /**
     27  * Host-side utility class for reading properties and gathering information for testing
     28  * Android device compatibility.
     29  */
     30 public class PropertyUtil {
     31 
     32     /**
     33      * Name of read-only property detailing the first API level for which the product was
     34      * shipped. Property should be undefined for factory ROM products.
     35      */
     36     public static final String FIRST_API_LEVEL = "ro.product.first_api_level";
     37     private static final String BUILD_TAGS_PROPERTY = "ro.build.tags";
     38     private static final String BUILD_TYPE_PROPERTY = "ro.build.type";
     39     private static final String MANUFACTURER_PROPERTY = "ro.product.manufacturer";
     40     private static final String TAG_DEV_KEYS = "dev-keys";
     41 
     42     public static final String GOOGLE_SETTINGS_QUERY =
     43             "content query --uri content://com.google.settings/partner";
     44 
     45     /** Returns whether the device build is a user build */
     46     public static boolean isUserBuild(ITestDevice device) throws DeviceNotAvailableException {
     47         return propertyEquals(device, BUILD_TYPE_PROPERTY, "user");
     48     }
     49 
     50     /** Returns whether the device build is the factory ROM */
     51     public static boolean isFactoryROM(ITestDevice device) throws DeviceNotAvailableException {
     52         // first API level property should be undefined if and only if the product is factory ROM.
     53         return device.getProperty(FIRST_API_LEVEL) == null;
     54     }
     55 
     56     /** Returns whether this build is built with dev-keys */
     57     public static boolean isDevKeysBuild(ITestDevice device) throws DeviceNotAvailableException {
     58         String buildTags = device.getProperty(BUILD_TAGS_PROPERTY);
     59         for (String tag : buildTags.split(",")) {
     60             if (TAG_DEV_KEYS.equals(tag.trim())) {
     61                 return true;
     62             }
     63         }
     64         return false;
     65     }
     66 
     67     /**
     68      * Return the first API level for this product. If the read-only property is unset,
     69      * this means the first API level is the current API level, and the current API level
     70      * is returned.
     71      */
     72     public static int getFirstApiLevel(ITestDevice device) throws DeviceNotAvailableException {
     73         String propString = device.getProperty(FIRST_API_LEVEL);
     74         return (propString == null) ? device.getApiLevel() : Integer.parseInt(propString);
     75     }
     76 
     77     /**
     78      * Return the manufacturer of this product. If unset, return null.
     79      */
     80     public static String getManufacturer(ITestDevice device) throws DeviceNotAvailableException {
     81         return device.getProperty(MANUFACTURER_PROPERTY);
     82     }
     83 
     84     /** Returns a mapping from client ID names to client ID values */
     85     public static Map<String, String> getClientIds(ITestDevice device)
     86             throws DeviceNotAvailableException {
     87         Map<String,String> clientIds = new HashMap<>();
     88         String queryOutput = device.executeShellCommand(GOOGLE_SETTINGS_QUERY);
     89         for (String line : queryOutput.split("[\\r?\\n]+")) {
     90             // Expected line format: "Row: 1 _id=123, name=<property_name>, value=<property_value>"
     91             Pattern pattern = Pattern.compile("name=([a-z_]*), value=(.*)$");
     92             Matcher matcher = pattern.matcher(line);
     93             if (matcher.find()) {
     94                 String name = matcher.group(1);
     95                 String value = matcher.group(2);
     96                 if (name.contains("client_id")) {
     97                     clientIds.put(name, value); // only add name-value pair for client ids
     98                 }
     99             }
    100         }
    101         return clientIds;
    102     }
    103 
    104     /** Returns whether the property exists on this device */
    105     public static boolean propertyExists(ITestDevice device, String property)
    106             throws DeviceNotAvailableException {
    107         return device.getProperty(property) != null;
    108     }
    109 
    110     /** Returns whether the property value is equal to a given string */
    111     public static boolean propertyEquals(ITestDevice device, String property, String value)
    112             throws DeviceNotAvailableException {
    113         if (value == null) {
    114             return !propertyExists(device, property); // null value implies property does not exist
    115         }
    116         return value.equals(device.getProperty(property));
    117     }
    118 
    119     /**
    120      * Returns whether the property value matches a given regular expression. The method uses
    121      * String.matches(), requiring a complete match (i.e. expression matches entire value string)
    122      */
    123     public static boolean propertyMatches(ITestDevice device, String property, String regex)
    124             throws DeviceNotAvailableException {
    125         if (regex == null || regex.isEmpty()) {
    126             // null or empty pattern implies property does not exist
    127             return !propertyExists(device, property);
    128         }
    129         String value = device.getProperty(property);
    130         return (value == null) ? false : value.matches(regex);
    131     }
    132 }
    133