use of com.android.internal.app.IBatteryStats 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);
}
}
}
}
}
use of com.android.internal.app.IBatteryStats in project android_frameworks_base by AOSPA.
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);
}
}
}
}
}
use of com.android.internal.app.IBatteryStats in project android_frameworks_base by AOSPA.
the class ConnectivityService method sendStickyBroadcast.
private void sendStickyBroadcast(Intent intent) {
synchronized (this) {
if (!mSystemReady) {
mInitialBroadcast = new Intent(intent);
}
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (VDBG) {
log("sendStickyBroadcast: action=" + intent.getAction());
}
Bundle options = null;
final long ident = Binder.clearCallingIdentity();
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
final NetworkInfo ni = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (ni.getType() == ConnectivityManager.TYPE_MOBILE_SUPL) {
intent.setAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
} else {
BroadcastOptions opts = BroadcastOptions.makeBasic();
opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
options = opts.toBundle();
}
final IBatteryStats bs = BatteryStatsService.getService();
try {
bs.noteConnectivityChanged(intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_NONE), ni != null ? ni.getState().toString() : "?");
} catch (RemoteException e) {
}
}
try {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL, options);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
use of com.android.internal.app.IBatteryStats in project android_frameworks_base by ResurrectionRemix.
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);
}
}
}
}
}
use of com.android.internal.app.IBatteryStats in project android_frameworks_base by ResurrectionRemix.
the class ConnectivityService method sendStickyBroadcast.
private void sendStickyBroadcast(Intent intent) {
synchronized (this) {
if (!mSystemReady) {
mInitialBroadcast = new Intent(intent);
}
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (VDBG) {
log("sendStickyBroadcast: action=" + intent.getAction());
}
Bundle options = null;
final long ident = Binder.clearCallingIdentity();
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
final NetworkInfo ni = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (ni.getType() == ConnectivityManager.TYPE_MOBILE_SUPL) {
intent.setAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
} else {
BroadcastOptions opts = BroadcastOptions.makeBasic();
opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
options = opts.toBundle();
}
final IBatteryStats bs = BatteryStatsService.getService();
try {
bs.noteConnectivityChanged(intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_NONE), ni != null ? ni.getState().toString() : "?");
} catch (RemoteException e) {
}
}
try {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL, options);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
Aggregations