Search in sources :

Example 96 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project android_frameworks_base by DirtyUnicorns.

the class ConnectivityService method sendLegacyNetworkBroadcast.

private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) {
    // The NetworkInfo we actually send out has no bearing on the real
    // state of affairs. For example, if the default connection is mobile,
    // and a request for HIPRI has just gone away, we need to pretend that
    // HIPRI has just disconnected. So we need to set the type to HIPRI and
    // the state to DISCONNECTED, even though the network is of type MOBILE
    // and is still connected.
    NetworkInfo info = new NetworkInfo(nai.networkInfo);
    info.setType(type);
    if (state != DetailedState.DISCONNECTED) {
        info.setDetailedState(state, null, info.getExtraInfo());
        sendConnectedBroadcast(info);
    } else {
        info.setDetailedState(state, info.getReason(), info.getExtraInfo());
        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
        if (info.isFailover()) {
            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
            nai.networkInfo.setFailover(false);
        }
        if (info.getReason() != null) {
            intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
        }
        if (info.getExtraInfo() != null) {
            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
        }
        NetworkAgentInfo newDefaultAgent = null;
        if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
            newDefaultAgent = getDefaultNetwork();
            if (newDefaultAgent != null) {
                intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, newDefaultAgent.networkInfo);
            } else {
                intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
            }
        }
        intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
        sendStickyBroadcast(intent);
        if (newDefaultAgent != null) {
            sendConnectedBroadcast(newDefaultAgent.networkInfo);
        }
    }
}
Also used : NetworkInfo(android.net.NetworkInfo) NetworkAgentInfo(com.android.server.connectivity.NetworkAgentInfo) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent)

Example 97 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project android_frameworks_base by DirtyUnicorns.

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) notifyNetworkCallback(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 98 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project android_frameworks_base by DirtyUnicorns.

the class ConnectivityService method dumpAvoidBadWifiSettings.

// TODO: Evaluate whether this is of interest to other consumers of
// AvoidBadWifiTracker and worth moving out of here.
private void dumpAvoidBadWifiSettings(IndentingPrintWriter pw) {
    final boolean configRestrict = mAvoidBadWifiTracker.configRestrictsAvoidBadWifi();
    if (!configRestrict) {
        pw.println("Bad Wi-Fi avoidance: unrestricted");
        return;
    }
    pw.println("Bad Wi-Fi avoidance: " + avoidBadWifi());
    pw.increaseIndent();
    pw.println("Config restrict:   " + configRestrict);
    final String value = mAvoidBadWifiTracker.getSettingsValue();
    String description;
    // Can't use a switch statement because strings are legal case labels, but null is not.
    if ("0".equals(value)) {
        description = "get stuck";
    } else if (value == null) {
        description = "prompt";
    } else if ("1".equals(value)) {
        description = "avoid";
    } else {
        description = value + " (?)";
    }
    pw.println("User setting:      " + description);
    pw.println("Network overrides:");
    pw.increaseIndent();
    for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
        if (nai.avoidUnvalidated) {
            pw.println(nai.name());
        }
    }
    pw.decreaseIndent();
    pw.decreaseIndent();
}
Also used : NetworkAgentInfo(com.android.server.connectivity.NetworkAgentInfo) NetworkPolicyManager.uidRulesToString(android.net.NetworkPolicyManager.uidRulesToString)

Example 99 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project android_frameworks_base by DirtyUnicorns.

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 100 with NetworkAgentInfo

use of com.android.server.connectivity.NetworkAgentInfo in project android_frameworks_base by DirtyUnicorns.

the class ConnectivityService method handleAsyncChannelDisconnected.

private void handleAsyncChannelDisconnected(Message msg) {
    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
    if (nai != null) {
        if (DBG) {
            log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests());
        }
        // disconnect the channel.
        if (nai.networkInfo.isConnected()) {
            nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
        }
        final boolean wasDefault = isDefaultNetwork(nai);
        if (wasDefault) {
            mDefaultInetConditionPublished = 0;
            // Log default network disconnection before required book-keeping.
            // Let rematchAllNetworksAndRequests() below record a new default network event
            // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
            // whose timestamps tell how long it takes to recover a default network.
            logDefaultNetworkEvent(null, nai);
        }
        notifyIfacesChangedForNetworkStats();
        // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
        // by other networks that are already connected. Perhaps that can be done by
        // sending all CALLBACK_LOST messages (for requests, not listens) at the end
        // of rematchAllNetworksAndRequests
        notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
        mKeepaliveTracker.handleStopAllKeepalives(nai, ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
        nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
        mNetworkAgentInfos.remove(msg.replyTo);
        updateClat(null, nai.linkProperties, nai);
        synchronized (mNetworkForNetId) {
            // Remove the NetworkAgent, but don't mark the netId as
            // available until we've told netd to delete it below.
            mNetworkForNetId.remove(nai.network.netId);
        }
        // Remove all previously satisfied requests.
        for (int i = 0; i < nai.numNetworkRequests(); i++) {
            NetworkRequest request = nai.requestAt(i);
            NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
            if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
                mNetworkForRequestId.remove(request.requestId);
                sendUpdatedScoreToFactories(request, 0);
            }
        }
        nai.clearLingerState();
        if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
            removeDataActivityTracking(nai);
            notifyLockdownVpn(nai);
            requestNetworkTransitionWakelock(nai.name());
        }
        mLegacyTypeTracker.remove(nai, wasDefault);
        rematchAllNetworksAndRequests(null, 0);
        mLingerMonitor.noteDisconnect(nai);
        if (nai.created) {
            // long time.
            try {
                mNetd.removeNetwork(nai.network.netId);
            } catch (Exception e) {
                loge("Exception removing network: " + e);
            }
        }
        synchronized (mNetworkForNetId) {
            mNetIdInUse.delete(nai.network.netId);
        }
    } else {
        NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
        if (DBG && nfi != null)
            log("unregisterNetworkFactory for " + nfi.name);
    }
}
Also used : NetworkAgentInfo(com.android.server.connectivity.NetworkAgentInfo) NetworkRequest(android.net.NetworkRequest) RemoteException(android.os.RemoteException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) FileNotFoundException(java.io.FileNotFoundException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException)

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