![JAR search and dependency download from the Maven repository](/logo.png)
src.android.telephony.data.TrafficDescriptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of android-all Show documentation
Show all versions of android-all Show documentation
A library jar that provides APIs for Applications written for the Google Android Platform.
/*
* Copyright (C) 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 android.telephony.data;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for UE Route Selection
* Policy(URSP) traffic matching as described in 3GPP TS 24.526 Section 4.2.2. It includes an
* optional Data Network Name(DNN), which, if present, must be used for traffic matching; it does
* not specify the end point to be used for the data call.
*/
public final class TrafficDescriptor implements Parcelable {
/**
* The OS/App id
*
* @hide
*/
public static final class OsAppId {
/**
* OSId for "Android", using UUID version 5 with namespace ISO OSI.
* Prepended to the OsAppId in TrafficDescriptor to use for URSP matching.
*/
public static final UUID ANDROID_OS_ID =
UUID.fromString("97a498e3-fc92-5c94-8986-0333d06e4e47");
/**
* Allowed app ids.
*/
// The following app ids are the only apps id Android supports. OEMs or vendors are
// prohibited to modify/extend the allowed list, especially passing the real package name to
// the network.
private static final Set ALLOWED_APP_IDS = Set.of(
"ENTERPRISE", "PRIORITIZE_LATENCY", "PRIORITIZE_BANDWIDTH", "CBS"
);
/** OS id in UUID format. */
private final @NonNull UUID mOsId;
/**
* App id in string format. Note that Android will not allow use specific app id. This must
* be a category/capability identifier.
*/
private final @NonNull String mAppId;
/**
* The differentiator when multiple traffic descriptor has the same OS and app id. Must be
* greater than 1.
*/
private final int mDifferentiator;
/**
* Constructor
*
* @param osId OS id in UUID format.
* @param appId App id in string format. Note that Android will not allow use specific app
* id. This must be a category/capability identifier.
*/
public OsAppId(@NonNull UUID osId, @NonNull String appId) {
this(osId, appId, 1);
}
/**
* Constructor
*
* @param osId OS id in UUID format.
* @param appId App id in string format. Note that Android will not allow use specific app
* id. This must be a category/capability identifier.
* @param differentiator The differentiator when multiple traffic descriptor has the same
* OS and app id. Must be greater than 0.
*/
public OsAppId(@NonNull UUID osId, @NonNull String appId, int differentiator) {
Objects.requireNonNull(osId);
Objects.requireNonNull(appId);
if (differentiator < 1) {
throw new IllegalArgumentException("Invalid differentiator " + differentiator);
}
mOsId = osId;
mAppId = appId;
mDifferentiator = differentiator;
}
/**
* Constructor from raw byte array.
*
* @param rawOsAppId The raw OS/App id.
*/
public OsAppId(@NonNull byte[] rawOsAppId) {
try {
ByteBuffer bb = ByteBuffer.wrap(rawOsAppId);
// OS id is the first 16 bytes.
mOsId = new UUID(bb.getLong(), bb.getLong());
// App id length is 1 byte.
int appIdLen = bb.get();
// The remaining is the app id + differentiator.
byte[] appIdAndDifferentiator = new byte[appIdLen];
bb.get(appIdAndDifferentiator, 0, appIdLen);
// Extract trailing numbers, for example, "ENTERPRISE", "ENTERPRISE3".
String appIdAndDifferentiatorStr = new String(appIdAndDifferentiator);
Pattern pattern = Pattern.compile("[^0-9]+([0-9]+)$");
Matcher matcher = pattern.matcher(new String(appIdAndDifferentiator));
if (matcher.find()) {
mDifferentiator = Integer.parseInt(matcher.group(1));
mAppId = appIdAndDifferentiatorStr.replace(matcher.group(1), "");
} else {
mDifferentiator = 1;
mAppId = appIdAndDifferentiatorStr;
}
} catch (Exception e) {
throw new IllegalArgumentException("Failed to decode " + (rawOsAppId != null
? new BigInteger(1, rawOsAppId).toString(16) : null));
}
}
/**
* @return The OS id in UUID format.
*/
public @NonNull UUID getOsId() {
return mOsId;
}
/**
* @return App id in string format. Note that Android will not allow use specific app id.
* This must be a category/capability identifier.
*/
public @NonNull String getAppId() {
return mAppId;
}
/**
* @return The differentiator when multiple traffic descriptor has the same OS and app id.
* Must be greater than 1.
*/
public int getDifferentiator() {
return mDifferentiator;
}
/**
* @return OS/App id in raw byte format.
*/
public @NonNull byte[] getBytes() {
byte[] osAppId = (mAppId + (mDifferentiator > 1 ? mDifferentiator : "")).getBytes();
// 16 bytes for UUID, 1 byte for length of osAppId, and up to 255 bytes for osAppId
ByteBuffer bb = ByteBuffer.allocate(16 + 1 + osAppId.length);
bb.putLong(mOsId.getMostSignificantBits());
bb.putLong(mOsId.getLeastSignificantBits());
bb.put((byte) osAppId.length);
bb.put(osAppId);
return bb.array();
}
@Override
public String toString() {
return "[OsAppId: OS=" + mOsId + ", App=" + mAppId + ", differentiator="
+ mDifferentiator + ", raw="
+ new BigInteger(1, getBytes()).toString(16) + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OsAppId osAppId = (OsAppId) o;
return mDifferentiator == osAppId.mDifferentiator && mOsId.equals(osAppId.mOsId)
&& mAppId.equals(osAppId.mAppId);
}
@Override
public int hashCode() {
return Objects.hash(mOsId, mAppId, mDifferentiator);
}
}
private final String mDnn;
private final OsAppId mOsAppId;
private TrafficDescriptor(@NonNull Parcel in) {
mDnn = in.readString();
byte[] osAppIdBytes = in.createByteArray();
OsAppId osAppId = null;
if (osAppIdBytes != null) {
osAppId = new OsAppId(osAppIdBytes);
}
mOsAppId = osAppId;
enforceAllowedIds();
}
/**
* Create a traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2
* @param dnn optional DNN, which must be used for traffic matching, if present
* @param osAppIdRawBytes Raw bytes of OsId + osAppId of the traffic descriptor
*
* @hide
*/
public TrafficDescriptor(String dnn, @Nullable byte[] osAppIdRawBytes) {
mDnn = dnn;
OsAppId osAppId = null;
if (osAppIdRawBytes != null) {
osAppId = new OsAppId(osAppIdRawBytes);
}
mOsAppId = osAppId;
enforceAllowedIds();
}
/**
* Enforce the OS id and app id are in the allowed list.
*
* @throws IllegalArgumentException if ids are not allowed.
*/
private void enforceAllowedIds() {
if (mOsAppId != null && !mOsAppId.getOsId().equals(OsAppId.ANDROID_OS_ID)) {
throw new IllegalArgumentException("OS id " + mOsAppId.getOsId() + " does not match "
+ OsAppId.ANDROID_OS_ID);
}
if (mOsAppId != null && !OsAppId.ALLOWED_APP_IDS.contains(mOsAppId.getAppId())) {
throw new IllegalArgumentException("Illegal app id " + mOsAppId.getAppId()
+ ". Only allowing one of the following " + OsAppId.ALLOWED_APP_IDS);
}
}
/**
* DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003.
* @return the DNN of this traffic descriptor if one is included by the network, null
* otherwise.
*/
public @Nullable String getDataNetworkName() {
return mDnn;
}
/**
* OsAppId identifies a broader traffic category. Although it names Os/App id, it only includes
* OS version with a general/broader category id used as app id.
*
* @return The id in byte format. {@code null} if not available.
*/
public @Nullable byte[] getOsAppId() {
return mOsAppId != null ? mOsAppId.getBytes() : null;
}
@Override
public int describeContents() {
return 0;
}
@NonNull @Override
public String toString() {
return "TrafficDescriptor={mDnn=" + mDnn + ", " + mOsAppId + "}";
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mDnn);
dest.writeByteArray(mOsAppId != null ? mOsAppId.getBytes() : null);
}
public static final @NonNull Parcelable.Creator CREATOR =
new Parcelable.Creator() {
@Override
public @NonNull TrafficDescriptor createFromParcel(@NonNull Parcel source) {
return new TrafficDescriptor(source);
}
@Override
public @NonNull TrafficDescriptor[] newArray(int size) {
return new TrafficDescriptor[size];
}
};
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrafficDescriptor that = (TrafficDescriptor) o;
return Objects.equals(mDnn, that.mDnn) && Objects.equals(mOsAppId, that.mOsAppId);
}
@Override
public int hashCode() {
return Objects.hash(mDnn, mOsAppId);
}
/**
* Provides a convenient way to set the fields of a {@link TrafficDescriptor} when creating a
* new instance.
*
* The example below shows how you might create a new {@code TrafficDescriptor}:
*
*
*
* TrafficDescriptor response = new TrafficDescriptor.Builder()
* .setDnn("")
* .build();
*
*
*/
public static final class Builder {
private String mDnn = null;
private byte[] mOsAppId = null;
/**
* Default constructor for Builder.
*/
public Builder() {
}
/**
* Set the Data Network Name(DNN).
*
* @return The same instance of the builder.
*/
@NonNull
public Builder setDataNetworkName(@NonNull String dnn) {
this.mDnn = dnn;
return this;
}
/**
* Set the OS App ID (including OS Id as defined in the specs).
*
* @return The same instance of the builder.
*/
@NonNull
public Builder setOsAppId(@NonNull byte[] osAppId) {
this.mOsAppId = osAppId;
return this;
}
/**
* Build the {@link TrafficDescriptor}.
*
* @throws IllegalArgumentException if DNN and OS App ID are null.
*
* @return the {@link TrafficDescriptor} object.
*/
@NonNull
public TrafficDescriptor build() {
if (this.mDnn == null && this.mOsAppId == null) {
throw new IllegalArgumentException("DNN and OS App ID are null");
}
return new TrafficDescriptor(this.mDnn, this.mOsAppId);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy