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.os.Parcel;
21 import android.os.Parcelable;
22 import android.text.TextUtils;
23 import android.util.SparseArray;
24 
25 import com.android.internal.util.MessageUtils;
26 
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.util.ArrayList;
30 import java.util.BitSet;
31 import java.util.List;
32 
33 /**
34  * An event logged when there is a change or event that requires updating the
35  * the APF program in place with a new APF program.
36  * {@hide}
37  */
38 public final class ApfProgramEvent implements Parcelable {
39 
40     // Bitflag constants describing what an Apf program filters.
41     // Bits are indexeds from LSB to MSB, starting at index 0.
42     public static final int FLAG_MULTICAST_FILTER_ON = 0;
43     public static final int FLAG_HAS_IPV4_ADDRESS    = 1;
44 
45     /** {@hide} */
46     @IntDef(flag = true, value = {FLAG_MULTICAST_FILTER_ON, FLAG_HAS_IPV4_ADDRESS})
47     @Retention(RetentionPolicy.SOURCE)
48     public @interface Flags {}
49 
50     public long lifetime;       // Maximum computed lifetime of the program in seconds
51     public long actualLifetime; // Effective program lifetime in seconds
52     public int filteredRas;     // Number of RAs filtered by the APF program
53     public int currentRas;      // Total number of current RAs at generation time
54     public int programLength;   // Length of the APF program in bytes
55     public int flags;           // Bitfield compound of FLAG_* constants
56 
ApfProgramEvent()57     public ApfProgramEvent() {
58     }
59 
ApfProgramEvent(Parcel in)60     private ApfProgramEvent(Parcel in) {
61         this.lifetime = in.readLong();
62         this.actualLifetime = in.readLong();
63         this.filteredRas = in.readInt();
64         this.currentRas = in.readInt();
65         this.programLength = in.readInt();
66         this.flags = in.readInt();
67     }
68 
69     @Override
writeToParcel(Parcel out, int flags)70     public void writeToParcel(Parcel out, int flags) {
71         out.writeLong(lifetime);
72         out.writeLong(actualLifetime);
73         out.writeInt(filteredRas);
74         out.writeInt(currentRas);
75         out.writeInt(programLength);
76         out.writeInt(flags);
77     }
78 
79     @Override
describeContents()80     public int describeContents() {
81         return 0;
82     }
83 
84     @Override
toString()85     public String toString() {
86         String lifetimeString = (lifetime < Long.MAX_VALUE) ? lifetime + "s" : "forever";
87         return String.format("ApfProgramEvent(%d/%d RAs %dB %ds/%s %s)", filteredRas, currentRas,
88                 programLength, actualLifetime, lifetimeString, namesOf(flags));
89     }
90 
91     public static final Parcelable.Creator<ApfProgramEvent> CREATOR
92             = new Parcelable.Creator<ApfProgramEvent>() {
93         public ApfProgramEvent createFromParcel(Parcel in) {
94             return new ApfProgramEvent(in);
95         }
96 
97         public ApfProgramEvent[] newArray(int size) {
98             return new ApfProgramEvent[size];
99         }
100     };
101 
flagsFor(boolean hasIPv4, boolean multicastFilterOn)102     public static @Flags int flagsFor(boolean hasIPv4, boolean multicastFilterOn) {
103         int bitfield = 0;
104         if (hasIPv4) {
105             bitfield |= (1 << FLAG_HAS_IPV4_ADDRESS);
106         }
107         if (multicastFilterOn) {
108             bitfield |= (1 << FLAG_MULTICAST_FILTER_ON);
109         }
110         return bitfield;
111     }
112 
namesOf(@lags int bitfield)113     private static String namesOf(@Flags int bitfield) {
114         List<String> names = new ArrayList<>(Integer.bitCount(bitfield));
115         BitSet set = BitSet.valueOf(new long[]{bitfield & Integer.MAX_VALUE});
116         // Only iterate over flag bits which are set.
117         for (int bit = set.nextSetBit(0); bit >= 0; bit = set.nextSetBit(bit+1)) {
118             names.add(Decoder.constants.get(bit));
119         }
120         return TextUtils.join("|", names);
121     }
122 
123     final static class Decoder {
124         static final SparseArray<String> constants =
125                 MessageUtils.findMessageNames(
126                        new Class[]{ApfProgramEvent.class}, new String[]{"FLAG_"});
127     }
128 }
129