Search in sources :

Example 81 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project platform_frameworks_base by android.

the class ConnectivityService method rematchNetworkAndRequests.

// Handles a network appearing or improving its score.
//
// - Evaluates all current NetworkRequests that can be
//   satisfied by newNetwork, and reassigns to newNetwork
//   any such requests for which newNetwork is the best.
//
// - Lingers any validated Networks that as a result are no longer
//   needed. A network is needed if it is the best network for
//   one or more NetworkRequests, or if it is a VPN.
//
// - Tears down newNetwork if it just became validated
//   but turns out to be unneeded.
//
// - If reapUnvalidatedNetworks==REAP, tears down unvalidated
//   networks that have no chance (i.e. even if validated)
//   of becoming the highest scoring network.
//
// NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
// it does not remove NetworkRequests that other Networks could better satisfy.
// If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}.
// This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
// as it performs better by a factor of the number of Networks.
//
// @param newNetwork is the network to be matched against NetworkRequests.
// @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be
//               performed to tear down unvalidated networks that have no chance (i.e. even if
//               validated) of becoming the highest scoring network.
private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
    if (!newNetwork.everConnected)
        return;
    boolean keep = newNetwork.isVPN();
    boolean isNewDefault = false;
    NetworkAgentInfo oldDefaultNetwork = null;
    final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork();
    final int score = newNetwork.getCurrentScore();
    if (VDBG)
        log("rematching " + newNetwork.name());
    // Find and migrate to this Network any NetworkRequests for
    // which this network is now the best.
    ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<NetworkAgentInfo>();
    ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<NetworkRequestInfo>();
    NetworkCapabilities nc = newNetwork.networkCapabilities;
    if (VDBG)
        log(" network has: " + nc);
    for (NetworkRequestInfo nri : mNetworkRequests.values()) {
        // requests or not, and doesn't affect the network's score.
        if (nri.request.isListen())
            continue;
        final NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
        final boolean satisfies = newNetwork.satisfies(nri.request);
        if (newNetwork == currentNetwork && satisfies) {
            if (VDBG) {
                log("Network " + newNetwork.name() + " was already satisfying" + " request " + nri.request.requestId + ". No change.");
            }
            keep = true;
            continue;
        }
        // check if it satisfies the NetworkCapabilities
        if (VDBG)
            log("  checking if request is satisfied: " + nri.request);
        if (satisfies) {
            // this request
            if (VDBG) {
                log("currentScore = " + (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) + ", newScore = " + score);
            }
            if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
                if (VDBG)
                    log("rematch for " + newNetwork.name());
                if (currentNetwork != null) {
                    if (VDBG)
                        log("   accepting network in place of " + currentNetwork.name());
                    currentNetwork.removeRequest(nri.request.requestId);
                    currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs);
                    affectedNetworks.add(currentNetwork);
                } else {
                    if (VDBG)
                        log("   accepting network in place of null");
                }
                newNetwork.unlingerRequest(nri.request);
                mNetworkForRequestId.put(nri.request.requestId, newNetwork);
                if (!newNetwork.addRequest(nri.request)) {
                    Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request);
                }
                addedRequests.add(nri);
                keep = true;
                // Tell NetworkFactories about the new score, so they can stop
                // trying to connect if they know they cannot match it.
                // TODO - this could get expensive if we have alot of requests for this
                // network.  Think about if there is a way to reduce this.  Push
                // netid->request mapping to each factory?
                sendUpdatedScoreToFactories(nri.request, score);
                if (isDefaultRequest(nri)) {
                    isNewDefault = true;
                    oldDefaultNetwork = currentNetwork;
                    if (currentNetwork != null) {
                        mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork);
                    }
                }
            }
        } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
            // longer satisfies "nri" when "currentNetwork" does not equal "newNetwork".
            if (DBG) {
                log("Network " + newNetwork.name() + " stopped satisfying" + " request " + nri.request.requestId);
            }
            newNetwork.removeRequest(nri.request.requestId);
            if (currentNetwork == newNetwork) {
                mNetworkForRequestId.remove(nri.request.requestId);
                sendUpdatedScoreToFactories(nri.request, 0);
            } else {
                Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " + newNetwork.name() + " without updating mNetworkForRequestId or factories!");
            }
            // TODO: Technically, sending CALLBACK_LOST here is
            // incorrect if there is a replacement network currently
            // connected that can satisfy nri, which is a request
            // (not a listen). However, the only capability that can both
            // a) be requested and b) change is NET_CAPABILITY_TRUSTED,
            // so this code is only incorrect for a network that loses
            // the TRUSTED capability, which is a rare case.
            callCallbackForRequest(nri, newNetwork, ConnectivityManager.CALLBACK_LOST, 0);
        }
    }
    if (isNewDefault) {
        // Notify system services that this network is up.
        makeDefault(newNetwork);
        // Log 0 -> X and Y -> X default network transitions, where X is the new default.
        logDefaultNetworkEvent(newNetwork, oldDefaultNetwork);
        synchronized (ConnectivityService.this) {
            // to reconnect over the new network
            if (mNetTransitionWakeLock.isHeld()) {
                mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_CLEAR_NET_TRANSITION_WAKELOCK, mNetTransitionWakeLockSerialNumber, 0), 1000);
            }
        }
    }
    if (!newNetwork.networkCapabilities.equalRequestableCapabilities(nc)) {
        Slog.wtf(TAG, String.format("BUG: %s changed requestable capabilities during rematch: %s -> %s", nc, newNetwork.networkCapabilities));
    }
    if (newNetwork.getCurrentScore() != score) {
        Slog.wtf(TAG, String.format("BUG: %s changed score during rematch: %d -> %d", score, newNetwork.getCurrentScore()));
    }
    // Second pass: process all listens.
    if (wasBackgroundNetwork != newNetwork.isBackgroundNetwork()) {
        // If the network went from background to foreground or vice versa, we need to update
        // its foreground state. It is safe to do this after rematching the requests because
        // NET_CAPABILITY_FOREGROUND does not affect requests, as is not a requestable
        // capability and does not affect the network's score (see the Slog.wtf call above).
        updateCapabilities(score, newNetwork, newNetwork.networkCapabilities);
    } else {
        processListenRequests(newNetwork, false);
    }
    // before LegacyTypeTracker sends legacy broadcasts
    for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri);
    // available callback for newNetwork.
    for (NetworkAgentInfo nai : affectedNetworks) {
        updateLingerState(nai, now);
    }
    // Possibly unlinger newNetwork. Unlingering a network does not send any callbacks so it
    // does not need to be done in any particular order.
    updateLingerState(newNetwork, now);
    if (isNewDefault) {
        // the new one connected.
        if (oldDefaultNetwork != null) {
            mLegacyTypeTracker.remove(oldDefaultNetwork.networkInfo.getType(), oldDefaultNetwork, true);
        }
        mDefaultInetConditionPublished = newNetwork.lastValidated ? 100 : 0;
        mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork);
        notifyLockdownVpn(newNetwork);
    }
    if (keep) {
        // TODO: Avoid redoing this; this must only be done once when a network comes online.
        try {
            final IBatteryStats bs = BatteryStatsService.getService();
            final int type = newNetwork.networkInfo.getType();
            final String baseIface = newNetwork.linkProperties.getInterfaceName();
            bs.noteNetworkInterfaceType(baseIface, type);
            for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) {
                final String stackedIface = stacked.getInterfaceName();
                bs.noteNetworkInterfaceType(stackedIface, type);
                NetworkStatsFactory.noteStackedIface(stackedIface, baseIface);
            }
        } catch (RemoteException ignored) {
        }
        // This is on top of the multiple intent sequencing referenced in the todo above.
        for (int i = 0; i < newNetwork.numNetworkRequests(); i++) {
            NetworkRequest nr = newNetwork.requestAt(i);
            if (nr.legacyType != TYPE_NONE && nr.isRequest()) {
                // legacy type tracker filters out repeat adds
                mLegacyTypeTracker.add(nr.legacyType, newNetwork);
            }
        }
        // newNetwork to the tracker explicitly (it's a no-op if it has already been added).
        if (newNetwork.isVPN()) {
            mLegacyTypeTracker.add(TYPE_VPN, newNetwork);
        }
    }
    if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
            if (unneeded(nai, UnneededFor.TEARDOWN)) {
                if (nai.getLingerExpiry() > 0) {
                    // This network has active linger timers and no requests, but is not
                    // lingering. Linger it.
                    //
                    // One way (the only way?) this can happen if this network is unvalidated
                    // and became unneeded due to another network improving its score to the
                    // point where this network will no longer be able to satisfy any requests
                    // even if it validates.
                    updateLingerState(nai, now);
                } else {
                    if (DBG)
                        log("Reaping " + nai.name());
                    teardownUnneededNetwork(nai);
                }
            }
        }
    }
}
Also used : IBatteryStats(com.android.internal.app.IBatteryStats) NetworkAgentInfo(com.android.server.connectivity.NetworkAgentInfo) ArrayList(java.util.ArrayList) NetworkRequest(android.net.NetworkRequest) NetworkPolicyManager.uidRulesToString(android.net.NetworkPolicyManager.uidRulesToString) NetworkCapabilities(android.net.NetworkCapabilities) LinkProperties(android.net.LinkProperties) RemoteException(android.os.RemoteException)

Example 82 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project platform_frameworks_base by android.

the class ConnectivityService method rematchAllNetworksAndRequests.

/**
     * Attempt to rematch all Networks with NetworkRequests.  This may result in Networks
     * being disconnected.
     * @param changed If only one Network's score or capabilities have been modified since the last
     *         time this function was called, pass this Network in this argument, otherwise pass
     *         null.
     * @param oldScore If only one Network has been changed but its NetworkCapabilities have not
     *         changed, pass in the Network's score (from getCurrentScore()) prior to the change via
     *         this argument, otherwise pass {@code changed.getCurrentScore()} or 0 if
     *         {@code changed} is {@code null}. This is because NetworkCapabilities influence a
     *         network's score.
     */
private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
    // TODO: This may get slow.  The "changed" parameter is provided for future optimization
    // to avoid the slowness.  It is not simply enough to process just "changed", for
    // example in the case where "changed"'s score decreases and another network should begin
    // satifying a NetworkRequest that "changed" currently satisfies.
    // Optimization: Only reprocess "changed" if its score improved.  This is safe because it
    // can only add more NetworkRequests satisfied by "changed", and this is exactly what
    // rematchNetworkAndRequests() handles.
    final long now = SystemClock.elapsedRealtime();
    if (changed != null && oldScore < changed.getCurrentScore()) {
        rematchNetworkAndRequests(changed, ReapUnvalidatedNetworks.REAP, now);
    } else {
        final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray(new NetworkAgentInfo[mNetworkAgentInfos.size()]);
        // Rematch higher scoring networks first to prevent requests first matching a lower
        // scoring network and then a higher scoring network, which could produce multiple
        // callbacks and inadvertently unlinger networks.
        Arrays.sort(nais);
        for (NetworkAgentInfo nai : nais) {
            rematchNetworkAndRequests(nai, // rematched.
            (nai != nais[nais.length - 1]) ? ReapUnvalidatedNetworks.DONT_REAP : ReapUnvalidatedNetworks.REAP, now);
        }
    }
}
Also used : NetworkAgentInfo(com.android.server.connectivity.NetworkAgentInfo)

Example 83 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project platform_frameworks_base by android.

the class ConnectivityService method registerNetworkAgent.

public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkMisc networkMisc) {
    enforceConnectivityInternalPermission();
    // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
    // satisfies mDefaultRequest.
    final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(linkProperties), new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
    synchronized (this) {
        nai.networkMonitor.systemReady = mSystemReady;
    }
    addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network, networkInfo.getExtraInfo());
    if (DBG)
        log("registerNetworkAgent " + nai);
    mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
    return nai.network.netId;
}
Also used : NetworkMisc(android.net.NetworkMisc) NetworkInfo(android.net.NetworkInfo) NetworkAgentInfo(com.android.server.connectivity.NetworkAgentInfo) Network(android.net.Network) AsyncChannel(com.android.internal.util.AsyncChannel) LinkProperties(android.net.LinkProperties) NetworkCapabilities(android.net.NetworkCapabilities)

Example 84 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project platform_frameworks_base by android.

the class ConnectivityService method requestBandwidthUpdate.

@Override
public boolean requestBandwidthUpdate(Network network) {
    enforceAccessPermission();
    NetworkAgentInfo nai = null;
    if (network == null) {
        return false;
    }
    synchronized (mNetworkForNetId) {
        nai = mNetworkForNetId.get(network.netId);
    }
    if (nai != null) {
        nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
        return true;
    }
    return false;
}
Also used : NetworkAgentInfo(com.android.server.connectivity.NetworkAgentInfo)

Example 85 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project platform_frameworks_base by android.

the class ConnectivityService method dumpNetworkDiagnostics.

private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
    final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
    final long DIAG_TIME_MS = 5000;
    for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
        // Start gathering diagnostic information.
        netDiags.add(new NetworkDiagnostics(nai.network, // Must be a copy.
        new LinkProperties(nai.linkProperties), DIAG_TIME_MS));
    }
    for (NetworkDiagnostics netDiag : netDiags) {
        pw.println();
        netDiag.waitForMeasurements();
        netDiag.dump(pw);
    }
}
Also used : NetworkDiagnostics(com.android.server.connectivity.NetworkDiagnostics) NetworkAgentInfo(com.android.server.connectivity.NetworkAgentInfo) ArrayList(java.util.ArrayList) LinkProperties(android.net.LinkProperties)

Aggregations

NetworkAgentInfo (com.android.server.connectivity.NetworkAgentInfo)165 LinkProperties (android.net.LinkProperties)40 Network (android.net.Network)25 NetworkPolicyManager.uidRulesToString (android.net.NetworkPolicyManager.uidRulesToString)21 NetworkCapabilities (android.net.NetworkCapabilities)20 NetworkInfo (android.net.NetworkInfo)15 NetworkRequest (android.net.NetworkRequest)15 NetworkState (android.net.NetworkState)15 RemoteException (android.os.RemoteException)14 UnknownHostException (java.net.UnknownHostException)14 AsyncChannel (com.android.internal.util.AsyncChannel)11 Vpn (com.android.server.connectivity.Vpn)10 ArrayList (java.util.ArrayList)10 FileNotFoundException (java.io.FileNotFoundException)9 IOException (java.io.IOException)9 InetAddress (java.net.InetAddress)9 XmlPullParserException (org.xmlpull.v1.XmlPullParserException)9 Nullable (android.annotation.Nullable)5 PendingIntent (android.app.PendingIntent)5 Intent (android.content.Intent)5