blob: f93907a37f3fd93d04740fcd0bdddef223b5a9cb [file] [log] [blame]
/*
* Copyright (C) 2016 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.metrics;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.SparseArray;
import com.android.internal.util.MessageUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
/**
* An event logged when there is a change or event that requires updating the
* the APF program in place with a new APF program.
* {@hide}
*/
@TestApi
@SystemApi
public final class ApfProgramEvent implements IpConnectivityLog.Event {
// Bitflag constants describing what an Apf program filters.
// Bits are indexeds from LSB to MSB, starting at index 0.
/** @hide */
public static final int FLAG_MULTICAST_FILTER_ON = 0;
/** @hide */
public static final int FLAG_HAS_IPV4_ADDRESS = 1;
/** {@hide} */
@IntDef(flag = true, value = {FLAG_MULTICAST_FILTER_ON, FLAG_HAS_IPV4_ADDRESS})
@Retention(RetentionPolicy.SOURCE)
public @interface Flags {}
/** @hide */
@UnsupportedAppUsage
public final long lifetime; // Maximum computed lifetime of the program in seconds
/** @hide */
@UnsupportedAppUsage
public final long actualLifetime; // Effective program lifetime in seconds
/** @hide */
@UnsupportedAppUsage
public final int filteredRas; // Number of RAs filtered by the APF program
/** @hide */
@UnsupportedAppUsage
public final int currentRas; // Total number of current RAs at generation time
/** @hide */
@UnsupportedAppUsage
public final int programLength; // Length of the APF program in bytes
/** @hide */
@UnsupportedAppUsage
public final int flags; // Bitfield compound of FLAG_* constants
private ApfProgramEvent(long lifetime, long actualLifetime, int filteredRas, int currentRas,
int programLength, int flags) {
this.lifetime = lifetime;
this.actualLifetime = actualLifetime;
this.filteredRas = filteredRas;
this.currentRas = currentRas;
this.programLength = programLength;
this.flags = flags;
}
private ApfProgramEvent(Parcel in) {
this.lifetime = in.readLong();
this.actualLifetime = in.readLong();
this.filteredRas = in.readInt();
this.currentRas = in.readInt();
this.programLength = in.readInt();
this.flags = in.readInt();
}
/**
* Utility to create an instance of {@link ApfProgramEvent}.
*/
public static final class Builder {
private long mLifetime;
private long mActualLifetime;
private int mFilteredRas;
private int mCurrentRas;
private int mProgramLength;
private int mFlags;
/**
* Set the maximum computed lifetime of the program in seconds.
*/
@NonNull
public Builder setLifetime(long lifetime) {
mLifetime = lifetime;
return this;
}
/**
* Set the effective program lifetime in seconds.
*/
@NonNull
public Builder setActualLifetime(long lifetime) {
mActualLifetime = lifetime;
return this;
}
/**
* Set the number of RAs filtered by the APF program.
*/
@NonNull
public Builder setFilteredRas(int filteredRas) {
mFilteredRas = filteredRas;
return this;
}
/**
* Set the total number of current RAs at generation time.
*/
@NonNull
public Builder setCurrentRas(int currentRas) {
mCurrentRas = currentRas;
return this;
}
/**
* Set the length of the APF program in bytes.
*/
@NonNull
public Builder setProgramLength(int programLength) {
mProgramLength = programLength;
return this;
}
/**
* Set the flags describing what an Apf program filters.
*/
@NonNull
public Builder setFlags(boolean hasIPv4, boolean multicastFilterOn) {
mFlags = flagsFor(hasIPv4, multicastFilterOn);
return this;
}
/**
* Build a new {@link ApfProgramEvent}.
*/
@NonNull
public ApfProgramEvent build() {
return new ApfProgramEvent(mLifetime, mActualLifetime, mFilteredRas, mCurrentRas,
mProgramLength, mFlags);
}
}
/** @hide */
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeLong(lifetime);
out.writeLong(actualLifetime);
out.writeInt(filteredRas);
out.writeInt(currentRas);
out.writeInt(programLength);
out.writeInt(this.flags);
}
/** @hide */
@Override
public int describeContents() {
return 0;
}
@NonNull
@Override
public String toString() {
String lifetimeString = (lifetime < Long.MAX_VALUE) ? lifetime + "s" : "forever";
return String.format("ApfProgramEvent(%d/%d RAs %dB %ds/%s %s)", filteredRas, currentRas,
programLength, actualLifetime, lifetimeString, namesOf(flags));
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == null || !(obj.getClass().equals(ApfProgramEvent.class))) return false;
final ApfProgramEvent other = (ApfProgramEvent) obj;
return lifetime == other.lifetime
&& actualLifetime == other.actualLifetime
&& filteredRas == other.filteredRas
&& currentRas == other.currentRas
&& programLength == other.programLength
&& flags == other.flags;
}
/** @hide */
public static final @android.annotation.NonNull Parcelable.Creator<ApfProgramEvent> CREATOR
= new Parcelable.Creator<ApfProgramEvent>() {
public ApfProgramEvent createFromParcel(Parcel in) {
return new ApfProgramEvent(in);
}
public ApfProgramEvent[] newArray(int size) {
return new ApfProgramEvent[size];
}
};
/** @hide */
@UnsupportedAppUsage
public static @Flags int flagsFor(boolean hasIPv4, boolean multicastFilterOn) {
int bitfield = 0;
if (hasIPv4) {
bitfield |= (1 << FLAG_HAS_IPV4_ADDRESS);
}
if (multicastFilterOn) {
bitfield |= (1 << FLAG_MULTICAST_FILTER_ON);
}
return bitfield;
}
private static String namesOf(@Flags int bitfield) {
List<String> names = new ArrayList<>(Integer.bitCount(bitfield));
BitSet set = BitSet.valueOf(new long[]{bitfield & Integer.MAX_VALUE});
// Only iterate over flag bits which are set.
for (int bit = set.nextSetBit(0); bit >= 0; bit = set.nextSetBit(bit+1)) {
names.add(Decoder.constants.get(bit));
}
return TextUtils.join("|", names);
}
final static class Decoder {
static final SparseArray<String> constants =
MessageUtils.findMessageNames(
new Class[]{ApfProgramEvent.class}, new String[]{"FLAG_"});
}
}