Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0aa4a469 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "RTT LCI API (Client Side)"

parents ecc418c4 b1772f92
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -30577,6 +30577,7 @@ package android.net.wifi.rtt {
    method public int getNumSuccessfulMeasurements();
    method @Nullable public android.net.wifi.aware.PeerHandle getPeerHandle();
    method public long getRangingTimestampMillis();
    method @Nullable public android.net.wifi.rtt.ResponderLocation getResponderLocation();
    method public int getRssi();
    method public int getStatus();
    method public void writeToParcel(android.os.Parcel, int);
@@ -30594,6 +30595,64 @@ package android.net.wifi.rtt {
    field public static final int STATUS_CODE_FAIL_RTT_NOT_AVAILABLE = 2; // 0x2
  }
  public final class ResponderLocation implements android.os.Parcelable {
    method public int describeContents();
    method public double getAltitude();
    method public int getAltitudeType();
    method public double getAltitudeUncertainty();
    method public java.util.List<android.net.MacAddress> getColocatedBssids();
    method public int getDatum();
    method public int getExpectedToMove();
    method public double getLatitude();
    method public double getLatitudeUncertainty();
    method public int getLciFlags();
    method public double getLongitude();
    method public double getLongitudeUncertainty();
    method public int getMapImageType();
    method @Nullable public java.net.URL getMapImageUrl();
    method public double getStaFloorNumber();
    method public double getStaHeightAboveFloorMeters();
    method public double getStaHeightAboveFloorUncertaintyMeters();
    method public boolean isLciSubelementValid();
    method public boolean isZsubelementValid();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int ALTITUDE_FLOORS = 2; // 0x2
    field public static final int ALTITUDE_METERS = 1; // 0x1
    field public static final int ALTITUDE_UNDEFINED = 0; // 0x0
    field public static final android.os.Parcelable.Creator<android.net.wifi.rtt.ResponderLocation> CREATOR;
    field public static final int DATUM_NAD83_MLLW = 3; // 0x3
    field public static final int DATUM_NAD83_NAV88 = 2; // 0x2
    field public static final int DATUM_UNDEFINED = 0; // 0x0
    field public static final int DATUM_WGS84 = 1; // 0x1
    field public static final int LCI_FLAGS_MASK_DEPENDENT_STA = 4; // 0x4
    field public static final int LCI_FLAGS_MASK_REGLOC_AGREEMENT = 16; // 0x10
    field public static final int LCI_FLAGS_MASK_REGLOC_DSE = 8; // 0x8
    field public static final int LCI_FLAGS_MASK_VERSION = 3; // 0x3
    field public static final int LCI_VERSION_1 = 1; // 0x1
    field public static final int LOCATION_FIXED = 0; // 0x0
    field public static final int LOCATION_MOVEMENT_UNKNOWN = 2; // 0x2
    field public static final int LOCATION_RESERVED = 3; // 0x3
    field public static final int LOCATION_VARIABLE = 1; // 0x1
    field public static final int MAP_TYPE_BMP = 12; // 0xc
    field public static final int MAP_TYPE_CAD = 8; // 0x8
    field public static final int MAP_TYPE_DWF = 7; // 0x7
    field public static final int MAP_TYPE_DWG = 6; // 0x6
    field public static final int MAP_TYPE_DXF = 5; // 0x5
    field public static final int MAP_TYPE_GIF = 2; // 0x2
    field public static final int MAP_TYPE_GML = 10; // 0xa
    field public static final int MAP_TYPE_ICO = 17; // 0x11
    field public static final int MAP_TYPE_JPG = 3; // 0x3
    field public static final int MAP_TYPE_KML = 11; // 0xb
    field public static final int MAP_TYPE_PGM = 13; // 0xd
    field public static final int MAP_TYPE_PNG = 1; // 0x1
    field public static final int MAP_TYPE_PPM = 14; // 0xe
    field public static final int MAP_TYPE_SVG = 4; // 0x4
    field public static final int MAP_TYPE_TIFF = 9; // 0x9
    field public static final int MAP_TYPE_URL_DEFINED = 0; // 0x0
    field public static final int MAP_TYPE_XBM = 15; // 0xf
    field public static final int MAP_TYPE_XPM = 16; // 0x10
  }
  public class WifiRttManager {
    method public boolean isAvailable();
    method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.ACCESS_WIFI_STATE}) public void startRanging(@NonNull android.net.wifi.rtt.RangingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.rtt.RangingResultCallback);
+4 −0
Original line number Diff line number Diff line
@@ -4943,6 +4943,10 @@ package android.net.wifi.rtt {
    field public final boolean supports80211mc;
  }
  public final class ResponderLocation implements android.os.Parcelable {
    method public boolean getExtraInfoOnAssociationIndication();
  }
  public class WifiRttManager {
    method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE}) public void cancelRanging(@Nullable android.os.WorkSource);
    method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.ACCESS_WIFI_STATE}) public void startRanging(@Nullable android.os.WorkSource, @NonNull android.net.wifi.rtt.RangingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.rtt.RangingResultCallback);
+323 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 android.net.wifi.rtt;

import android.annotation.Nullable;
import android.location.Address;
import android.net.wifi.rtt.CivicLocationKeys.CivicLocationKeysType;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;
import android.util.SparseArray;

import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Objects;

/**
 * Decodes the Type Length Value (TLV) elements found in a Location Civic Record as defined by IEEE
 * P802.11-REVmc/D8.0 section 9.4.2.22.13 using the format described in IETF RFC 4776.
 *
 * <p>The TLVs each define a key, value pair for a civic address type such as apt, street, city,
 * county, and country. The class provides a general getter method to extract a value for an element
 * key, returning null if not set.
 *
 * @hide
 */
public final class CivicLocation implements Parcelable {
    // Address (class) line indexes
    private static final int ADDRESS_LINE_0_ROOM_DESK_FLOOR = 0;
    private static final int ADDRESS_LINE_1_NUMBER_ROAD_SUFFIX_APT = 1;
    private static final int ADDRESS_LINE_2_CITY = 2;
    private static final int ADDRESS_LINE_3_STATE_POSTAL_CODE = 3;
    private static final int ADDRESS_LINE_4_COUNTRY = 4;

    // Buffer management
    private static final int MIN_CIVIC_BUFFER_SIZE = 3;
    private static final int MAX_CIVIC_BUFFER_SIZE = 256;
    private static final int COUNTRY_CODE_LENGTH = 2;
    private static final int BYTE_MASK = 0xFF;
    private static final int TLV_TYPE_INDEX = 0;
    private static final int TLV_LENGTH_INDEX = 1;
    private static final int TLV_VALUE_INDEX = 2;

    private final boolean mIsValid;
    private final String mCountryCode; // Two character country code (ISO 3166 standard).
    private SparseArray<String> mCivicAddressElements =
            new SparseArray<>(MIN_CIVIC_BUFFER_SIZE);


    /**
     * Constructor
     *
     * @param civicTLVs    a byte buffer containing parameters in the form type, length, value
     * @param countryCode the two letter code defined by the ISO 3166 standard
     *
     * @hide
     */
    public CivicLocation(@Nullable byte[] civicTLVs, @Nullable String countryCode) {
        this.mCountryCode = countryCode;
        if (countryCode == null || countryCode.length() != COUNTRY_CODE_LENGTH) {
            this.mIsValid = false;
            return;
        }
        boolean isValid = false;
        if (civicTLVs != null
                && civicTLVs.length >= MIN_CIVIC_BUFFER_SIZE
                && civicTLVs.length < MAX_CIVIC_BUFFER_SIZE) {
            isValid = parseCivicTLVs(civicTLVs);
        }

        mIsValid = isValid;
    }

    private CivicLocation(Parcel in) {
        mIsValid = in.readByte() != 0;
        mCountryCode = in.readString();
        mCivicAddressElements = in.readSparseArray(this.getClass().getClassLoader());
    }

    public static final Creator<CivicLocation> CREATOR = new Creator<CivicLocation>() {
        @Override
        public CivicLocation createFromParcel(Parcel in) {
            return new CivicLocation(in);
        }

        @Override
        public CivicLocation[] newArray(int size) {
            return new CivicLocation[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeByte((byte) (mIsValid ? 1 : 0));
        parcel.writeString(mCountryCode);
        parcel.writeSparseArray((android.util.SparseArray) mCivicAddressElements);
    }

    /**
     * Check TLV format and store TLV key/value pairs in this object so they can be queried by key.
     *
     * @param civicTLVs the buffer of TLV elements
     * @return a boolean indicating success of the parsing process
     */
    private boolean parseCivicTLVs(byte[] civicTLVs) {
        int bufferPtr = 0;
        int bufferLength = civicTLVs.length;

        // Iterate through the sub-elements contained in the LCI IE checking the accumulated
        // element lengths do not overflow the total buffer length
        while (bufferPtr < bufferLength) {
            int civicAddressType = civicTLVs[bufferPtr + TLV_TYPE_INDEX] & BYTE_MASK;
            int civicAddressTypeLength = civicTLVs[bufferPtr + TLV_LENGTH_INDEX];
            if (civicAddressTypeLength != 0) {
                if (bufferPtr + TLV_VALUE_INDEX + civicAddressTypeLength > bufferLength) {
                    return false;
                }
                mCivicAddressElements.put(civicAddressType,
                        new String(civicTLVs, bufferPtr + TLV_VALUE_INDEX,
                                civicAddressTypeLength, StandardCharsets.UTF_8));
            }
            bufferPtr += civicAddressTypeLength + TLV_VALUE_INDEX;
        }
        return true;
    }

    /**
     * Getter for the value of a civic Address element type.
     *
     * @param key an integer code for the element type key
     * @return the string value associated with that element type
     */
    @Nullable
    public String getCivicElementValue(@CivicLocationKeysType int key) {
        return mCivicAddressElements.get(key);
    }

    /**
     * Generates a comma separated string of all the defined elements.
     *
     * @return a compiled string representing all elements
     */
    @Override
    public String toString() {
        return mCivicAddressElements.toString();
    }

    /**
     * Converts Civic Location to the best effort Address Object.
     *
     * @return the {@link Address} object based on the Civic Location data
     */
    @Nullable
    public Address toAddress() {
        if (!mIsValid) {
            return null;
        }
        Address address = new Address(Locale.US);
        String room = formatAddressElement("Room: ", getCivicElementValue(CivicLocationKeys.ROOM));
        String desk =
                formatAddressElement(" Desk: ", getCivicElementValue(CivicLocationKeys.DESK));
        String floor =
                formatAddressElement(", Flr: ", getCivicElementValue(CivicLocationKeys.FLOOR));
        String houseNumber = formatAddressElement("", getCivicElementValue(CivicLocationKeys.HNO));
        String houseNumberSuffix =
                formatAddressElement("", getCivicElementValue(CivicLocationKeys.HNS));
        String road =
                formatAddressElement(" ", getCivicElementValue(
                        CivicLocationKeys.PRIMARY_ROAD_NAME));
        String roadSuffix = formatAddressElement(" ", getCivicElementValue(CivicLocationKeys.STS));
        String apt = formatAddressElement(", Apt: ", getCivicElementValue(CivicLocationKeys.APT));
        String city = formatAddressElement("", getCivicElementValue(CivicLocationKeys.CITY));
        String state = formatAddressElement("", getCivicElementValue(CivicLocationKeys.STATE));
        String postalCode =
                formatAddressElement(" ", getCivicElementValue(CivicLocationKeys.POSTAL_CODE));

        // Aggregation into common address format
        String addressLine0 =
                new StringBuilder().append(room).append(desk).append(floor).toString();
        String addressLine1 =
                new StringBuilder().append(houseNumber).append(houseNumberSuffix).append(road)
                        .append(roadSuffix).append(apt).toString();
        String addressLine2 = city;
        String addressLine3 = new StringBuilder().append(state).append(postalCode).toString();
        String addressLine4 = mCountryCode;

        // Setting Address object line fields by common convention.
        address.setAddressLine(ADDRESS_LINE_0_ROOM_DESK_FLOOR, addressLine0);
        address.setAddressLine(ADDRESS_LINE_1_NUMBER_ROAD_SUFFIX_APT, addressLine1);
        address.setAddressLine(ADDRESS_LINE_2_CITY, addressLine2);
        address.setAddressLine(ADDRESS_LINE_3_STATE_POSTAL_CODE, addressLine3);
        address.setAddressLine(ADDRESS_LINE_4_COUNTRY, addressLine4);

        // Other compatible fields between the CIVIC_ADDRESS and the Address Class.
        address.setFeatureName(getCivicElementValue(CivicLocationKeys.NAM)); // Structure name
        address.setSubThoroughfare(getCivicElementValue(CivicLocationKeys.HNO));
        address.setThoroughfare(getCivicElementValue(CivicLocationKeys.PRIMARY_ROAD_NAME));
        address.setSubLocality(getCivicElementValue(CivicLocationKeys.NEIGHBORHOOD));
        address.setSubAdminArea(getCivicElementValue(CivicLocationKeys.COUNTY));
        address.setAdminArea(getCivicElementValue(CivicLocationKeys.STATE));
        address.setPostalCode(getCivicElementValue(CivicLocationKeys.POSTAL_CODE));
        address.setCountryCode(mCountryCode); // Country
        return address;
    }

    /**
     * Prepares an address element so that it can be integrated into an address line convention.
     *
     * <p>If an address element is null, the return string will be empty e.g. "".
     *
     * @param label a string defining the type of address element
     * @param value a string defining the elements value
     * @return the formatted version of the value, with null values converted to empty strings
     */
    private String formatAddressElement(String label, String value) {
        if (value != null) {
            return label + value;
        } else {
            return "";
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof CivicLocation)) {
            return false;
        }
        CivicLocation other = (CivicLocation) obj;
        return mIsValid == other.mIsValid
                && Objects.equals(mCountryCode, other.mCountryCode)
                && isSparseArrayStringEqual(mCivicAddressElements, other.mCivicAddressElements);
    }

    @Override
    public int hashCode() {
        int[] civicAddressKeys = getSparseArrayKeys(mCivicAddressElements);
        String[] civicAddressValues = getSparseArrayValues(mCivicAddressElements);
        return Objects.hash(mIsValid, mCountryCode, civicAddressKeys, civicAddressValues);
    }

    /**
     * Tests if the Civic Location object is valid
     *
     * @return a boolean defining mIsValid
     */
    public boolean isValid() {
        return mIsValid;
    }

    /**
     * Tests if two sparse arrays are equal on a key for key basis
     *
     * @param sa1 the first sparse array
     * @param sa2 the second sparse array
     * @return the boolean result after comparing values key by key
     */
    private boolean isSparseArrayStringEqual(SparseArray<String> sa1, SparseArray<String> sa2) {
        int size = sa1.size();
        if (size != sa2.size()) {
            return false;
        }
        for (int i = 0; i < size; i++) {
            String sa1Value = sa1.valueAt(i);
            String sa2Value = sa2.valueAt(i);
            if (!sa1Value.equals(sa2Value)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Extract an array of all the keys in a SparseArray<String>
     *
     * @param sa the sparse array of Strings
     * @return an integer array of all keys in the SparseArray<String>
     */
    private int[] getSparseArrayKeys(SparseArray<String> sa) {
        int size = sa.size();
        int[] keys = new int[size];
        for (int i = 0; i < size; i++) {
            keys[i] = sa.keyAt(i);
        }
        return keys;
    }

    /**
     * Extract an array of all the String values in a SparseArray<String>
     *
     * @param sa the sparse array of Strings
     * @return a String array of all values in the SparseArray<String>
     */
    private String[] getSparseArrayValues(SparseArray<String> sa) {
        int size = sa.size();
        String[] values = new String[size];
        for (int i = 0; i < size; i++) {
            values[i] = sa.valueAt(i);
        }
        return values;
    }
}
+116 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 android.net.wifi.rtt;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.annotation.IntDef;

import java.lang.annotation.Retention;

/**
 * Civic Address key types used to define address elements.
 *
 * <p>These keys can be used in ResponderLocation look-up the corresponding string values.</p>
 *
 * @hide
 */
public class CivicLocationKeys {

    /**
     * An enumeration of all civic location keys.
     *
     * @hide
     */
    @Retention(SOURCE)
    @IntDef({LANGUAGE, STATE, COUNTY, CITY, BOROUGH, NEIGHBORHOOD, GROUP_OF_STREETS, PRD, POD, STS,
            HNO, HNS, LMK, LOC, NAM, POSTAL_CODE, BUILDING, APT, FLOOR, ROOM, TYPE_OF_PLACE, PCN,
            PO_BOX, ADDITIONAL_CODE, DESK, PRIMARY_ROAD_NAME, ROAD_SECTION, BRANCH_ROAD_NAME,
            SUBBRANCH_ROAD_NAME, STREET_NAME_PRE_MODIFIER, STREET_NAME_POST_MODIFIER, SCRIPT})
    public @interface CivicLocationKeysType {
    }

    /** Language key e.g. i-default. */
    public static final int LANGUAGE = 0;
    /** Category label A1 key e.g. California. */
    public static final int STATE = 1;
    /** Category label A2 key e.g. Marin. */
    public static final int COUNTY = 2;
    /** Category label A3 key e.g. San Francisco. */
    public static final int CITY = 3;
    /** Category label A4 key e.g. Westminster. */
    public static final int BOROUGH = 4;
    /** Category label A5 key e.g. Pacific Heights. */
    public static final int NEIGHBORHOOD = 5;
    /** Category label A6 key e.g. University District. */
    public static final int GROUP_OF_STREETS = 6;
    // 7 - 15 not defined
    /** Leading Street direction key e.g. N. */
    public static final int PRD = 16;
    /** Trailing street suffix key e.g. SW. */
    public static final int POD = 17;
    /** Street suffix or Type key e.g Ave, Platz. */
    public static final int STS = 18;
    /** House Number key e.g. 123. */
    public static final int HNO = 19;
    /** House number suffix key e.g. A, 1/2. */
    public static final int HNS = 20;
    /** Landmark or vanity address key e.g. Columbia Univ. */
    public static final int LMK = 21;
    /** Additional Location info key e.g. South Wing. */
    public static final int LOC = 22;
    /** Name of residence key e.g. Joe's Barbershop. */
    public static final int NAM = 23;
    /** Postal or ZIP code key e.g. 10027-1234. */
    public static final int POSTAL_CODE = 24;
    /** Building key e.g. Low Library. */
    public static final int BUILDING = 25;
    /** Apartment or suite key e.g. Apt 42. */
    public static final int APT = 26;
    /** Floor key e.g. 4. */
    public static final int FLOOR = 27;
    /** Room key e.g. 450F. */
    public static final int ROOM = 28;
    /** Type of place key e.g. office. */
    public static final int TYPE_OF_PLACE = 29;
    /** Postal community name key e.g. Leonia. */
    public static final int PCN = 30;
    /** Post Office Box key e.g. 12345. */
    public static final int PO_BOX = 31;
    /** Additional Code key e.g. 13203000003. */
    public static final int ADDITIONAL_CODE = 32;
    /** Seat, desk, pole, or cubical key e.g. WS 181. */
    public static final int DESK = 33;
    /** Primary road name key e.g. Shoreline. */
    public static final int PRIMARY_ROAD_NAME = 34;
    /** Road Section key e.g. 14. */
    public static final int ROAD_SECTION = 35;
    /** Branch Rd Name key e.g. Lane 7. */
    public static final int BRANCH_ROAD_NAME = 36;
    /** Subbranch Rd Name key e.g. Alley 8. */
    public static final int SUBBRANCH_ROAD_NAME = 37;
    /** Premodifier key e.g. Old. */
    public static final int STREET_NAME_PRE_MODIFIER = 38;
    /** Postmodifier key e.g. Service. */
    public static final int STREET_NAME_POST_MODIFIER = 39;
    /** Script key e.g. Latn. */
    public static final int SCRIPT = 128;

    /** private constructor */
    private CivicLocationKeys() {}
}
+38 −7

File changed.

Preview size limit exceeded, changes collapsed.

Loading