• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 com.android.server.vcn.routeselection;
18 
19 import static android.net.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
20 
21 import static com.android.server.VcnManagementService.LOCAL_LOG;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.TargetApi;
26 import android.net.IpSecTransform;
27 import android.net.IpSecTransformState;
28 import android.net.Network;
29 import android.os.Build;
30 import android.os.OutcomeReceiver;
31 import android.util.CloseGuard;
32 import android.util.Slog;
33 
34 import com.android.internal.annotations.VisibleForTesting;
35 import com.android.internal.annotations.VisibleForTesting.Visibility;
36 import com.android.server.vcn.VcnContext;
37 
38 import java.util.Objects;
39 import java.util.concurrent.Executor;
40 
41 /**
42  * NetworkMetricMonitor is responsible for managing metric monitoring and tracking validation
43  * results.
44  *
45  * <p>This class is flag gated by "network_metric_monitor"
46  */
47 @TargetApi(Build.VERSION_CODES.BAKLAVA)
48 public abstract class NetworkMetricMonitor implements AutoCloseable {
49     private static final String TAG = NetworkMetricMonitor.class.getSimpleName();
50 
51     private static final boolean VDBG = false; // STOPSHIP: if true
52 
53     @NonNull private final CloseGuard mCloseGuard = new CloseGuard();
54 
55     @NonNull private final VcnContext mVcnContext;
56     @NonNull private final Network mNetwork;
57     @NonNull private final NetworkMetricMonitorCallback mCallback;
58 
59     private boolean mIsSelectedUnderlyingNetwork;
60     private boolean mIsStarted;
61     private boolean mIsValidationFailed;
62 
NetworkMetricMonitor( @onNull VcnContext vcnContext, @NonNull Network network, @Nullable PersistableBundleWrapper carrierConfig, @NonNull NetworkMetricMonitorCallback callback)63     protected NetworkMetricMonitor(
64             @NonNull VcnContext vcnContext,
65             @NonNull Network network,
66             @Nullable PersistableBundleWrapper carrierConfig,
67             @NonNull NetworkMetricMonitorCallback callback)
68             throws IllegalAccessException {
69         mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext");
70         mNetwork = Objects.requireNonNull(network, "Missing network");
71         mCallback = Objects.requireNonNull(callback, "Missing callback");
72 
73         mIsSelectedUnderlyingNetwork = false;
74         mIsStarted = false;
75         mIsValidationFailed = false;
76     }
77 
78     /** Callback to notify caller of the validation result */
79     public interface NetworkMetricMonitorCallback {
80         /** Called when there is a validation result is ready */
onValidationResultReceived()81         void onValidationResultReceived();
82     }
83 
84     /**
85      * Start monitoring
86      *
87      * <p>This method might be called on a an already started monitor for updating monitor
88      * properties (e.g. IpSecTransform, carrier config)
89      *
90      * <p>Subclasses MUST call super.start() when overriding this method
91      */
start()92     protected void start() {
93         mIsStarted = true;
94     }
95 
96     /**
97      * Stop monitoring
98      *
99      * <p>Subclasses MUST call super.stop() when overriding this method
100      */
stop()101     public void stop() {
102         mIsValidationFailed = false;
103         mIsStarted = false;
104     }
105 
106     /** Called by the subclasses when the validation result is ready */
onValidationResultReceivedInternal(boolean isFailed)107     protected void onValidationResultReceivedInternal(boolean isFailed) {
108         mIsValidationFailed = isFailed;
109         mCallback.onValidationResultReceived();
110     }
111 
112     /** Called when the underlying network changes to selected or unselected */
onSelectedUnderlyingNetworkChanged()113     protected abstract void onSelectedUnderlyingNetworkChanged();
114 
115     /**
116      * Mark the network being monitored selected or unselected
117      *
118      * <p>Subclasses MUST call super when overriding this method
119      */
setIsSelectedUnderlyingNetwork(boolean isSelectedUnderlyingNetwork)120     public void setIsSelectedUnderlyingNetwork(boolean isSelectedUnderlyingNetwork) {
121         if (mIsSelectedUnderlyingNetwork == isSelectedUnderlyingNetwork) {
122             return;
123         }
124 
125         mIsSelectedUnderlyingNetwork = isSelectedUnderlyingNetwork;
126         onSelectedUnderlyingNetworkChanged();
127     }
128 
129     /** Wrapper that allows injection for testing purposes */
130     @VisibleForTesting(visibility = Visibility.PROTECTED)
131     public static class IpSecTransformWrapper {
132         @NonNull public final IpSecTransform ipSecTransform;
133 
IpSecTransformWrapper(@onNull IpSecTransform ipSecTransform)134         public IpSecTransformWrapper(@NonNull IpSecTransform ipSecTransform) {
135             this.ipSecTransform = ipSecTransform;
136         }
137 
138         /** Poll an IpSecTransformState */
requestIpSecTransformState( @onNull Executor executor, @NonNull OutcomeReceiver<IpSecTransformState, RuntimeException> callback)139         public void requestIpSecTransformState(
140                 @NonNull Executor executor,
141                 @NonNull OutcomeReceiver<IpSecTransformState, RuntimeException> callback) {
142             ipSecTransform.requestIpSecTransformState(executor, callback);
143         }
144 
145         /** Close this instance and release the underlying resources */
close()146         public void close() {
147             ipSecTransform.close();
148         }
149 
150         @Override
hashCode()151         public int hashCode() {
152             return Objects.hash(ipSecTransform);
153         }
154 
155         @Override
equals(Object o)156         public boolean equals(Object o) {
157             if (!(o instanceof IpSecTransformWrapper)) {
158                 return false;
159             }
160 
161             final IpSecTransformWrapper other = (IpSecTransformWrapper) o;
162 
163             return Objects.equals(ipSecTransform, other.ipSecTransform);
164         }
165     }
166 
167     /** Set the IpSecTransform that is applied to the Network being monitored */
setInboundTransform(@onNull IpSecTransform inTransform)168     public void setInboundTransform(@NonNull IpSecTransform inTransform) {
169         setInboundTransformInternal(new IpSecTransformWrapper(inTransform));
170     }
171 
172     /**
173      * Set the IpSecTransform that applied to the Network being monitored *
174      *
175      * <p>Subclasses MUST call super when overriding this method
176      */
177     @VisibleForTesting(visibility = Visibility.PRIVATE)
setInboundTransformInternal(@onNull IpSecTransformWrapper inTransform)178     public void setInboundTransformInternal(@NonNull IpSecTransformWrapper inTransform) {
179         // Subclasses MUST override it if they care
180     }
181 
182     /** Update the carrierconfig */
setCarrierConfig(@ullable PersistableBundleWrapper carrierConfig)183     public void setCarrierConfig(@Nullable PersistableBundleWrapper carrierConfig) {
184         // Subclasses MUST override it if they care
185     }
186 
187     /** Called when LinkProperties or NetworkCapabilities have changed */
onLinkPropertiesOrCapabilitiesChanged()188     public void onLinkPropertiesOrCapabilitiesChanged() {
189         // Subclasses MUST override it if they care
190     }
191 
isValidationFailed()192     public boolean isValidationFailed() {
193         return mIsValidationFailed;
194     }
195 
isSelectedUnderlyingNetwork()196     public boolean isSelectedUnderlyingNetwork() {
197         return mIsSelectedUnderlyingNetwork;
198     }
199 
isStarted()200     public boolean isStarted() {
201         return mIsStarted;
202     }
203 
204     @NonNull
getVcnContext()205     public VcnContext getVcnContext() {
206         return mVcnContext;
207     }
208 
209     @NonNull
getNetwork()210     public Network getNetwork() {
211         return mNetwork;
212     }
213 
214     // Override methods for AutoCloseable. Subclasses MUST call super when overriding this method
215     @Override
close()216     public void close() {
217         mCloseGuard.close();
218 
219         stop();
220     }
221 
222     // Override #finalize() to use closeGuard for flagging that #close() was not called
223     @SuppressWarnings("Finalize")
224     @Override
finalize()225     protected void finalize() throws Throwable {
226         try {
227             if (mCloseGuard != null) {
228                 mCloseGuard.warnIfOpen();
229             }
230             close();
231         } finally {
232             super.finalize();
233         }
234     }
235 
getClassName()236     private String getClassName() {
237         return this.getClass().getSimpleName();
238     }
239 
getLogPrefix()240     protected String getLogPrefix() {
241         return " [Network " + mNetwork + "] ";
242     }
243 
logV(String msg)244     protected void logV(String msg) {
245         if (VDBG) {
246             Slog.v(getClassName(), getLogPrefix() + msg);
247             LOCAL_LOG.log("[VERBOSE ] " + getClassName() + getLogPrefix() + msg);
248         }
249     }
250 
logInfo(String msg)251     protected void logInfo(String msg) {
252         Slog.i(getClassName(), getLogPrefix() + msg);
253         LOCAL_LOG.log("[INFO ] " + getClassName() + getLogPrefix() + msg);
254     }
255 
logW(String msg)256     protected void logW(String msg) {
257         Slog.w(getClassName(), getLogPrefix() + msg);
258         LOCAL_LOG.log("[WARN ] " + getClassName() + getLogPrefix() + msg);
259     }
260 
logWtf(String msg)261     protected void logWtf(String msg) {
262         Slog.wtf(getClassName(), getLogPrefix() + msg);
263         LOCAL_LOG.log("[WTF ] " + getClassName() + getLogPrefix() + msg);
264     }
265 
logV(String className, String msgWithPrefix)266     protected static void logV(String className, String msgWithPrefix) {
267         if (VDBG) {
268             Slog.wtf(className, msgWithPrefix);
269             LOCAL_LOG.log("[VERBOSE ] " + className + msgWithPrefix);
270         }
271     }
272 
logE(String className, String msgWithPrefix)273     protected static void logE(String className, String msgWithPrefix) {
274         Slog.w(className, msgWithPrefix);
275         LOCAL_LOG.log("[ERROR ] " + className + msgWithPrefix);
276     }
277 
logWtf(String className, String msgWithPrefix)278     protected static void logWtf(String className, String msgWithPrefix) {
279         Slog.wtf(className, msgWithPrefix);
280         LOCAL_LOG.log("[WTF ] " + className + msgWithPrefix);
281     }
282 }
283