/* * Copyright (C) 2020 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; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; /** * Information on a tethered downstream client. * @hide */ @SystemApi public final class TetheredClient implements Parcelable { @NonNull private final MacAddress mMacAddress; @NonNull private final List mAddresses; // TODO: use an @IntDef here private final int mTetheringType; public TetheredClient(@NonNull MacAddress macAddress, @NonNull Collection addresses, int tetheringType) { mMacAddress = macAddress; mAddresses = new ArrayList<>(addresses); mTetheringType = tetheringType; } private TetheredClient(@NonNull Parcel in) { this(in.readParcelable(null), in.createTypedArrayList(AddressInfo.CREATOR), in.readInt()); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeParcelable(mMacAddress, flags); dest.writeTypedList(mAddresses); dest.writeInt(mTetheringType); } /** * Get the MAC address used to identify the client. */ @NonNull public MacAddress getMacAddress() { return mMacAddress; } /** * Get information on the list of addresses that are associated with the client. */ @NonNull public List getAddresses() { return new ArrayList<>(mAddresses); } /** * Get the type of tethering used by the client. * @return one of the {@code TetheringManager#TETHERING_*} constants. */ public int getTetheringType() { return mTetheringType; } /** * Return a new {@link TetheredClient} that has all the attributes of this instance, plus the * {@link AddressInfo} of the provided {@link TetheredClient}. * *

Duplicate addresses are removed. * @hide */ public TetheredClient addAddresses(@NonNull TetheredClient other) { final LinkedHashSet newAddresses = new LinkedHashSet<>( mAddresses.size() + other.mAddresses.size()); newAddresses.addAll(mAddresses); newAddresses.addAll(other.mAddresses); return new TetheredClient(mMacAddress, newAddresses, mTetheringType); } @Override public int hashCode() { return Objects.hash(mMacAddress, mAddresses, mTetheringType); } @Override public boolean equals(@Nullable Object obj) { if (!(obj instanceof TetheredClient)) return false; final TetheredClient other = (TetheredClient) obj; return mMacAddress.equals(other.mMacAddress) && mAddresses.equals(other.mAddresses) && mTetheringType == other.mTetheringType; } /** * Information on an lease assigned to a tethered client. */ public static final class AddressInfo implements Parcelable { @NonNull private final LinkAddress mAddress; @Nullable private final String mHostname; /** @hide */ public AddressInfo(@NonNull LinkAddress address, @Nullable String hostname) { this.mAddress = address; this.mHostname = hostname; } private AddressInfo(Parcel in) { this(in.readParcelable(null), in.readString()); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeParcelable(mAddress, flags); dest.writeString(mHostname); } /** * Get the link address (including prefix length and lifetime) used by the client. * * This may be an IPv4 or IPv6 address. */ @NonNull public LinkAddress getAddress() { return mAddress; } /** * Get the hostname that was advertised by the client when obtaining its address, if any. */ @Nullable public String getHostname() { return mHostname; } /** * Get the expiration time of the address assigned to the client. * @hide */ public long getExpirationTime() { return mAddress.getExpirationTime(); } @Override public int describeContents() { return 0; } @Override public int hashCode() { return Objects.hash(mAddress, mHostname); } @Override public boolean equals(@Nullable Object obj) { if (!(obj instanceof AddressInfo)) return false; final AddressInfo other = (AddressInfo) obj; // Use .equals() for addresses as all changes, including address expiry changes, // should be included. return other.mAddress.equals(mAddress) && Objects.equals(mHostname, other.mHostname); } @NonNull public static final Creator CREATOR = new Creator() { @NonNull @Override public AddressInfo createFromParcel(@NonNull Parcel in) { return new AddressInfo(in); } @NonNull @Override public AddressInfo[] newArray(int size) { return new AddressInfo[size]; } }; @NonNull @Override public String toString() { return "AddressInfo {" + mAddress + (mHostname != null ? ", hostname " + mHostname : "") + "}"; } } @Override public int describeContents() { return 0; } @NonNull public static final Creator CREATOR = new Creator() { @NonNull @Override public TetheredClient createFromParcel(@NonNull Parcel in) { return new TetheredClient(in); } @NonNull @Override public TetheredClient[] newArray(int size) { return new TetheredClient[size]; } }; @NonNull @Override public String toString() { return "TetheredClient {hwAddr " + mMacAddress + ", addresses " + mAddresses + ", tetheringType " + mTetheringType + "}"; } }