| /* |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.wifi; |
| |
| import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; |
| import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED; |
| |
| import android.annotation.IntDef; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.content.Context; |
| import android.net.wifi.ScanResult; |
| import android.net.wifi.WifiInfo; |
| import android.net.wifi.WifiManager; |
| import android.os.Handler; |
| import android.os.WorkSource; |
| import android.util.Log; |
| import android.util.SparseArray; |
| |
| import com.android.internal.annotations.VisibleForTesting; |
| import com.android.modules.utils.build.SdkLevel; |
| |
| import java.io.FileDescriptor; |
| import java.io.PrintWriter; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| |
| /** |
| * Manages STA + STA for multi internet networks. |
| */ |
| public class MultiInternetManager { |
| private static final String TAG = "WifiMultiInternet"; |
| |
| private final ActiveModeWarden mActiveModeWarden; |
| private final FrameworkFacade mFrameworkFacade; |
| private final Context mContext; |
| private final ClientModeImplMonitor mCmiMonitor; |
| private final WifiSettingsStore mSettingsStore; |
| private final Handler mEventHandler; |
| private final Clock mClock; |
| private int mStaConcurrencyMultiInternetMode = WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED; |
| @MultiInternetState |
| private int mMultiInternetConnectionState = MULTI_INTERNET_STATE_NONE; |
| private ConnectionStatusListener mConnectionStatusListener; |
| |
| private SparseArray<NetworkConnectionState> mNetworkConnectionStates = new SparseArray<>(); |
| private boolean mVerboseLoggingEnabled = false; |
| |
| /** No multi internet connection needed. */ |
| public static final int MULTI_INTERNET_STATE_NONE = 0; |
| /** Multi internet connection is connecting. */ |
| public static final int MULTI_INTERNET_STATE_CONNECTION_REQUESTED = 1; |
| /** No multi internet connection is connected. */ |
| public static final int MULTI_INTERNET_STATE_CONNECTED = 2; |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef(prefix = {"MULTI_INTERNET_STATE_"}, value = { |
| MULTI_INTERNET_STATE_NONE, |
| MULTI_INTERNET_STATE_CONNECTION_REQUESTED, |
| MULTI_INTERNET_STATE_CONNECTED}) |
| public @interface MultiInternetState {} |
| |
| /** The internal network connection state per each Wi-Fi band. */ |
| class NetworkConnectionState { |
| // If the supplicant connection is completed. |
| private boolean mConnected; |
| // If the internet has been validated. |
| private boolean mValidated; |
| // The connection start time in millisecond |
| public long connectionStartTimeMillis; |
| // The WorkSource of the connection requestor. |
| public WorkSource requestorWorkSource; |
| |
| NetworkConnectionState(WorkSource workSource) { |
| this(workSource, -1L); |
| } |
| |
| NetworkConnectionState(WorkSource workSource, long connectionStartTime) { |
| requestorWorkSource = workSource; |
| connectionStartTimeMillis = connectionStartTime; |
| |
| mConnected = false; |
| mValidated = false; |
| } |
| |
| public NetworkConnectionState setConnected(boolean connected) { |
| mConnected = connected; |
| return this; |
| } |
| |
| @VisibleForTesting |
| public boolean isConnected() { |
| return mConnected; |
| } |
| |
| public NetworkConnectionState setValidated(boolean validated) { |
| mValidated = validated; |
| return this; |
| } |
| |
| @VisibleForTesting |
| public boolean isValidated() { |
| return mValidated; |
| } |
| } |
| |
| @VisibleForTesting |
| SparseArray<NetworkConnectionState> getNetworkConnectionState() { |
| return mNetworkConnectionStates; |
| } |
| |
| /** The Multi Internet Connection Status Listener. The registered listener will be notified |
| * for the connection status change and scan needed. */ |
| public interface ConnectionStatusListener { |
| /** Called when connection status changed */ |
| void onStatusChange( |
| @MultiInternetManager.MultiInternetState int state, |
| WorkSource requestorWs); |
| /** Called when a scan is needed */ |
| void onStartScan(WorkSource requestorWs); |
| } |
| |
| @Nullable private WorkSource getRequestorWorkSource(int band) { |
| if (!mNetworkConnectionStates.contains(band)) { |
| return null; |
| } |
| return mNetworkConnectionStates.get(band).requestorWorkSource; |
| } |
| |
| private class ModeChangeCallback implements ActiveModeWarden.ModeChangeCallback { |
| @Override |
| public void onActiveModeManagerAdded(@NonNull ActiveModeManager activeModeManager) { |
| if (!mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet() |
| || !isStaConcurrencyForMultiInternetEnabled()) { |
| return; |
| } |
| if (!(activeModeManager instanceof ConcreteClientModeManager)) { |
| return; |
| } |
| final ConcreteClientModeManager ccm = (ConcreteClientModeManager) activeModeManager; |
| // TODO: b/197670907 : Add client role ROLE_CLIENT_SECONDARY_INTERNET |
| if (ccm.getRole() != ROLE_CLIENT_SECONDARY_LONG_LIVED || !ccm.isSecondaryInternet()) { |
| return; |
| } |
| if (mVerboseLoggingEnabled) { |
| Log.v(TAG, "Secondary ClientModeManager created for internet, connecting!"); |
| } |
| updateNetworkConnectionStates(); |
| } |
| |
| @Override |
| public void onActiveModeManagerRemoved(@NonNull ActiveModeManager activeModeManager) { |
| if (!mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet() |
| || !isStaConcurrencyForMultiInternetEnabled()) { |
| return; |
| } |
| if (!(activeModeManager instanceof ConcreteClientModeManager)) { |
| return; |
| } |
| final ConcreteClientModeManager ccm = (ConcreteClientModeManager) activeModeManager; |
| // TODO: b/197670907 : Add client role ROLE_CLIENT_SECONDARY_INTERNET |
| if (ccm.getRole() != ROLE_CLIENT_SECONDARY_LONG_LIVED || !ccm.isSecondaryInternet()) { |
| return; |
| } |
| if (mVerboseLoggingEnabled) { |
| Log.v(TAG, "ClientModeManager for internet removed"); |
| } |
| // A secondary cmm was removed because of the connection was lost, start scan |
| // to find the new network connection. |
| updateNetworkConnectionStates(); |
| if (hasPendingConnectionRequests()) { |
| startConnectivityScan(); |
| } |
| } |
| |
| @Override |
| public void onActiveModeManagerRoleChanged(@NonNull ActiveModeManager activeModeManager) { |
| if (!mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet() |
| || !isStaConcurrencyForMultiInternetEnabled()) { |
| return; |
| } |
| if (!(activeModeManager instanceof ConcreteClientModeManager)) { |
| return; |
| } |
| final ConcreteClientModeManager ccm = (ConcreteClientModeManager) activeModeManager; |
| if (ccm.getPreviousRole() == ROLE_CLIENT_SECONDARY_LONG_LIVED |
| && ccm.isSecondaryInternet()) { |
| Log.w(TAG, "Secondary client mode manager changed role to " |
| + ccm.getRole()); |
| } |
| updateNetworkConnectionStates(); |
| } |
| } |
| |
| private class ClientModeListenerInternal implements ClientModeImplListener { |
| @Override |
| public void onInternetValidated(@NonNull ConcreteClientModeManager clientModeManager) { |
| if (!mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet() |
| || !isStaConcurrencyForMultiInternetEnabled()) { |
| return; |
| } |
| final WifiInfo info = clientModeManager.syncRequestConnectionInfo(); |
| if (info != null) { |
| final int band = ScanResult.toBand(info.getFrequency()); |
| if (mNetworkConnectionStates.contains(band)) { |
| mNetworkConnectionStates.get(band).setValidated(true); |
| } |
| } |
| if (mVerboseLoggingEnabled) { |
| Log.v(TAG, "ClientModeManager role " + clientModeManager.getRole() |
| + " internet validated for connection"); |
| } |
| // If the primary role was connected and internet validated, update the connection state |
| // immediately and issue scan for secondary network connection if needed. |
| // If the secondary role was connected and internet validated, update the connection |
| // state and notify connectivity manager. |
| // TODO: b/197670907 : Add client role ROLE_CLIENT_SECONDARY_INTERNET |
| if (clientModeManager.getRole() == ROLE_CLIENT_PRIMARY) { |
| updateNetworkConnectionStates(); |
| final int band = findUnconnectedRequestBand(); |
| if (band != ScanResult.UNSPECIFIED) { |
| // Trigger the connectivity scan |
| mConnectionStatusListener.onStartScan(getRequestorWorkSource(band)); |
| } |
| } else if (clientModeManager.getRole() == ROLE_CLIENT_SECONDARY_LONG_LIVED |
| && clientModeManager.isSecondaryInternet()) { |
| updateNetworkConnectionStates(); |
| } |
| } |
| |
| // TODO(b/175896748): not yet triggered by ClientModeImpl |
| @Override |
| public void onL3Connected(@NonNull ConcreteClientModeManager clientModeManager) { |
| if (!mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet() |
| || !isStaConcurrencyForMultiInternetEnabled()) { |
| return; |
| } |
| // TODO: b/197670907 : Add client role ROLE_CLIENT_SECONDARY_INTERNET |
| if (clientModeManager.getRole() != ROLE_CLIENT_SECONDARY_LONG_LIVED |
| || !clientModeManager.isSecondaryInternet()) { |
| return; |
| } |
| updateNetworkConnectionStates(); |
| // If no pending connection requests, update connection listener. |
| if (!hasPendingConnectionRequests()) { |
| final int band = getSecondaryConnectedNetworkBand(); |
| if (band == ScanResult.UNSPECIFIED) return; |
| final long connectionTime = mClock.getElapsedSinceBootMillis() |
| - mNetworkConnectionStates.get(band).connectionStartTimeMillis; |
| if (mVerboseLoggingEnabled) { |
| Log.v(TAG, "ClientModeManager for internet L3 connected for " |
| + connectionTime + " ms."); |
| } |
| handleConnectionStateChange(MULTI_INTERNET_STATE_CONNECTED, |
| getRequestorWorkSource(band)); |
| } |
| } |
| |
| @Override |
| public void onConnectionEnd(@NonNull ConcreteClientModeManager clientModeManager) { |
| if (!mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet() |
| || !isStaConcurrencyForMultiInternetEnabled()) { |
| return; |
| } |
| if (clientModeManager.getRole() == ROLE_CLIENT_PRIMARY) { |
| if (mVerboseLoggingEnabled) { |
| Log.v(TAG, "Connection end on primary client mode manager"); |
| } |
| // When the primary network connection is ended, disconnect the secondary network, |
| // as the secondary network is opportunistic. |
| // TODO: b/197670907 : Add client role ROLE_CLIENT_SECONDARY_INTERNET |
| for (ConcreteClientModeManager cmm : mActiveModeWarden.getClientModeManagersInRoles( |
| ROLE_CLIENT_SECONDARY_LONG_LIVED)) { |
| if (cmm.isSecondaryInternet()) { |
| if (mVerboseLoggingEnabled) { |
| Log.v(TAG, "Disconnect secondary client mode manager"); |
| } |
| cmm.disconnect(); |
| } |
| } |
| // As the secondary network is disconnected, mark all bands as disconnected. |
| for (int i = 0; i < mNetworkConnectionStates.size(); i++) { |
| mNetworkConnectionStates.valueAt(i).setConnected(false); |
| } |
| } |
| updateNetworkConnectionStates(); |
| } |
| } |
| |
| public MultiInternetManager( |
| @NonNull ActiveModeWarden activeModeWarden, |
| @NonNull FrameworkFacade frameworkFacade, |
| @NonNull Context context, |
| @NonNull ClientModeImplMonitor cmiMonitor, |
| @NonNull WifiSettingsStore settingsStore, |
| @NonNull Handler handler, |
| @NonNull Clock clock) { |
| mActiveModeWarden = activeModeWarden; |
| mFrameworkFacade = frameworkFacade; |
| mContext = context; |
| mCmiMonitor = cmiMonitor; |
| mSettingsStore = settingsStore; |
| mEventHandler = handler; |
| mClock = clock; |
| mActiveModeWarden.registerModeChangeCallback(new ModeChangeCallback()); |
| cmiMonitor.registerListener(new ClientModeListenerInternal()); |
| mStaConcurrencyMultiInternetMode = mSettingsStore.getWifiMultiInternetMode(); |
| } |
| |
| /** |
| * Check if Wi-Fi multi internet use case is enabled. |
| * |
| * @return true if Wi-Fi multi internet use case is enabled. |
| */ |
| public boolean isStaConcurrencyForMultiInternetEnabled() { |
| return mStaConcurrencyMultiInternetMode |
| != WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED; |
| } |
| |
| /** |
| * Check if Wi-Fi multi internet use case allows multi AP. |
| * |
| * @return true if Wi-Fi multi internet use case allows multi AP. |
| */ |
| public boolean isStaConcurrencyForMultiInternetMultiApAllowed() { |
| return mStaConcurrencyMultiInternetMode |
| == WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP; |
| } |
| |
| /** |
| * Return Wi-Fi multi internet use case mode. |
| * |
| * @return Current mode of Wi-Fi multi internet use case. |
| */ |
| public @WifiManager.WifiMultiInternetMode int getStaConcurrencyForMultiInternetMode() { |
| if (mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet()) { |
| return mStaConcurrencyMultiInternetMode; |
| } |
| return WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED; |
| } |
| |
| /** |
| * Set the multi internet use case mode. |
| * @return true if the mode set successfully, false if failed. |
| */ |
| public boolean setStaConcurrencyForMultiInternetMode( |
| @WifiManager.WifiMultiInternetMode int mode) { |
| final boolean enabled = (mode != WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED); |
| if (!mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet()) { |
| return false; |
| } |
| |
| if (mode == mStaConcurrencyMultiInternetMode) { |
| return true; |
| } |
| // If the STA+STA multi internet feature was disabled, disconnect the secondary cmm. |
| // TODO: b/197670907 : Add client role ROLE_CLIENT_SECONDARY_INTERNET |
| if (!enabled) { |
| for (ConcreteClientModeManager cmm : mActiveModeWarden.getClientModeManagersInRoles( |
| ROLE_CLIENT_SECONDARY_LONG_LIVED)) { |
| if (cmm.isSecondaryInternet()) { |
| cmm.disconnect(); |
| } |
| } |
| for (int i = 0; i < mNetworkConnectionStates.size(); i++) { |
| // Clear the connection state for all bands. |
| mNetworkConnectionStates.setValueAt(i, new NetworkConnectionState(null)); |
| } |
| handleConnectionStateChange(MULTI_INTERNET_STATE_NONE, null); |
| } else { |
| updateNetworkConnectionStates(); |
| final int band = findUnconnectedRequestBand(); |
| if (band != ScanResult.UNSPECIFIED) { |
| handleConnectionStateChange(MULTI_INTERNET_STATE_CONNECTION_REQUESTED, |
| getRequestorWorkSource(band)); |
| } |
| } |
| mStaConcurrencyMultiInternetMode = mode; |
| mSettingsStore.handleWifiMultiInternetMode(mode); |
| // Check if there is already multi internet request then start scan for connection. |
| if (hasPendingConnectionRequests()) { |
| startConnectivityScan(); |
| } |
| return true; |
| } |
| |
| public void setVerboseLoggingEnabled(boolean enabled) { |
| mVerboseLoggingEnabled = enabled; |
| } |
| |
| /** Set the Multi Internet Connection Status listener. |
| * |
| * @param listener The Multi Internet Connection Status listener. |
| */ |
| public void setConnectionStatusListener(ConnectionStatusListener listener) { |
| mConnectionStatusListener = listener; |
| } |
| |
| /** Notify the BSSID associated event from ClientModeImpl. Triggered by |
| * WifiMonitor.ASSOCIATED_BSSID_EVENT. |
| * @param clientModeManager the client mode manager with BSSID associated event. |
| */ |
| public void notifyBssidAssociatedEvent(ConcreteClientModeManager clientModeManager) { |
| if (clientModeManager.getRole() != ROLE_CLIENT_PRIMARY |
| || !mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet() |
| || !isStaConcurrencyForMultiInternetEnabled()) { |
| return; |
| } |
| // If primary CMM has associated to a new BSSID, need to check if it is in a different band |
| // of secondary CMM. |
| final WifiInfo info = clientModeManager.syncRequestConnectionInfo(); |
| final ConcreteClientModeManager secondaryCcmm = |
| mActiveModeWarden.getClientModeManagerInRole(ROLE_CLIENT_SECONDARY_LONG_LIVED); |
| // If no secondary client mode manager then it's ok |
| if (secondaryCcmm == null) return; |
| // If secondary client mode manager is not connected or not for secondary internet |
| if (!secondaryCcmm.isConnected() || !secondaryCcmm.isSecondaryInternet()) return; |
| final WifiInfo info2 = secondaryCcmm.syncRequestConnectionInfo(); |
| // If secondary network is in same band as primary now |
| if (ScanResult.toBand(info.getFrequency()) == ScanResult.toBand(info2.getFrequency())) { |
| // Need to disconnect secondary network |
| secondaryCcmm.disconnect(); |
| // As the secondary network is disconnected, mark all bands as disconnected. |
| for (int i = 0; i < mNetworkConnectionStates.size(); i++) { |
| mNetworkConnectionStates.valueAt(i).setConnected(false); |
| } |
| updateNetworkConnectionStates(); |
| } |
| } |
| |
| /** Check if there is a connection request for multi internet |
| * @return true if there is one or more connection request |
| */ |
| public boolean hasPendingConnectionRequests() { |
| return findUnconnectedRequestBand() != ScanResult.UNSPECIFIED; |
| } |
| |
| /** |
| * Check if there is connection request on a specific band. |
| * @param band The band for the connection request. |
| * @return true if there is connection request on specific band. |
| */ |
| public boolean hasConnectionRequest(int band) { |
| return mNetworkConnectionStates.contains(band) |
| ? (getRequestorWorkSource(band) != null) : false; |
| } |
| |
| /** |
| * Check if there is unconnected network connection request. |
| * @return the band of the connection request that is still not connected. |
| */ |
| public int findUnconnectedRequestBand() { |
| for (int i = 0; i < mNetworkConnectionStates.size(); i++) { |
| if (!mNetworkConnectionStates.valueAt(i).isConnected()) { |
| return mNetworkConnectionStates.keyAt(i); |
| } |
| } |
| return ScanResult.UNSPECIFIED; |
| } |
| |
| /** |
| * Traverse the client mode managers and update the internal connection states. |
| */ |
| private void updateNetworkConnectionStates() { |
| for (int i = 0; i < mNetworkConnectionStates.size(); i++) { |
| mNetworkConnectionStates.valueAt(i).setConnected(false); |
| } |
| |
| for (ClientModeManager clientModeManager : |
| mActiveModeWarden.getInternetConnectivityClientModeManagers()) { |
| // TODO: b/197670907 : Add client role ROLE_CLIENT_SECONDARY_INTERNET |
| if (clientModeManager instanceof ConcreteClientModeManager |
| && (clientModeManager.getRole() == ROLE_CLIENT_PRIMARY |
| || clientModeManager.getRole() == ROLE_CLIENT_SECONDARY_LONG_LIVED)) { |
| ConcreteClientModeManager ccmm = (ConcreteClientModeManager) clientModeManager; |
| // Exclude the secondary client mode manager not for secondary internet. |
| if (ccmm.getRole() == ROLE_CLIENT_SECONDARY_LONG_LIVED |
| && !ccmm.isSecondaryInternet()) { |
| continue; |
| } |
| WifiInfo info = clientModeManager.syncRequestConnectionInfo(); |
| // Exclude the network that is not connected or restricted. |
| if (info == null || !clientModeManager.isConnected() |
| || info.isRestricted()) continue; |
| // Exclude the network that is oem paid/private. |
| if (SdkLevel.isAtLeastT() && (info.isOemPaid() || info.isOemPrivate())) continue; |
| final int band = ScanResult.toBand(info.getFrequency()); |
| if (mNetworkConnectionStates.contains(band)) { |
| // Update the connected state |
| mNetworkConnectionStates.get(band).setConnected(true); |
| } |
| if (mVerboseLoggingEnabled) { |
| Log.v(TAG, "network band " + band + " role " |
| + clientModeManager.getRole().toString()); |
| } |
| } |
| } |
| // Handle the state change and notify listener |
| if (!hasPendingConnectionRequests()) { |
| if (mNetworkConnectionStates.size() == 0) { |
| handleConnectionStateChange(MULTI_INTERNET_STATE_NONE, null); |
| } else { |
| final int band = getSecondaryConnectedNetworkBand(); |
| if (band == ScanResult.UNSPECIFIED) return; |
| handleConnectionStateChange(MULTI_INTERNET_STATE_CONNECTED, |
| getRequestorWorkSource(band)); |
| } |
| } else { |
| final int band = findUnconnectedRequestBand(); |
| handleConnectionStateChange(MULTI_INTERNET_STATE_CONNECTION_REQUESTED, |
| getRequestorWorkSource(band)); |
| } |
| } |
| |
| /** |
| * Set a network connection request from a requestor WorkSource for a specific band, or clear |
| * the connection request if the WorkSource is null. |
| * Triggered when {@link MultiInternetWifiNetworkFactory} has a pending network request. |
| * @param band The band of the Wi-Fi network requested. |
| * @param requestorWs The requestor's WorkSource. Null to clear a network request for a |
| * a band. |
| */ |
| public void setMultiInternetConnectionWorksource(int band, WorkSource requestorWs) { |
| if (!isStaConcurrencyForMultiInternetEnabled()) { |
| Log.w(TAG, "MultInternet is not enabled."); |
| return; |
| } |
| if (mVerboseLoggingEnabled) { |
| Log.v(TAG, "setMultiInternetConnectionWorksource: band=" + band + ", requestorWs=" |
| + requestorWs); |
| } |
| if (requestorWs == null) { |
| // Disconnect secondary network if the request is removed. |
| if (band == getSecondaryConnectedNetworkBand()) { |
| for (ConcreteClientModeManager cmm : mActiveModeWarden.getClientModeManagersInRoles( |
| ROLE_CLIENT_SECONDARY_LONG_LIVED)) { |
| if (cmm.isSecondaryInternet()) { |
| cmm.disconnect(); |
| } |
| } |
| } |
| mNetworkConnectionStates.remove(band); |
| updateNetworkConnectionStates(); |
| return; |
| } |
| if (mNetworkConnectionStates.contains(band)) { |
| Log.w(TAG, "band " + band + " already requested."); |
| } |
| mNetworkConnectionStates.put(band, new NetworkConnectionState(requestorWs, |
| mClock.getElapsedSinceBootMillis())); |
| startConnectivityScan(); |
| } |
| |
| /** Returns the band of the secondary network connected. */ |
| private int getSecondaryConnectedNetworkBand() { |
| final ConcreteClientModeManager secondaryCcmm = |
| mActiveModeWarden.getClientModeManagerInRole(ROLE_CLIENT_SECONDARY_LONG_LIVED); |
| if (secondaryCcmm == null) { |
| return ScanResult.UNSPECIFIED; |
| } |
| final WifiInfo info = secondaryCcmm.syncRequestConnectionInfo(); |
| // Make sure secondary network is connected. |
| if (info == null || !secondaryCcmm.isConnected() || !secondaryCcmm.isSecondaryInternet()) { |
| return ScanResult.UNSPECIFIED; |
| } |
| return ScanResult.toBand(info.getFrequency()); |
| } |
| |
| /** |
| * Handles the connection state change and notifies the status listener. |
| * The listener will only be notified when the state changes. If the state remains the same |
| * but with a different requestor WorkSource then the listener is not notified. |
| * |
| * @param state |
| * @param workSource |
| */ |
| private void handleConnectionStateChange(int state, WorkSource workSource) { |
| if (mMultiInternetConnectionState == state) { |
| return; |
| } |
| mMultiInternetConnectionState = state; |
| mConnectionStatusListener.onStatusChange(state, workSource); |
| } |
| |
| /** |
| * Start a connectivity scan to trigger the network selection process and connect to |
| * the requested multi internet networks. |
| */ |
| private void startConnectivityScan() { |
| if (!isStaConcurrencyForMultiInternetEnabled()) { |
| return; |
| } |
| updateNetworkConnectionStates(); |
| |
| final int band = findUnconnectedRequestBand(); |
| if (band == ScanResult.UNSPECIFIED) return; |
| NetworkConnectionState state = mNetworkConnectionStates.get(band); |
| if (mVerboseLoggingEnabled) { |
| Log.v(TAG, "Schedule connectivity scan for network request with band " + band |
| + " start time " + state.connectionStartTimeMillis + " now " |
| + mClock.getElapsedSinceBootMillis()); |
| } |
| // Trigger the connectivity scan |
| mConnectionStatusListener.onStartScan(getRequestorWorkSource(band)); |
| } |
| |
| /** Dump the internal states of MultiInternetManager */ |
| public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { |
| pw.println("Dump of MultiInternetManager"); |
| pw.println(TAG + ": mStaConcurrencyMultiInternetMode " |
| + mStaConcurrencyMultiInternetMode); |
| for (int i = 0; i < mNetworkConnectionStates.size(); i++) { |
| pw.println("band " + mNetworkConnectionStates.keyAt(i) + " connected " |
| + mNetworkConnectionStates.valueAt(i).isConnected() |
| + " validated " + mNetworkConnectionStates.valueAt(i).isValidated()); |
| } |
| } |
| |
| } |