1 /* 2 * Copyright 2024 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.google.android.iwlan.epdg; 18 19 import android.annotation.NonNull; 20 21 import java.net.InetAddress; 22 import java.util.HashSet; 23 import java.util.Set; 24 25 public class EpdgMonitor { 26 private InetAddress mEpdgAddressForNormalSession; 27 private InetAddress mSeparateEpdgAddressForEmergencySession; 28 private Set<String> mApnConnectToNormalEpdg = new HashSet<>(); 29 private final Set<String> mApnConnectToEmergencyEpdg = new HashSet<>(); 30 private boolean mHasEmergencyPdnFailedWithConnectedEpdg = false; 31 EpdgMonitor()32 public EpdgMonitor() {} 33 34 /** 35 * Called when an APN connects to an ePDG. Tracks the ePDG address and associated APN. 36 * 37 * @param apnName The name of the Access Point Name (APN). 38 * @param address The InetAddress of the connected ePDG. 39 */ onApnConnectToEpdg(@onNull String apnName, @NonNull InetAddress address)40 public void onApnConnectToEpdg(@NonNull String apnName, @NonNull InetAddress address) { 41 if (address.equals(getEpdgAddressForEmergencySession())) { 42 mApnConnectToEmergencyEpdg.add(apnName); 43 return; 44 } 45 46 if (address.equals(getEpdgAddressForNormalSession())) { 47 mApnConnectToNormalEpdg.add(apnName); 48 return; 49 } 50 51 if (!hasEpdgConnectedForNormalSession()) { 52 mEpdgAddressForNormalSession = address; 53 mApnConnectToNormalEpdg.clear(); 54 mApnConnectToNormalEpdg.add(apnName); 55 } else { 56 mSeparateEpdgAddressForEmergencySession = address; 57 mApnConnectToEmergencyEpdg.clear(); 58 mApnConnectToEmergencyEpdg.add(apnName); 59 } 60 } 61 62 /** 63 * Called when an APN disconnects from an ePDG. Updates internal tracking of APN connections to 64 * ePDGs. 65 * 66 * @param apnName The name of the Access Point Name (APN) that disconnected. 67 */ onApnDisconnectFromEpdg(String apnName)68 public void onApnDisconnectFromEpdg(String apnName) { 69 if (mApnConnectToNormalEpdg.contains(apnName)) { 70 mApnConnectToNormalEpdg.remove(apnName); 71 if (mApnConnectToNormalEpdg.isEmpty()) { 72 mEpdgAddressForNormalSession = null; 73 if (hasSeparateEpdgConnectedForEmergencySession()) { 74 // If ePDG for normal session has no PDN and emergency PDN established on an 75 // separate ePDG, mark the ePDG for emergency as ePDG for normal session. 76 mEpdgAddressForNormalSession = mSeparateEpdgAddressForEmergencySession; 77 mApnConnectToNormalEpdg = mApnConnectToEmergencyEpdg; 78 mSeparateEpdgAddressForEmergencySession = null; 79 mApnConnectToEmergencyEpdg.clear(); 80 mHasEmergencyPdnFailedWithConnectedEpdg = false; 81 } 82 } 83 } else if (mApnConnectToEmergencyEpdg.contains(apnName)) { 84 mApnConnectToEmergencyEpdg.remove(apnName); 85 if (mApnConnectToEmergencyEpdg.isEmpty()) { 86 mSeparateEpdgAddressForEmergencySession = null; 87 } 88 } 89 90 if (!hasEpdgConnectedForNormalSession()) { 91 mHasEmergencyPdnFailedWithConnectedEpdg = false; 92 } 93 } 94 95 /** 96 * Returns the ePDG address currently associated with normal PDN sessions. 97 * 98 * @return The InetAddress of the ePDG for normal sessions, or null if not connected. 99 */ getEpdgAddressForNormalSession()100 public InetAddress getEpdgAddressForNormalSession() { 101 return mEpdgAddressForNormalSession; 102 } 103 104 /** 105 * Returns the ePDG address currently associated with emergency PDN sessions. 106 * 107 * @return The InetAddress of the ePDG for emergency sessions, or null if not connected. 108 */ getEpdgAddressForEmergencySession()109 public InetAddress getEpdgAddressForEmergencySession() { 110 return mSeparateEpdgAddressForEmergencySession; 111 } 112 113 /** 114 * Checks whether an ePDG connection is established for normal PDN sessions. 115 * 116 * @return True if an ePDG is connected for normal sessions, false otherwise. 117 */ hasEpdgConnectedForNormalSession()118 public boolean hasEpdgConnectedForNormalSession() { 119 return mEpdgAddressForNormalSession != null; 120 } 121 122 /** 123 * Checks whether an separate ePDG connection is established for emergency PDN sessions. 124 * 125 * @return True if an separate ePDG is connected for emergency sessions, false otherwise. 126 */ hasSeparateEpdgConnectedForEmergencySession()127 public boolean hasSeparateEpdgConnectedForEmergencySession() { 128 return mSeparateEpdgAddressForEmergencySession != null; 129 } 130 131 /** 132 * Checks whether ePDG connection is established. 133 * 134 * @return True if ePDG is connected, false otherwise. 135 */ hasEpdgConnected()136 public boolean hasEpdgConnected() { 137 return hasEpdgConnectedForNormalSession() || hasSeparateEpdgConnectedForEmergencySession(); 138 } 139 140 /** 141 * Indicates whether an attempt to establish an emergency PDN has failed while a normal PDN 142 * session is active on the same ePDG. 143 * 144 * @return True if an emergency PDN establishment has failed on the connected ePDG, false 145 * otherwise. 146 */ hasEmergencyPdnFailedWithConnectedEpdg()147 public boolean hasEmergencyPdnFailedWithConnectedEpdg() { 148 return mHasEmergencyPdnFailedWithConnectedEpdg; 149 } 150 151 /** 152 * Called when a connection to an ePDG fails. Updates internal tracking and flags if an 153 * emergency PDN failure occurred on a previously connected ePDG. 154 * 155 * @param isEmergency Indicates whether the failed ePDG connection was for an emergency session. 156 * @param epdgAddress The InetAddress of the ePDG where the connection failed. 157 */ onEpdgConnectionFailed(boolean isEmergency, InetAddress epdgAddress)158 public void onEpdgConnectionFailed(boolean isEmergency, InetAddress epdgAddress) { 159 if (isEmergency 160 && hasEpdgConnectedForNormalSession() 161 && epdgAddress.equals(getEpdgAddressForNormalSession())) { 162 mHasEmergencyPdnFailedWithConnectedEpdg = true; 163 } 164 } 165 166 /** 167 * Determines if the provided EPDG address represents a connected EPDG (i.e., is the EPDG 168 * address used for normal or emergency sessions). 169 * 170 * @param epdgAddress The EPDG address to check. 171 * @return `true` if the provided EPDG address is a connected EPDG address, `false` otherwise. 172 */ isConnectedEpdg(InetAddress epdgAddress)173 public boolean isConnectedEpdg(InetAddress epdgAddress) { 174 return epdgAddress.equals(getEpdgAddressForNormalSession()) 175 || epdgAddress.equals(getEpdgAddressForEmergencySession()); 176 } 177 } 178