public final class

PropertyUtils

extends java.lang.Object

 java.lang.Object

↳androidx.car.app.hardware.common.PropertyUtils

Gradle dependencies

compile group: 'androidx.car.app', name: 'app-automotive', version: '1.2.0-rc01'

  • groupId: androidx.car.app
  • artifactId: app-automotive
  • version: 1.2.0-rc01

Artifact androidx.car.app:app-automotive:1.2.0-rc01 it located at Google repository (https://maven.google.com/)

Overview

Utility functions to work with

Summary

Methods
public static intcovertDistanceUnit(int vehicleUnit)

Maps distance units in car service to distance units in CarUnit.

public static intcovertEvConnectorType(int vehicleEvConnectorType)

Maps EV connector types in car service to types in EnergyProfile.

public static intcovertSpeedUnit(int vehicleUnit)

Maps speed units in car service to speed units in CarUnit.

public static intcovertVolumeUnit(int vehicleUnit)

Maps volume units in car service to volume units in CarUnit.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

public static int covertSpeedUnit(int vehicleUnit)

Maps speed units in car service to speed units in CarUnit.

public static int covertDistanceUnit(int vehicleUnit)

Maps distance units in car service to distance units in CarUnit.

public static int covertVolumeUnit(int vehicleUnit)

Maps volume units in car service to volume units in CarUnit.

public static int covertEvConnectorType(int vehicleEvConnectorType)

Maps EV connector types in car service to types in EnergyProfile.

Source

/*
 * Copyright 2021 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 androidx.car.app.hardware.common;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.car.app.hardware.common.CarUnit.IMPERIAL_GALLON;
import static androidx.car.app.hardware.common.CarUnit.LITER;
import static androidx.car.app.hardware.common.CarUnit.MILLILITER;
import static androidx.car.app.hardware.common.CarUnit.US_GALLON;

import android.car.Car;
import android.car.VehiclePropertyIds;
import android.car.hardware.CarPropertyValue;
import android.util.Pair;
import android.util.SparseArray;

import androidx.annotation.OptIn;
import androidx.annotation.RestrictTo;
import androidx.car.app.annotations.ExperimentalCarApi;
import androidx.car.app.hardware.info.AutomotiveCarInfo;
import androidx.car.app.hardware.info.EnergyProfile;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Utility functions to work with {@link android.car.hardware.CarPropertyValue}
 *
 * @hide
 */
@RestrictTo(LIBRARY)
public final class PropertyUtils {
    // System level permission in car-lib for read car' mileage.
    private static final String CAR_PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";

    // System level permission in car-lib for reading car tire pressures.
    private static final String CAR_PERMISSION_TIRES = "android.car.permission.CAR_TIRES";

    // System level permission in car-lib for setting range remaining value for cars.
    private static final String CAR_PERMISSION_ADJUST_RANGE_REMAINING =
            "android.car.permission.ADJUST_RANGE_REMAINING";

    // System level permission in car-lib for controlling car's energy ports.
    private static final String CAR_PERMISSION_CONTROL_CAR_ENERGY_PORTS =
            "android.car.permission.CONTROL_CAR_ENERGY_PORTS";

    // Index key is property id, value is the permission to read property.
    private static final SparseArray<String> PERMISSION_READ_PROPERTY = new SparseArray<String>() {
        {
            append(VehiclePropertyIds.INFO_VIN, Car.PERMISSION_IDENTIFICATION);
            append(VehiclePropertyIds.INFO_MAKE, Car.PERMISSION_CAR_INFO);
            append(VehiclePropertyIds.INFO_MODEL, Car.PERMISSION_CAR_INFO);
            append(VehiclePropertyIds.INFO_MODEL_YEAR, Car.PERMISSION_CAR_INFO);
            append(VehiclePropertyIds.INFO_FUEL_CAPACITY, Car.PERMISSION_CAR_INFO);
            append(VehiclePropertyIds.INFO_FUEL_TYPE, Car.PERMISSION_CAR_INFO);
            append(VehiclePropertyIds.INFO_EV_BATTERY_CAPACITY, Car.PERMISSION_CAR_INFO);
            append(VehiclePropertyIds.INFO_EV_CONNECTOR_TYPE, Car.PERMISSION_CAR_INFO);
            append(VehiclePropertyIds.INFO_DRIVER_SEAT, Car.PERMISSION_CAR_INFO);
            append(AutomotiveCarInfo.TOLL_CARD_STATUS_ID, Car.PERMISSION_CAR_INFO);
            append(AutomotiveCarInfo.SPEED_DISPLAY_UNIT_ID, Car.PERMISSION_READ_DISPLAY_UNITS);
            append(VehiclePropertyIds.DISTANCE_DISPLAY_UNITS, Car.PERMISSION_READ_DISPLAY_UNITS);
            // CAR_MILEAGE is system permission
            append(VehiclePropertyIds.PERF_ODOMETER, CAR_PERMISSION_MILEAGE);
            append(VehiclePropertyIds.PERF_VEHICLE_SPEED, Car.PERMISSION_SPEED);
            append(VehiclePropertyIds.PERF_VEHICLE_SPEED_DISPLAY, Car.PERMISSION_SPEED);
            append(VehiclePropertyIds.WHEEL_TICK, Car.PERMISSION_SPEED);
            append(VehiclePropertyIds.FUEL_LEVEL, Car.PERMISSION_ENERGY);
            append(VehiclePropertyIds.FUEL_LEVEL_LOW, Car.PERMISSION_ENERGY);
            append(VehiclePropertyIds.EV_BATTERY_LEVEL, Car.PERMISSION_ENERGY);
            append(VehiclePropertyIds.FUEL_DOOR_OPEN, Car.PERMISSION_ENERGY_PORTS);
            append(VehiclePropertyIds.EV_CHARGE_PORT_OPEN, Car.PERMISSION_ENERGY_PORTS);
            append(VehiclePropertyIds.EV_CHARGE_PORT_CONNECTED, Car.PERMISSION_ENERGY_PORTS);
            append(VehiclePropertyIds.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE,
                    Car.PERMISSION_ENERGY_PORTS);
            append(VehiclePropertyIds.RANGE_REMAINING, Car.PERMISSION_ENERGY);
            append(VehiclePropertyIds.TIRE_PRESSURE, CAR_PERMISSION_TIRES);
            append(VehiclePropertyIds.GEAR_SELECTION, Car.PERMISSION_POWERTRAIN);
            append(VehiclePropertyIds.CURRENT_GEAR, Car.PERMISSION_POWERTRAIN);
            append(VehiclePropertyIds.PARKING_BRAKE_ON, Car.PERMISSION_POWERTRAIN);
            append(VehiclePropertyIds.PARKING_BRAKE_AUTO_APPLY, Car.PERMISSION_POWERTRAIN);
            append(VehiclePropertyIds.FUEL_VOLUME_DISPLAY_UNITS, Car.PERMISSION_READ_DISPLAY_UNITS);
        }
    };

    // Permissions for writing properties. They are system level permissions.
    private static final SparseArray<String> PERMISSION_WRITE_PROPERTY = new SparseArray<String>() {
        {
            append(VehiclePropertyIds.FUEL_DOOR_OPEN, CAR_PERMISSION_CONTROL_CAR_ENERGY_PORTS);
            append(VehiclePropertyIds.EV_CHARGE_PORT_OPEN, CAR_PERMISSION_CONTROL_CAR_ENERGY_PORTS);
            append(VehiclePropertyIds.RANGE_REMAINING, CAR_PERMISSION_ADJUST_RANGE_REMAINING);
        }
    };
    private static final Set<Integer> ON_CHANGE_PROPERTIES =
            new HashSet<>(Arrays.asList(VehiclePropertyIds.FUEL_LEVEL_LOW,
                    AutomotiveCarInfo.TOLL_CARD_STATUS_ID,
                    AutomotiveCarInfo.SPEED_DISPLAY_UNIT_ID,
                    VehiclePropertyIds.DISTANCE_DISPLAY_UNITS));

    // VehicleArea:MASK in vehicle/2.0/types.hal
    private static final int VEHICLE_AREA_MASK = 0x0f000000;

    // VehicleArea:GLOBAL in vehicle/2.0/types.hal
    private static final int VEHICLE_AREA_GLOBAL = 0x01000000;

    // VehicleUnit.METER_PER_SEC in car service
    private static final int VEHICLE_UNIT_METER_PER_SEC = 0x01;

    // VehicleUnit.MILES_PER_HOUR in car service
    private static final int VEHICLE_UNIT_MILES_PER_HOUR = 0x90;

    // VehicleUnit.KILOMETERS_PER_HOUR in car service
    private static final int VEHICLE_UNIT_KILOMETERS_PER_HOUR = 0x91;

    // VehicleUnit.MILLIMETER in car service
    private static final int VEHICLE_UNIT_MILLIMETER = 0x20;

    // VehicleUnit.METER in car service
    private static final int VEHICLE_UNIT_METER = 0x21;

    // VehicleUnit.KILOMETER in car service
    private static final int VEHICLE_UNIT_KILOMETER = 0x23;

    // VehicleUnit.MILE in car service
    private static final int VEHICLE_UNIT_MILE = 0x24;

    // VehicleUnit.MILLIMETER in car service
    private static final int VEHICLE_UNIT_MILLILITER = 0x40;

    // VehicleUnit.LITER in car service
    private static final int VEHICLE_UNIT_VOLUME_LITER = 0x41;

    // VehicleUnit.US_GALLON in car service
    private static final int VEHICLE_UNIT_VOLUME_US_GALLON = 0x42;

    // VehicleUnit.IMPERIAL_GALLON in car service
    private static final int VEHICLE_UNIT_VOLUME_IMPERIAL_GALLON = 0x43;

    /**
     * Maps speed units in car service to speed units in {@link CarUnit}.
     */
    public static @CarUnit.CarSpeedUnit int covertSpeedUnit(int vehicleUnit) {
        switch (vehicleUnit) {
            case VEHICLE_UNIT_METER_PER_SEC:
                return CarUnit.METERS_PER_SEC;
            case VEHICLE_UNIT_MILES_PER_HOUR:
                return CarUnit.MILES_PER_HOUR;
            case VEHICLE_UNIT_KILOMETERS_PER_HOUR:
                return CarUnit.KILOMETERS_PER_HOUR;
            default:
                throw new IllegalArgumentException("Invalid speed unit: " + vehicleUnit);
        }
    }

    /**
     * Maps distance units in car service to distance units in {@link CarUnit}.
     */
    public static @CarUnit.CarDistanceUnit int covertDistanceUnit(int vehicleUnit) {
        switch (vehicleUnit) {
            case VEHICLE_UNIT_METER:
                return CarUnit.METER;
            case VEHICLE_UNIT_MILE:
                return CarUnit.MILE;
            case VEHICLE_UNIT_MILLIMETER:
                return CarUnit.MILLIMETER;
            case VEHICLE_UNIT_KILOMETER:
                return CarUnit.KILOMETER;
            default:
                throw new IllegalArgumentException("Invalid display unit: " + vehicleUnit);
        }
    }

    /**
     * Maps volume units in car service to volume units in {@link CarUnit}.
     */
    // TODO(b/202303614): Remove this annotation once FuelVolumeDisplayUnit is ready.
    @OptIn(markerClass = ExperimentalCarApi.class)
    public static @CarUnit.CarVolumeUnit int covertVolumeUnit(int vehicleUnit) {
        switch (vehicleUnit) {
            case VEHICLE_UNIT_MILLILITER:
                return MILLILITER;
            case VEHICLE_UNIT_VOLUME_LITER:
                return LITER;
            case VEHICLE_UNIT_VOLUME_US_GALLON:
                return US_GALLON;
            case VEHICLE_UNIT_VOLUME_IMPERIAL_GALLON:
                return IMPERIAL_GALLON;
            default:
                throw new IllegalArgumentException("Invalid volume unit: " + vehicleUnit);
        }
    }

    /**
     * Maps EV connector types in car service to types in {@link EnergyProfile}.
     */
    public static @EnergyProfile.EvConnectorType int covertEvConnectorType(
            int vehicleEvConnectorType) {
        switch (vehicleEvConnectorType) {
            case 1: // IEC_TYPE_1_AC
                return EnergyProfile.EVCONNECTOR_TYPE_J1772;
            case 2: // IEC_TYPE_2_AC
                return EnergyProfile.EVCONNECTOR_TYPE_MENNEKES;
            case 3: // IEC_TYPE_3_AC
                return EnergyProfile.EVCONNECTOR_TYPE_SCAME;
            case 4: // IEC_TYPE_4_DC
                return EnergyProfile.EVCONNECTOR_TYPE_CHADEMO;
            case 5: // IEC_TYPE_1_CCS_DC
                return EnergyProfile.EVCONNECTOR_TYPE_COMBO_1;
            case 6: // IEC_TYPE_2_CCS_DC
                return EnergyProfile.EVCONNECTOR_TYPE_COMBO_2;
            case 7: // TESLA_ROADSTER
                return EnergyProfile.EVCONNECTOR_TYPE_TESLA_ROADSTER;
            case 8: // TESLA_HPWC
                return EnergyProfile.EVCONNECTOR_TYPE_TESLA_HPWC;
            case 9: // TESLA_SUPERCHARGER
                return EnergyProfile.EVCONNECTOR_TYPE_TESLA_SUPERCHARGER;
            case 10: // GBT_AC
                return EnergyProfile.EVCONNECTOR_TYPE_GBT;
            case 11: // GBT_DC
                return EnergyProfile.EVCONNECTOR_TYPE_GBT_DC;
            case 101: // OTHER
                return EnergyProfile.EVCONNECTOR_TYPE_OTHER;
            default:
                return EnergyProfile.EVCONNECTOR_TYPE_UNKNOWN;
        }
    }

    /**
     * Returns a {@link Set<String>} that contains permissions for reading properties.
     *
     * @throws SecurityException if android application cannot access the property
     */
    static Set<String> getReadPermissionsByPropertyIds(List<Integer> requestList) {
        Set<String> permissions = new HashSet<>();
        for (int propertyId : requestList) {
            String permissionString =
                    PERMISSION_READ_PROPERTY.get(propertyId, null);
            if (permissionString == null) {
                throw new SecurityException(
                        "Application cannot get permission for reading property: " + propertyId);
            }
            permissions.add(permissionString);
        }
        return permissions;
    }

    /**
     * Returns a {@link Set<String>} that contains permissions for setting properties.
     *
     * @throws SecurityException if android application cannot set value for property
     */
    static Set<String> getWritePermissions(List<Pair<Integer, Integer>> props) {
        Set<String> permissions = new HashSet<>();
        for (Pair<Integer, Integer> prop : props) {
            String permissionString = PERMISSION_WRITE_PROPERTY.get(prop.first, null);
            if (permissionString == null) {
                throw new SecurityException(
                        "Application cannot get permission for setting property: "
                                + prop.first);
            }
            permissions.add(permissionString);
        }
        return permissions;
    }

    /**
     * Returns {@code true} if the property is
     * {@link android.car.VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL} property.
     */
    static boolean isGlobalProperty(int propertyId) {
        return (propertyId & VEHICLE_AREA_MASK) == VEHICLE_AREA_GLOBAL;
    }

    /**
     * Returns true if the property has change mode as
     * {@link android.car.hardware.CarPropertyConfig#VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE}.
     */
    static boolean isOnChangeProperty(int propertyId) {
        return ON_CHANGE_PROPERTIES.contains(propertyId);
    }

    /**
     * Maps from status in {@link CarPropertyValue.PropertyStatus} to status
     * in {@link CarValue.StatusCode}.
     */
    static @CarValue.StatusCode int mapToStatusCodeInCarValue(int carPropertyStatus) {
        switch (carPropertyStatus) {
            case CarPropertyValue.STATUS_AVAILABLE:
                return CarValue.STATUS_SUCCESS;
            case CarPropertyValue.STATUS_ERROR:
                // TODO(b/191932488): add status_error in CarValue.
                return CarValue.STATUS_UNKNOWN;
            case CarPropertyValue.STATUS_UNAVAILABLE:
                return CarValue.STATUS_UNAVAILABLE;
            default:
                throw new IllegalArgumentException("Invalid car property status: "
                        + carPropertyStatus);
        }
    }

    private PropertyUtils() {
    }
}