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.os.Parcel;
24 import android.os.Parcelable;
25 import android.util.SparseArray;
26 
27 import com.android.internal.util.MessageUtils;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 
32 /**
33  * An event recorded by NetworkMonitor when sending a probe for finding captive portals.
34  * {@hide}
35  * @deprecated The event may not be sent in Android S and above. The events
36  * are logged by a single caller in the system using signature permissions
37  * and that caller is migrating to statsd.
38  */
39 @Deprecated
40 @SystemApi
41 public final class ValidationProbeEvent implements IpConnectivityLog.Event {
42 
43     public static final int PROBE_DNS       = 0;
44     public static final int PROBE_HTTP      = 1;
45     public static final int PROBE_HTTPS     = 2;
46     public static final int PROBE_PAC       = 3;
47     public static final int PROBE_FALLBACK  = 4;
48     public static final int PROBE_PRIVDNS   = 5;
49 
50     public static final int DNS_FAILURE = 0;
51     public static final int DNS_SUCCESS = 1;
52 
53     private static final int FIRST_VALIDATION  = 1 << 8;
54     private static final int REVALIDATION      = 2 << 8;
55 
56     /** @hide */
57     @IntDef(value = {DNS_FAILURE, DNS_SUCCESS})
58     @Retention(RetentionPolicy.SOURCE)
59     public @interface ReturnCode {}
60 
61     /** @hide */
62     public final long durationMs;
63     // probeType byte format (MSB to LSB):
64     // byte 0: unused
65     // byte 1: unused
66     // byte 2: 0 = UNKNOWN, 1 = FIRST_VALIDATION, 2 = REVALIDATION
67     // byte 3: PROBE_* constant
68     /** @hide */
69     public final int probeType;
70     /** @hide */
71     public final @ReturnCode int returnCode;
72 
ValidationProbeEvent(long durationMs, int probeType, int returnCode)73     private ValidationProbeEvent(long durationMs, int probeType, int returnCode) {
74         this.durationMs = durationMs;
75         this.probeType = probeType;
76         this.returnCode = returnCode;
77     }
78 
ValidationProbeEvent(Parcel in)79     private ValidationProbeEvent(Parcel in) {
80         durationMs = in.readLong();
81         probeType = in.readInt();
82         returnCode = in.readInt();
83     }
84 
85     /**
86      * Utility to create an instance of {@link ValidationProbeEvent}.
87      */
88     public static final class Builder {
89         private long mDurationMs;
90         private int mProbeType;
91         private int mReturnCode;
92 
93         /**
94          * Set the duration of the probe in milliseconds.
95          */
96         @NonNull
setDurationMs(long durationMs)97         public Builder setDurationMs(long durationMs) {
98             mDurationMs = durationMs;
99             return this;
100         }
101 
102         /**
103          * Set the probe type based on whether it was the first validation.
104          */
105         @NonNull
setProbeType(int probeType, boolean firstValidation)106         public Builder setProbeType(int probeType, boolean firstValidation) {
107             mProbeType = makeProbeType(probeType, firstValidation);
108             return this;
109         }
110 
111         /**
112          * Set the return code of the probe.
113          */
114         @NonNull
setReturnCode(int returnCode)115         public Builder setReturnCode(int returnCode) {
116             mReturnCode = returnCode;
117             return this;
118         }
119 
120         /**
121          * Create a new {@link ValidationProbeEvent}.
122          */
123         @NonNull
build()124         public ValidationProbeEvent build() {
125             return new ValidationProbeEvent(mDurationMs, mProbeType, mReturnCode);
126         }
127     }
128 
129     /** @hide */
130     @Override
writeToParcel(Parcel out, int flags)131     public void writeToParcel(Parcel out, int flags) {
132         out.writeLong(durationMs);
133         out.writeInt(probeType);
134         out.writeInt(returnCode);
135     }
136 
137     /** @hide */
138     @Override
describeContents()139     public int describeContents() {
140         return 0;
141     }
142 
143     /** @hide */
144     public static final @android.annotation.NonNull Parcelable.Creator<ValidationProbeEvent> CREATOR
145         = new Parcelable.Creator<ValidationProbeEvent>() {
146         public ValidationProbeEvent createFromParcel(Parcel in) {
147             return new ValidationProbeEvent(in);
148         }
149 
150         public ValidationProbeEvent[] newArray(int size) {
151             return new ValidationProbeEvent[size];
152         }
153     };
154 
makeProbeType(int probeType, boolean firstValidation)155     private static int makeProbeType(int probeType, boolean firstValidation) {
156         return (probeType & 0xff) | (firstValidation ? FIRST_VALIDATION : REVALIDATION);
157     }
158 
159     /**
160      * Get the name of a probe specified by its probe type.
161      */
getProbeName(int probeType)162     public static @NonNull String getProbeName(int probeType) {
163         return Decoder.constants.get(probeType & 0xff, "PROBE_???");
164     }
165 
getValidationStage(int probeType)166     private static @NonNull String getValidationStage(int probeType) {
167         return Decoder.constants.get(probeType & 0xff00, "UNKNOWN");
168     }
169 
170     @NonNull
171     @Override
toString()172     public String toString() {
173         return String.format("ValidationProbeEvent(%s:%d %s, %dms)",
174                 getProbeName(probeType), returnCode, getValidationStage(probeType), durationMs);
175     }
176 
177     @Override
equals(@ullable Object obj)178     public boolean equals(@Nullable Object obj) {
179         if (obj == null || !(obj.getClass().equals(ValidationProbeEvent.class))) return false;
180         final ValidationProbeEvent other = (ValidationProbeEvent) obj;
181         return durationMs == other.durationMs
182                 && probeType == other.probeType
183                 && returnCode == other.returnCode;
184     }
185 
186     final static class Decoder {
187         static final SparseArray<String> constants = MessageUtils.findMessageNames(
188                 new Class[]{ValidationProbeEvent.class},
189                 new String[]{"PROBE_", "FIRST_", "REVALIDATION"});
190     }
191 }
192