Loading api/current.txt +59 −0 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); api/system-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading wifi/java/android/net/wifi/rtt/CivicLocation.java 0 → 100644 +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; } } wifi/java/android/net/wifi/rtt/CivicLocationKeys.java 0 → 100644 +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() {} } Loading
api/current.txt +59 −0 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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);
api/system-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
wifi/java/android/net/wifi/rtt/CivicLocation.java 0 → 100644 +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; } }
wifi/java/android/net/wifi/rtt/CivicLocationKeys.java 0 → 100644 +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() {} }