1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.metrics; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.annotation.TestApi; 24 import android.compat.annotation.UnsupportedAppUsage; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 import android.text.TextUtils; 28 import android.util.SparseArray; 29 30 import com.android.internal.util.MessageUtils; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 import java.util.ArrayList; 35 import java.util.BitSet; 36 import java.util.List; 37 38 /** 39 * An event logged when there is a change or event that requires updating the 40 * the APF program in place with a new APF program. 41 * {@hide} 42 */ 43 @TestApi 44 @SystemApi 45 public final class ApfProgramEvent implements IpConnectivityLog.Event { 46 47 // Bitflag constants describing what an Apf program filters. 48 // Bits are indexeds from LSB to MSB, starting at index 0. 49 /** @hide */ 50 public static final int FLAG_MULTICAST_FILTER_ON = 0; 51 /** @hide */ 52 public static final int FLAG_HAS_IPV4_ADDRESS = 1; 53 54 /** {@hide} */ 55 @IntDef(flag = true, value = {FLAG_MULTICAST_FILTER_ON, FLAG_HAS_IPV4_ADDRESS}) 56 @Retention(RetentionPolicy.SOURCE) 57 public @interface Flags {} 58 59 /** @hide */ 60 @UnsupportedAppUsage 61 public final long lifetime; // Maximum computed lifetime of the program in seconds 62 /** @hide */ 63 @UnsupportedAppUsage 64 public final long actualLifetime; // Effective program lifetime in seconds 65 /** @hide */ 66 @UnsupportedAppUsage 67 public final int filteredRas; // Number of RAs filtered by the APF program 68 /** @hide */ 69 @UnsupportedAppUsage 70 public final int currentRas; // Total number of current RAs at generation time 71 /** @hide */ 72 @UnsupportedAppUsage 73 public final int programLength; // Length of the APF program in bytes 74 /** @hide */ 75 @UnsupportedAppUsage 76 public final int flags; // Bitfield compound of FLAG_* constants 77 ApfProgramEvent(long lifetime, long actualLifetime, int filteredRas, int currentRas, int programLength, int flags)78 private ApfProgramEvent(long lifetime, long actualLifetime, int filteredRas, int currentRas, 79 int programLength, int flags) { 80 this.lifetime = lifetime; 81 this.actualLifetime = actualLifetime; 82 this.filteredRas = filteredRas; 83 this.currentRas = currentRas; 84 this.programLength = programLength; 85 this.flags = flags; 86 } 87 ApfProgramEvent(Parcel in)88 private ApfProgramEvent(Parcel in) { 89 this.lifetime = in.readLong(); 90 this.actualLifetime = in.readLong(); 91 this.filteredRas = in.readInt(); 92 this.currentRas = in.readInt(); 93 this.programLength = in.readInt(); 94 this.flags = in.readInt(); 95 } 96 97 /** 98 * Utility to create an instance of {@link ApfProgramEvent}. 99 */ 100 public static final class Builder { 101 private long mLifetime; 102 private long mActualLifetime; 103 private int mFilteredRas; 104 private int mCurrentRas; 105 private int mProgramLength; 106 private int mFlags; 107 108 /** 109 * Set the maximum computed lifetime of the program in seconds. 110 */ 111 @NonNull setLifetime(long lifetime)112 public Builder setLifetime(long lifetime) { 113 mLifetime = lifetime; 114 return this; 115 } 116 117 /** 118 * Set the effective program lifetime in seconds. 119 */ 120 @NonNull setActualLifetime(long lifetime)121 public Builder setActualLifetime(long lifetime) { 122 mActualLifetime = lifetime; 123 return this; 124 } 125 126 /** 127 * Set the number of RAs filtered by the APF program. 128 */ 129 @NonNull setFilteredRas(int filteredRas)130 public Builder setFilteredRas(int filteredRas) { 131 mFilteredRas = filteredRas; 132 return this; 133 } 134 135 /** 136 * Set the total number of current RAs at generation time. 137 */ 138 @NonNull setCurrentRas(int currentRas)139 public Builder setCurrentRas(int currentRas) { 140 mCurrentRas = currentRas; 141 return this; 142 } 143 144 /** 145 * Set the length of the APF program in bytes. 146 */ 147 @NonNull setProgramLength(int programLength)148 public Builder setProgramLength(int programLength) { 149 mProgramLength = programLength; 150 return this; 151 } 152 153 /** 154 * Set the flags describing what an Apf program filters. 155 */ 156 @NonNull setFlags(boolean hasIPv4, boolean multicastFilterOn)157 public Builder setFlags(boolean hasIPv4, boolean multicastFilterOn) { 158 mFlags = flagsFor(hasIPv4, multicastFilterOn); 159 return this; 160 } 161 162 /** 163 * Build a new {@link ApfProgramEvent}. 164 */ 165 @NonNull build()166 public ApfProgramEvent build() { 167 return new ApfProgramEvent(mLifetime, mActualLifetime, mFilteredRas, mCurrentRas, 168 mProgramLength, mFlags); 169 } 170 } 171 172 /** @hide */ 173 @Override writeToParcel(Parcel out, int flags)174 public void writeToParcel(Parcel out, int flags) { 175 out.writeLong(lifetime); 176 out.writeLong(actualLifetime); 177 out.writeInt(filteredRas); 178 out.writeInt(currentRas); 179 out.writeInt(programLength); 180 out.writeInt(this.flags); 181 } 182 183 /** @hide */ 184 @Override describeContents()185 public int describeContents() { 186 return 0; 187 } 188 189 @NonNull 190 @Override toString()191 public String toString() { 192 String lifetimeString = (lifetime < Long.MAX_VALUE) ? lifetime + "s" : "forever"; 193 return String.format("ApfProgramEvent(%d/%d RAs %dB %ds/%s %s)", filteredRas, currentRas, 194 programLength, actualLifetime, lifetimeString, namesOf(flags)); 195 } 196 197 @Override equals(@ullable Object obj)198 public boolean equals(@Nullable Object obj) { 199 if (obj == null || !(obj.getClass().equals(ApfProgramEvent.class))) return false; 200 final ApfProgramEvent other = (ApfProgramEvent) obj; 201 return lifetime == other.lifetime 202 && actualLifetime == other.actualLifetime 203 && filteredRas == other.filteredRas 204 && currentRas == other.currentRas 205 && programLength == other.programLength 206 && flags == other.flags; 207 } 208 209 /** @hide */ 210 public static final @android.annotation.NonNull Parcelable.Creator<ApfProgramEvent> CREATOR 211 = new Parcelable.Creator<ApfProgramEvent>() { 212 public ApfProgramEvent createFromParcel(Parcel in) { 213 return new ApfProgramEvent(in); 214 } 215 216 public ApfProgramEvent[] newArray(int size) { 217 return new ApfProgramEvent[size]; 218 } 219 }; 220 221 /** @hide */ 222 @UnsupportedAppUsage flagsFor(boolean hasIPv4, boolean multicastFilterOn)223 public static @Flags int flagsFor(boolean hasIPv4, boolean multicastFilterOn) { 224 int bitfield = 0; 225 if (hasIPv4) { 226 bitfield |= (1 << FLAG_HAS_IPV4_ADDRESS); 227 } 228 if (multicastFilterOn) { 229 bitfield |= (1 << FLAG_MULTICAST_FILTER_ON); 230 } 231 return bitfield; 232 } 233 namesOf(@lags int bitfield)234 private static String namesOf(@Flags int bitfield) { 235 List<String> names = new ArrayList<>(Integer.bitCount(bitfield)); 236 BitSet set = BitSet.valueOf(new long[]{bitfield & Integer.MAX_VALUE}); 237 // Only iterate over flag bits which are set. 238 for (int bit = set.nextSetBit(0); bit >= 0; bit = set.nextSetBit(bit+1)) { 239 names.add(Decoder.constants.get(bit)); 240 } 241 return TextUtils.join("|", names); 242 } 243 244 final static class Decoder { 245 static final SparseArray<String> constants = 246 MessageUtils.findMessageNames( 247 new Class[]{ApfProgramEvent.class}, new String[]{"FLAG_"}); 248 } 249 } 250