Enabling internal msg apis
NetworkFactory and NetworkAgent. First trying with wifi and getting rid of WifiStateTracker. Conflicts: api/current.txt services/core/java/com/android/server/ConnectivityService.java Change-Id: I7f0ec13d7d8988b32f3c6dc71f72012f3349fe02
This commit is contained in:
committed by
Lorenzo Colitti
parent
2a9d35f655
commit
e20f7a2429
@@ -534,38 +534,32 @@ public class ConnectivityManager {
|
||||
/**
|
||||
* Specifies the preferred network type. When the device has more
|
||||
* than one type available the preferred network type will be used.
|
||||
* Note that this made sense when we only had 2 network types,
|
||||
* but with more and more default networks we need an array to list
|
||||
* their ordering. This will be deprecated soon.
|
||||
*
|
||||
* @param preference the network type to prefer over all others. It is
|
||||
* unspecified what happens to the old preferred network in the
|
||||
* overall ordering.
|
||||
* @Deprecated Functionality has been removed as it no longer makes sense,
|
||||
* with many more than two networks - we'd need an array to express
|
||||
* preference. Instead we use dynamic network properties of
|
||||
* the networks to describe their precedence.
|
||||
*/
|
||||
public void setNetworkPreference(int preference) {
|
||||
try {
|
||||
mService.setNetworkPreference(preference);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current preferred network type.
|
||||
* Note that this made sense when we only had 2 network types,
|
||||
* but with more and more default networks we need an array to list
|
||||
* their ordering. This will be deprecated soon.
|
||||
*
|
||||
* @return an integer representing the preferred network type
|
||||
*
|
||||
* <p>This method requires the caller to hold the permission
|
||||
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
|
||||
* @Deprecated Functionality has been removed as it no longer makes sense,
|
||||
* with many more than two networks - we'd need an array to express
|
||||
* preference. Instead we use dynamic network properties of
|
||||
* the networks to describe their precedence.
|
||||
*/
|
||||
public int getNetworkPreference() {
|
||||
try {
|
||||
return mService.getNetworkPreference();
|
||||
} catch (RemoteException e) {
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -723,13 +717,14 @@ public class ConnectivityManager {
|
||||
* {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
|
||||
* {@hide}
|
||||
*/
|
||||
public boolean setRadios(boolean turnOn) {
|
||||
try {
|
||||
return mService.setRadios(turnOn);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// TODO - check for any callers and remove
|
||||
// public boolean setRadios(boolean turnOn) {
|
||||
// try {
|
||||
// return mService.setRadios(turnOn);
|
||||
// } catch (RemoteException e) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Tells a given networkType to set its radio power state as directed.
|
||||
@@ -743,13 +738,14 @@ public class ConnectivityManager {
|
||||
* {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
|
||||
* {@hide}
|
||||
*/
|
||||
public boolean setRadio(int networkType, boolean turnOn) {
|
||||
try {
|
||||
return mService.setRadio(networkType, turnOn);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// TODO - check for any callers and remove
|
||||
// public boolean setRadio(int networkType, boolean turnOn) {
|
||||
// try {
|
||||
// return mService.setRadio(networkType, turnOn);
|
||||
// } catch (RemoteException e) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Tells the underlying networking system that the caller wants to
|
||||
@@ -1594,4 +1590,81 @@ public class ConnectivityManager {
|
||||
mService.registerNetworkFactory(messenger);
|
||||
} catch (RemoteException e) { }
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public void registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
|
||||
NetworkCapabilities nc, int score) {
|
||||
try {
|
||||
mService.registerNetworkAgent(messenger, ni, lp, nc, score);
|
||||
} catch (RemoteException e) { }
|
||||
}
|
||||
|
||||
/** Interface for NetworkRequest callbacks {@hide} */
|
||||
public static class NetworkCallbacks {
|
||||
public static final int PRECHECK = 1;
|
||||
public static final int AVAILABLE = 2;
|
||||
public static final int LOSING = 3;
|
||||
public static final int LOST = 4;
|
||||
public static final int UNAVAIL = 5;
|
||||
public static final int CAP_CHANGED = 6;
|
||||
public static final int PROP_CHANGED = 7;
|
||||
public static final int CANCELED = 8;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Called whenever the framework connects to a network that it may use to
|
||||
* satisfy this request
|
||||
*/
|
||||
public void onPreCheck(NetworkRequest networkRequest, Network network) {}
|
||||
|
||||
/**
|
||||
* Called when the framework connects and has validated the new network.
|
||||
*/
|
||||
public void onAvailable(NetworkRequest networkRequest, Network network) {}
|
||||
|
||||
/**
|
||||
* Called when the framework is losing the network. Often paired with an
|
||||
* onAvailable call with the new replacement network for graceful handover.
|
||||
* This may not be called if we have a hard loss (loss without warning).
|
||||
* This may be followed by either an onLost call or an onAvailable call for this
|
||||
* network depending on if we lose or regain it.
|
||||
*/
|
||||
public void onLosing(NetworkRequest networkRequest, Network network, int maxSecToLive) {}
|
||||
|
||||
/**
|
||||
* Called when the framework has a hard loss of the network or when the
|
||||
* graceful failure ends. Note applications should only request this callback
|
||||
* if the application is willing to track the Available and Lost callbacks
|
||||
* together, else the application may think it has no network when it
|
||||
* really does (A Avail, B Avail, A Lost.. still have B).
|
||||
*/
|
||||
public void onLost(NetworkRequest networkRequest, Network network) {}
|
||||
|
||||
/**
|
||||
* Called if no network is found in the given timeout time. If no timeout is given,
|
||||
* this will not be called.
|
||||
*/
|
||||
public void onUnavailable(NetworkRequest networkRequest) {}
|
||||
|
||||
/**
|
||||
* Called when the network the framework connected to for this request
|
||||
* changes capabilities but still satisfies the stated need.
|
||||
*/
|
||||
public void onCapabilitiesChanged(NetworkRequest networkRequest, Network network,
|
||||
NetworkCapabilities networkCapabilities) {}
|
||||
|
||||
/**
|
||||
* Called when the network the framework connected to for this request
|
||||
* changes properties.
|
||||
*/
|
||||
public void onPropertiesChanged(NetworkRequest networkRequest, Network network,
|
||||
LinkProperties linkProperties) {}
|
||||
|
||||
/**
|
||||
* Called when a CancelRequest call concludes and the registered callbacks will
|
||||
* no longer be used.
|
||||
*/
|
||||
public void onCanceled(NetworkRequest networkRequest) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.net;
|
||||
|
||||
import android.net.LinkQualityInfo;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkQuotaInfo;
|
||||
import android.net.NetworkState;
|
||||
@@ -41,10 +42,6 @@ interface IConnectivityManager
|
||||
// Keep this in sync with framework/native/services/connectivitymanager/ConnectivityManager.h
|
||||
void markSocketAsUser(in ParcelFileDescriptor socket, int uid);
|
||||
|
||||
void setNetworkPreference(int pref);
|
||||
|
||||
int getNetworkPreference();
|
||||
|
||||
NetworkInfo getActiveNetworkInfo();
|
||||
NetworkInfo getActiveNetworkInfoForUid(int uid);
|
||||
NetworkInfo getNetworkInfo(int networkType);
|
||||
@@ -62,10 +59,6 @@ interface IConnectivityManager
|
||||
NetworkQuotaInfo getActiveNetworkQuotaInfo();
|
||||
boolean isActiveNetworkMetered();
|
||||
|
||||
boolean setRadios(boolean onOff);
|
||||
|
||||
boolean setRadio(int networkType, boolean turnOn);
|
||||
|
||||
int startUsingNetworkFeature(int networkType, in String feature,
|
||||
in IBinder binder);
|
||||
|
||||
@@ -147,9 +140,12 @@ interface IConnectivityManager
|
||||
|
||||
LinkQualityInfo[] getAllLinkQualityInfo();
|
||||
|
||||
void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo, in String url);
|
||||
void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo,
|
||||
in String url);
|
||||
|
||||
void setAirplaneMode(boolean enable);
|
||||
|
||||
void registerNetworkFactory(in Messenger messenger);
|
||||
|
||||
void registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, in NetworkCapabilities nc, int score);
|
||||
}
|
||||
|
||||
397
core/java/android/net/NetworkAgent.java
Normal file
397
core/java/android/net/NetworkAgent.java
Normal file
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.net;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.util.AsyncChannel;
|
||||
import com.android.internal.util.Protocol;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* A Utility class for handling NetworkRequests.
|
||||
*
|
||||
* Created by bearer-specific code to handle tracking requests, scores,
|
||||
* network data and handle communicating with ConnectivityService. Two
|
||||
* abstract methods: connect and disconnect are used to act on the
|
||||
* underlying bearer code. Connect is called when we have a NetworkRequest
|
||||
* and our score is better than the current handling network's score, while
|
||||
* disconnect is used when ConnectivityService requests a disconnect.
|
||||
*
|
||||
* A bearer may have more than one NetworkAgent if it can simultaneously
|
||||
* support separate networks (IMS / Internet / MMS Apns on cellular, or
|
||||
* perhaps connections with different SSID or P2P for Wi-Fi). The bearer
|
||||
* code should pass its NetworkAgents the NetworkRequests each NetworkAgent
|
||||
* can handle, demultiplexing for different network types. The bearer code
|
||||
* can also filter out requests it can never handle.
|
||||
*
|
||||
* Each NetworkAgent needs to be given a score and NetworkCapabilities for
|
||||
* their potential network. While disconnected, the NetworkAgent will check
|
||||
* each time its score changes or a NetworkRequest changes to see if
|
||||
* the NetworkAgent can provide a higher scored network for a NetworkRequest
|
||||
* that the NetworkAgent's NetworkCapabilties can satisfy. This condition will
|
||||
* trigger a connect request via connect(). After connection, connection data
|
||||
* should be given to the NetworkAgent by the bearer, including LinkProperties
|
||||
* NetworkCapabilties and NetworkInfo. After that the NetworkAgent will register
|
||||
* with ConnectivityService and forward the data on.
|
||||
* @hide
|
||||
*/
|
||||
public abstract class NetworkAgent extends Handler {
|
||||
private final SparseArray<NetworkRequestAndScore> mNetworkRequests = new SparseArray<>();
|
||||
private boolean mConnectionRequested = false;
|
||||
|
||||
private AsyncChannel mAsyncChannel;
|
||||
private final String LOG_TAG;
|
||||
private static final boolean DBG = true;
|
||||
// TODO - this class shouldn't cache data or it runs the risk of getting out of sync
|
||||
// Make the API require each of these when any is updated so we have the data we need,
|
||||
// without caching.
|
||||
private LinkProperties mLinkProperties;
|
||||
private NetworkInfo mNetworkInfo;
|
||||
private NetworkCapabilities mNetworkCapabilities;
|
||||
private int mNetworkScore;
|
||||
private boolean mRegistered = false;
|
||||
private final Context mContext;
|
||||
private AtomicBoolean mHasRequests = new AtomicBoolean(false);
|
||||
|
||||
// TODO - add a name member for logging purposes.
|
||||
|
||||
protected final Object mLockObj = new Object();
|
||||
|
||||
|
||||
private static final int BASE = Protocol.BASE_NETWORK_AGENT;
|
||||
|
||||
/**
|
||||
* Sent by self to queue up a new/modified request.
|
||||
* obj = NetworkRequestAndScore
|
||||
*/
|
||||
private static final int CMD_ADD_REQUEST = BASE + 1;
|
||||
|
||||
/**
|
||||
* Sent by self to queue up the removal of a request.
|
||||
* obj = NetworkRequest
|
||||
*/
|
||||
private static final int CMD_REMOVE_REQUEST = BASE + 2;
|
||||
|
||||
/**
|
||||
* Sent by ConnectivityService to the NetworkAgent to inform it of
|
||||
* suspected connectivity problems on its network. The NetworkAgent
|
||||
* should take steps to verify and correct connectivity.
|
||||
*/
|
||||
public static final int CMD_SUSPECT_BAD = BASE + 3;
|
||||
|
||||
/**
|
||||
* Sent by the NetworkAgent (note the EVENT vs CMD prefix) to
|
||||
* ConnectivityService to pass the current NetworkInfo (connection state).
|
||||
* Sent when the NetworkInfo changes, mainly due to change of state.
|
||||
* obj = NetworkInfo
|
||||
*/
|
||||
public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 4;
|
||||
|
||||
/**
|
||||
* Sent by the NetworkAgent to ConnectivityService to pass the current
|
||||
* NetworkCapabilties.
|
||||
* obj = NetworkCapabilities
|
||||
*/
|
||||
public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 5;
|
||||
|
||||
/**
|
||||
* Sent by the NetworkAgent to ConnectivityService to pass the current
|
||||
* NetworkProperties.
|
||||
* obj = NetworkProperties
|
||||
*/
|
||||
public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 6;
|
||||
|
||||
/**
|
||||
* Sent by the NetworkAgent to ConnectivityService to pass the current
|
||||
* network score.
|
||||
* arg1 = network score int
|
||||
*/
|
||||
public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 7;
|
||||
|
||||
public NetworkAgent(Looper looper, Context context, String logTag) {
|
||||
super(looper);
|
||||
LOG_TAG = logTag;
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* When conditions are right, register with ConnectivityService.
|
||||
* Connditions include having a well defined network and a request
|
||||
* that justifies it. The NetworkAgent will remain registered until
|
||||
* disconnected.
|
||||
* TODO - this should have all data passed in rather than caching
|
||||
*/
|
||||
private void registerSelf() {
|
||||
synchronized(mLockObj) {
|
||||
if (!mRegistered && mConnectionRequested &&
|
||||
mNetworkInfo != null && mNetworkInfo.isConnected() &&
|
||||
mNetworkCapabilities != null &&
|
||||
mLinkProperties != null &&
|
||||
mNetworkScore != 0) {
|
||||
if (DBG) log("Registering NetworkAgent");
|
||||
mRegistered = true;
|
||||
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
|
||||
Context.CONNECTIVITY_SERVICE);
|
||||
cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(mNetworkInfo),
|
||||
new LinkProperties(mLinkProperties),
|
||||
new NetworkCapabilities(mNetworkCapabilities), mNetworkScore);
|
||||
} else if (DBG && !mRegistered) {
|
||||
String err = "Not registering due to ";
|
||||
if (mConnectionRequested == false) err += "no Connect requested ";
|
||||
if (mNetworkInfo == null) err += "null NetworkInfo ";
|
||||
if (mNetworkInfo != null && mNetworkInfo.isConnected() == false) {
|
||||
err += "NetworkInfo disconnected ";
|
||||
}
|
||||
if (mLinkProperties == null) err += "null LinkProperties ";
|
||||
if (mNetworkCapabilities == null) err += "null NetworkCapabilities ";
|
||||
if (mNetworkScore == 0) err += "null NetworkScore";
|
||||
log(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
|
||||
synchronized (mLockObj) {
|
||||
if (mAsyncChannel != null) {
|
||||
log("Received new connection while already connected!");
|
||||
} else {
|
||||
if (DBG) log("NetworkAgent fully connected");
|
||||
mAsyncChannel = new AsyncChannel();
|
||||
mAsyncChannel.connected(null, this, msg.replyTo);
|
||||
mAsyncChannel.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
|
||||
AsyncChannel.STATUS_SUCCESSFUL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
|
||||
if (DBG) log("CMD_CHANNEL_DISCONNECT");
|
||||
if (mAsyncChannel != null) mAsyncChannel.disconnect();
|
||||
break;
|
||||
}
|
||||
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
|
||||
if (DBG) log("NetworkAgent channel lost");
|
||||
disconnect();
|
||||
clear();
|
||||
break;
|
||||
}
|
||||
case CMD_SUSPECT_BAD: {
|
||||
log("Unhandled Message " + msg);
|
||||
break;
|
||||
}
|
||||
case CMD_ADD_REQUEST: {
|
||||
handleAddRequest(msg);
|
||||
break;
|
||||
}
|
||||
case CMD_REMOVE_REQUEST: {
|
||||
handleRemoveRequest(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
synchronized(mLockObj) {
|
||||
mNetworkRequests.clear();
|
||||
mHasRequests.set(false);
|
||||
mConnectionRequested = false;
|
||||
mAsyncChannel = null;
|
||||
mRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class NetworkRequestAndScore {
|
||||
NetworkRequest req;
|
||||
int score;
|
||||
|
||||
NetworkRequestAndScore(NetworkRequest networkRequest, int score) {
|
||||
req = networkRequest;
|
||||
this.score = score;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAddRequest(Message msg) {
|
||||
NetworkRequestAndScore n = (NetworkRequestAndScore)msg.obj;
|
||||
// replaces old request, updating score
|
||||
mNetworkRequests.put(n.req.requestId, n);
|
||||
mHasRequests.set(true);
|
||||
evalScores();
|
||||
}
|
||||
|
||||
private void handleRemoveRequest(Message msg) {
|
||||
NetworkRequest networkRequest = (NetworkRequest)msg.obj;
|
||||
|
||||
if (mNetworkRequests.get(networkRequest.requestId) != null) {
|
||||
mNetworkRequests.remove(networkRequest.requestId);
|
||||
if (mNetworkRequests.size() == 0) mHasRequests.set(false);
|
||||
evalScores();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* called to go through our list of requests and see if we're
|
||||
* good enough to try connecting.
|
||||
*
|
||||
* Only does connects - we disconnect when requested via
|
||||
* CMD_CHANNEL_DISCONNECTED, generated by either a loss of connection
|
||||
* between modules (bearer or ConnectivityService dies) or more commonly
|
||||
* when the NetworkInfo reports to ConnectivityService it is disconnected.
|
||||
*/
|
||||
private void evalScores() {
|
||||
if (mConnectionRequested) {
|
||||
// already trying
|
||||
return;
|
||||
}
|
||||
for (int i=0; i < mNetworkRequests.size(); i++) {
|
||||
int score = mNetworkRequests.valueAt(i).score;
|
||||
if (score < mNetworkScore) {
|
||||
// have a request that has a lower scored network servicing it
|
||||
// (or no network) than we could provide, so lets connect!
|
||||
mConnectionRequested = true;
|
||||
connect();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addNetworkRequest(NetworkRequest networkRequest, int score) {
|
||||
if (DBG) log("adding NetworkRequest " + networkRequest + " with score " + score);
|
||||
sendMessage(obtainMessage(CMD_ADD_REQUEST,
|
||||
new NetworkRequestAndScore(networkRequest, score)));
|
||||
}
|
||||
|
||||
public void removeNetworkRequest(NetworkRequest networkRequest) {
|
||||
if (DBG) log("removing NetworkRequest " + networkRequest);
|
||||
sendMessage(obtainMessage(CMD_REMOVE_REQUEST, networkRequest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the bearer code when it has new LinkProperties data.
|
||||
* If we're a registered NetworkAgent, this new data will get forwarded on,
|
||||
* otherwise we store a copy in anticipation of registering. This call
|
||||
* may also prompt registration if it causes the NetworkAgent to meet
|
||||
* the conditions (fully configured, connected, satisfys a request and
|
||||
* has sufficient score).
|
||||
*/
|
||||
public void sendLinkProperties(LinkProperties linkProperties) {
|
||||
linkProperties = new LinkProperties(linkProperties);
|
||||
synchronized(mLockObj) {
|
||||
mLinkProperties = linkProperties;
|
||||
if (mAsyncChannel != null) {
|
||||
mAsyncChannel.sendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, linkProperties);
|
||||
} else {
|
||||
registerSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the bearer code when it has new NetworkInfo data.
|
||||
* If we're a registered NetworkAgent, this new data will get forwarded on,
|
||||
* otherwise we store a copy in anticipation of registering. This call
|
||||
* may also prompt registration if it causes the NetworkAgent to meet
|
||||
* the conditions (fully configured, connected, satisfys a request and
|
||||
* has sufficient score).
|
||||
*/
|
||||
public void sendNetworkInfo(NetworkInfo networkInfo) {
|
||||
networkInfo = new NetworkInfo(networkInfo);
|
||||
synchronized(mLockObj) {
|
||||
mNetworkInfo = networkInfo;
|
||||
if (mAsyncChannel != null) {
|
||||
mAsyncChannel.sendMessage(EVENT_NETWORK_INFO_CHANGED, networkInfo);
|
||||
} else {
|
||||
registerSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the bearer code when it has new NetworkCapabilities data.
|
||||
* If we're a registered NetworkAgent, this new data will get forwarded on,
|
||||
* otherwise we store a copy in anticipation of registering. This call
|
||||
* may also prompt registration if it causes the NetworkAgent to meet
|
||||
* the conditions (fully configured, connected, satisfys a request and
|
||||
* has sufficient score).
|
||||
* Note that if these capabilities make the network non-useful,
|
||||
* ConnectivityServce will tear this network down.
|
||||
*/
|
||||
public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) {
|
||||
networkCapabilities = new NetworkCapabilities(networkCapabilities);
|
||||
synchronized(mLockObj) {
|
||||
mNetworkCapabilities = networkCapabilities;
|
||||
if (mAsyncChannel != null) {
|
||||
mAsyncChannel.sendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED, networkCapabilities);
|
||||
} else {
|
||||
registerSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public NetworkCapabilities getNetworkCapabilities() {
|
||||
synchronized(mLockObj) {
|
||||
return new NetworkCapabilities(mNetworkCapabilities);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the bearer code when it has a new score for this network.
|
||||
* If we're a registered NetworkAgent, this new data will get forwarded on,
|
||||
* otherwise we store a copy.
|
||||
*/
|
||||
public synchronized void sendNetworkScore(int score) {
|
||||
synchronized(mLockObj) {
|
||||
mNetworkScore = score;
|
||||
evalScores();
|
||||
if (mAsyncChannel != null) {
|
||||
mAsyncChannel.sendMessage(EVENT_NETWORK_SCORE_CHANGED, mNetworkScore);
|
||||
} else {
|
||||
registerSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasRequests() {
|
||||
return mHasRequests.get();
|
||||
}
|
||||
|
||||
public boolean isConnectionRequested() {
|
||||
synchronized(mLockObj) {
|
||||
return mConnectionRequested;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
abstract protected void connect();
|
||||
abstract protected void disconnect();
|
||||
|
||||
protected void log(String s) {
|
||||
Log.d(LOG_TAG, "NetworkAgent: " + s);
|
||||
}
|
||||
}
|
||||
@@ -25,23 +25,55 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* @hide
|
||||
*/
|
||||
public class NetworkRequest implements Parcelable {
|
||||
/**
|
||||
* The NetworkCapabilities that define this request
|
||||
*/
|
||||
public final NetworkCapabilities networkCapabilities;
|
||||
|
||||
/**
|
||||
* Identifies the request. NetworkRequests should only be constructed by
|
||||
* the Framework and given out to applications as tokens to be used to identify
|
||||
* the request.
|
||||
* TODO - make sure this input is checked whenever a NR is passed in a public API
|
||||
*/
|
||||
public final int requestId;
|
||||
public final boolean legacy;
|
||||
private static final AtomicInteger sRequestId = new AtomicInteger();
|
||||
|
||||
/**
|
||||
* Set for legacy requests and the default.
|
||||
* Causes CONNECTIVITY_ACTION broadcasts to be sent.
|
||||
* @hide
|
||||
*/
|
||||
public final boolean needsBroadcasts;
|
||||
|
||||
private static final AtomicInteger sNextRequestId = new AtomicInteger(1);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public NetworkRequest(NetworkCapabilities nc) {
|
||||
this(nc, false, sRequestId.incrementAndGet());
|
||||
this(nc, false, sNextRequestId.getAndIncrement());
|
||||
}
|
||||
|
||||
public NetworkRequest(NetworkCapabilities nc, boolean legacy) {
|
||||
this(nc, legacy, sRequestId.incrementAndGet());
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public NetworkRequest(NetworkCapabilities nc, boolean needsBroadcasts) {
|
||||
this(nc, needsBroadcasts, sNextRequestId.getAndIncrement());
|
||||
}
|
||||
|
||||
private NetworkRequest(NetworkCapabilities nc, boolean legacy, int rId) {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
private NetworkRequest(NetworkCapabilities nc, boolean needsBroadcasts, int rId) {
|
||||
requestId = rId;
|
||||
networkCapabilities = nc;
|
||||
this.legacy = legacy;
|
||||
this.needsBroadcasts = needsBroadcasts;
|
||||
}
|
||||
|
||||
public NetworkRequest(NetworkRequest that) {
|
||||
networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
|
||||
requestId = that.requestId;
|
||||
needsBroadcasts = that.needsBroadcasts;
|
||||
}
|
||||
|
||||
// implement the Parcelable interface
|
||||
@@ -50,16 +82,17 @@ public class NetworkRequest implements Parcelable {
|
||||
}
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(networkCapabilities, flags);
|
||||
dest.writeInt(legacy ? 1 : 0);
|
||||
dest.writeInt(needsBroadcasts ? 1 : 0);
|
||||
dest.writeInt(requestId);
|
||||
}
|
||||
public static final Creator<NetworkRequest> CREATOR =
|
||||
new Creator<NetworkRequest>() {
|
||||
public NetworkRequest createFromParcel(Parcel in) {
|
||||
NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null);
|
||||
boolean legacy = (in.readInt() == 1);
|
||||
boolean needsBroadcasts = (in.readInt() == 1);
|
||||
int requestId = in.readInt();
|
||||
return new NetworkRequest(nc, legacy, requestId);
|
||||
NetworkRequest result = new NetworkRequest(nc, needsBroadcasts, requestId);
|
||||
return result;
|
||||
}
|
||||
public NetworkRequest[] newArray(int size) {
|
||||
return new NetworkRequest[size];
|
||||
@@ -67,14 +100,14 @@ public class NetworkRequest implements Parcelable {
|
||||
};
|
||||
|
||||
public String toString() {
|
||||
return "NetworkRequest [ id=" + requestId + ", legacy=" + legacy + ", " +
|
||||
networkCapabilities.toString() + " ]";
|
||||
return "NetworkRequest [ id=" + requestId + ", needsBroadcasts=" + needsBroadcasts +
|
||||
", " + networkCapabilities.toString() + " ]";
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof NetworkRequest == false) return false;
|
||||
NetworkRequest that = (NetworkRequest)obj;
|
||||
return (that.legacy == this.legacy &&
|
||||
return (that.needsBroadcasts == this.needsBroadcasts &&
|
||||
that.requestId == this.requestId &&
|
||||
((that.networkCapabilities == null && this.networkCapabilities == null) ||
|
||||
(that.networkCapabilities != null &&
|
||||
@@ -82,6 +115,7 @@ public class NetworkRequest implements Parcelable {
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return requestId + (legacy ? 1013 : 2026) + (networkCapabilities.hashCode() * 1051);
|
||||
return requestId + (needsBroadcasts ? 1013 : 2026) +
|
||||
(networkCapabilities.hashCode() * 1051);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
|
||||
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
|
||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
|
||||
import static android.net.ConnectivityManager.NetworkCallbacks;
|
||||
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
|
||||
import static android.net.ConnectivityManager.TYPE_DUMMY;
|
||||
import static android.net.ConnectivityManager.TYPE_ETHERNET;
|
||||
@@ -30,6 +31,7 @@ import static android.net.ConnectivityManager.TYPE_PROXY;
|
||||
import static android.net.ConnectivityManager.getNetworkTypeName;
|
||||
import static android.net.ConnectivityManager.isNetworkTypeValid;
|
||||
import static android.net.ConnectivityServiceProtocol.NetworkFactoryProtocol;
|
||||
import static android.net.ConnectivityServiceProtocol.NetworkMonitorProtocol;
|
||||
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
|
||||
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
|
||||
|
||||
@@ -67,6 +69,7 @@ import android.net.LinkProperties.CompareResult;
|
||||
import android.net.LinkQualityInfo;
|
||||
import android.net.MobileDataStateTracker;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkAgent;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkConfig;
|
||||
import android.net.NetworkInfo;
|
||||
@@ -82,7 +85,6 @@ import android.net.ProxyInfo;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.SamplingDataTracker;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiStateTracker;
|
||||
import android.net.wimax.WimaxManagerConstants;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Binder;
|
||||
@@ -128,6 +130,7 @@ import com.android.internal.util.XmlUtils;
|
||||
import com.android.server.am.BatteryStatsService;
|
||||
import com.android.server.connectivity.DataConnectionStats;
|
||||
import com.android.server.connectivity.Nat464Xlat;
|
||||
import com.android.server.connectivity.NetworkAgentInfo;
|
||||
import com.android.server.connectivity.PacManager;
|
||||
import com.android.server.connectivity.Tethering;
|
||||
import com.android.server.connectivity.Vpn;
|
||||
@@ -179,7 +182,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
private static final String TAG = "ConnectivityService";
|
||||
|
||||
private static final boolean DBG = true;
|
||||
private static final boolean VDBG = false;
|
||||
private static final boolean VDBG = true; // STOPSHIP
|
||||
|
||||
private static final boolean LOGD_RULES = false;
|
||||
|
||||
@@ -305,12 +308,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
*/
|
||||
private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 2;
|
||||
|
||||
/**
|
||||
* used internally to change our network preference setting
|
||||
* arg1 = networkType to prefer
|
||||
*/
|
||||
private static final int EVENT_SET_NETWORK_PREFERENCE = 3;
|
||||
|
||||
/**
|
||||
* used internally to synchronize inet condition reports
|
||||
* arg1 = networkType
|
||||
@@ -382,10 +379,16 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
*/
|
||||
private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
|
||||
|
||||
/**
|
||||
* used internally when registering NetworkAgents
|
||||
* obj = Messenger
|
||||
*/
|
||||
private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
|
||||
|
||||
/** Handler used for internal events. */
|
||||
private InternalHandler mHandler;
|
||||
final private InternalHandler mHandler;
|
||||
/** Handler used for incoming {@link NetworkStateTracker} events. */
|
||||
private NetworkStateTrackerHandler mTrackerHandler;
|
||||
final private NetworkStateTrackerHandler mTrackerHandler;
|
||||
|
||||
// list of DeathRecipients used to make sure features are turned off when
|
||||
// a process dies
|
||||
@@ -474,8 +477,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
NetworkCapabilities netCap = new NetworkCapabilities();
|
||||
netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
||||
netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
|
||||
NetworkRequest netRequest = new NetworkRequest(netCap);
|
||||
mNetworkRequests.append(netRequest.requestId, netRequest);
|
||||
mDefaultRequest = new NetworkRequest(netCap, true);
|
||||
mNetworkRequests.append(mDefaultRequest.requestId, mDefaultRequest);
|
||||
|
||||
HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
|
||||
handlerThread.start();
|
||||
@@ -624,21 +627,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
// Update mNetworkPreference according to user mannually first then overlay config.xml
|
||||
mNetworkPreference = getPersistedNetworkPreference();
|
||||
if (mNetworkPreference == -1) {
|
||||
for (int n : mPriorityList) {
|
||||
if (mNetConfigs[n].isDefault() && ConnectivityManager.isNetworkTypeValid(n)) {
|
||||
mNetworkPreference = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mNetworkPreference == -1) {
|
||||
throw new IllegalStateException(
|
||||
"You should set at least one default Network in config.xml!");
|
||||
}
|
||||
}
|
||||
|
||||
mNetRequestersPids =
|
||||
(List<Integer> [])new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
|
||||
for (int i : mPriorityList) {
|
||||
@@ -738,6 +726,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
/**
|
||||
* Factory that creates {@link NetworkStateTracker} instances using given
|
||||
* {@link NetworkConfig}.
|
||||
*
|
||||
* TODO - this is obsolete and will be deleted. It's replaced by the
|
||||
* registerNetworkFactory call and protocol.
|
||||
* @Deprecated in favor of registerNetworkFactory dynamic bindings
|
||||
*/
|
||||
public interface NetworkFactory {
|
||||
public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config);
|
||||
@@ -755,10 +747,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
@Override
|
||||
public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {
|
||||
switch (config.radio) {
|
||||
case TYPE_WIFI:
|
||||
return new WifiStateTracker(targetNetworkType, config.name);
|
||||
case TYPE_MOBILE:
|
||||
return new MobileDataStateTracker(targetNetworkType, config.name);
|
||||
case TYPE_DUMMY:
|
||||
return new DummyDataStateTracker(targetNetworkType, config.name);
|
||||
case TYPE_BLUETOOTH:
|
||||
@@ -859,41 +847,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
return wimaxStateTracker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the preferred network.
|
||||
* @param preference the new preference
|
||||
*/
|
||||
public void setNetworkPreference(int preference) {
|
||||
enforceChangePermission();
|
||||
|
||||
mHandler.sendMessage(
|
||||
mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
|
||||
}
|
||||
|
||||
public int getNetworkPreference() {
|
||||
enforceAccessPermission();
|
||||
int preference;
|
||||
synchronized(this) {
|
||||
preference = mNetworkPreference;
|
||||
}
|
||||
return preference;
|
||||
}
|
||||
|
||||
private void handleSetNetworkPreference(int preference) {
|
||||
if (ConnectivityManager.isNetworkTypeValid(preference) &&
|
||||
mNetConfigs[preference] != null &&
|
||||
mNetConfigs[preference].isDefault()) {
|
||||
if (mNetworkPreference != preference) {
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_PREFERENCE, preference);
|
||||
synchronized(this) {
|
||||
mNetworkPreference = preference;
|
||||
}
|
||||
enforcePreference();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getConnectivityChangeDelay() {
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
|
||||
@@ -905,41 +858,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
defaultDelay);
|
||||
}
|
||||
|
||||
private int getPersistedNetworkPreference() {
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
|
||||
final int networkPrefSetting = Settings.Global
|
||||
.getInt(cr, Settings.Global.NETWORK_PREFERENCE, -1);
|
||||
|
||||
return networkPrefSetting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the state of network connectivity conform to the preference settings
|
||||
* In this method, we only tear down a non-preferred network. Establishing
|
||||
* a connection to the preferred network is taken care of when we handle
|
||||
* the disconnect event from the non-preferred network
|
||||
* (see {@link #handleDisconnect(NetworkInfo)}).
|
||||
*/
|
||||
private void enforcePreference() {
|
||||
if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
|
||||
return;
|
||||
|
||||
if (!mNetTrackers[mNetworkPreference].isAvailable())
|
||||
return;
|
||||
|
||||
for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
|
||||
if (t != mNetworkPreference && mNetTrackers[t] != null &&
|
||||
mNetTrackers[t].getNetworkInfo().isConnected()) {
|
||||
if (DBG) {
|
||||
log("tearing down " + mNetTrackers[t].getNetworkInfo() +
|
||||
" in enforcePreference");
|
||||
}
|
||||
teardown(mNetTrackers[t]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean teardown(NetworkStateTracker netTracker) {
|
||||
if (netTracker.teardown()) {
|
||||
netTracker.setTeardownRequested(true);
|
||||
@@ -1192,24 +1110,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setRadios(boolean turnOn) {
|
||||
boolean result = true;
|
||||
enforceChangePermission();
|
||||
for (NetworkStateTracker t : mNetTrackers) {
|
||||
if (t != null) result = t.setRadio(turnOn) && result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean setRadio(int netType, boolean turnOn) {
|
||||
enforceChangePermission();
|
||||
if (!ConnectivityManager.isNetworkTypeValid(netType)) {
|
||||
return false;
|
||||
}
|
||||
NetworkStateTracker tracker = mNetTrackers[netType];
|
||||
return tracker != null && tracker.setRadio(turnOn);
|
||||
}
|
||||
|
||||
private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
|
||||
@Override
|
||||
public void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos) {
|
||||
@@ -1929,18 +1829,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
|
||||
private void handleSetMobileData(boolean enabled) {
|
||||
if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
|
||||
if (VDBG) {
|
||||
log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
|
||||
}
|
||||
mNetTrackers[ConnectivityManager.TYPE_MOBILE].setUserDataEnable(enabled);
|
||||
}
|
||||
if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) {
|
||||
if (VDBG) {
|
||||
log(mNetTrackers[ConnectivityManager.TYPE_WIMAX].toString() + enabled);
|
||||
}
|
||||
mNetTrackers[ConnectivityManager.TYPE_WIMAX].setUserDataEnable(enabled);
|
||||
}
|
||||
// TODO - handle this - probably generalize passing in a transport type and send to the
|
||||
// factories?
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1953,12 +1843,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
|
||||
private void handleSetPolicyDataEnable(int networkType, boolean enabled) {
|
||||
if (isNetworkTypeValid(networkType)) {
|
||||
final NetworkStateTracker tracker = mNetTrackers[networkType];
|
||||
if (tracker != null) {
|
||||
tracker.setPolicyDataEnable(enabled);
|
||||
}
|
||||
}
|
||||
// TODO - handle this passing to factories
|
||||
// if (isNetworkTypeValid(networkType)) {
|
||||
// final NetworkStateTracker tracker = mNetTrackers[networkType];
|
||||
// if (tracker != null) {
|
||||
// tracker.setPolicyDataEnable(enabled);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private void enforceAccessPermission() {
|
||||
@@ -2226,67 +2117,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an attempt to fail over to another network has failed.
|
||||
* @param info the {@link NetworkInfo} for the failed network
|
||||
*/
|
||||
private void handleConnectionFailure(NetworkInfo info) {
|
||||
mNetTrackers[info.getType()].setTeardownRequested(false);
|
||||
|
||||
String reason = info.getReason();
|
||||
String extraInfo = info.getExtraInfo();
|
||||
|
||||
String reasonText;
|
||||
if (reason == null) {
|
||||
reasonText = ".";
|
||||
} else {
|
||||
reasonText = " (" + reason + ").";
|
||||
}
|
||||
loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
|
||||
|
||||
Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
|
||||
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
|
||||
if (getActiveNetworkInfo() == null) {
|
||||
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
|
||||
}
|
||||
if (reason != null) {
|
||||
intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
|
||||
}
|
||||
if (extraInfo != null) {
|
||||
intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
|
||||
}
|
||||
if (info.isFailover()) {
|
||||
intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
|
||||
info.setFailover(false);
|
||||
}
|
||||
|
||||
if (mNetConfigs[info.getType()].isDefault()) {
|
||||
tryFailover(info.getType());
|
||||
if (mActiveDefaultNetwork != -1) {
|
||||
NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
|
||||
intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
|
||||
} else {
|
||||
mDefaultInetConditionPublished = 0;
|
||||
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
|
||||
}
|
||||
}
|
||||
|
||||
intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
|
||||
|
||||
final Intent immediateIntent = new Intent(intent);
|
||||
immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
|
||||
sendStickyBroadcast(immediateIntent);
|
||||
sendStickyBroadcast(intent);
|
||||
/*
|
||||
* If the failover network is already connected, then immediately send
|
||||
* out a followup broadcast indicating successful failover
|
||||
*/
|
||||
if (mActiveDefaultNetwork != -1) {
|
||||
sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
|
||||
}
|
||||
}
|
||||
|
||||
private void sendStickyBroadcast(Intent intent) {
|
||||
synchronized(this) {
|
||||
if (!mSystemReady) {
|
||||
@@ -2478,33 +2308,35 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup data activity tracking for the given network interface.
|
||||
* Setup data activity tracking for the given network.
|
||||
*
|
||||
* Every {@code setupDataActivityTracking} should be paired with a
|
||||
* {@link #removeDataActivityTracking} for cleanup.
|
||||
*/
|
||||
private void setupDataActivityTracking(int type) {
|
||||
final NetworkStateTracker thisNet = mNetTrackers[type];
|
||||
final String iface = thisNet.getLinkProperties().getInterfaceName();
|
||||
private void setupDataActivityTracking(NetworkAgentInfo networkAgent) {
|
||||
final String iface = networkAgent.linkProperties.getInterfaceName();
|
||||
|
||||
final int timeout;
|
||||
int type = ConnectivityManager.TYPE_NONE;
|
||||
|
||||
if (ConnectivityManager.isNetworkTypeMobile(type)) {
|
||||
if (networkAgent.networkCapabilities.hasTransport(
|
||||
NetworkCapabilities.TRANSPORT_CELLULAR)) {
|
||||
timeout = Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
|
||||
5);
|
||||
// Canonicalize mobile network type
|
||||
type = ConnectivityManager.TYPE_MOBILE;
|
||||
} else if (ConnectivityManager.TYPE_WIFI == type) {
|
||||
} else if (networkAgent.networkCapabilities.hasTransport(
|
||||
NetworkCapabilities.TRANSPORT_WIFI)) {
|
||||
timeout = Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
|
||||
0);
|
||||
type = ConnectivityManager.TYPE_WIFI;
|
||||
} else {
|
||||
// do not track any other networks
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
if (timeout > 0 && iface != null) {
|
||||
if (timeout > 0 && iface != null && type != ConnectivityManager.TYPE_NONE) {
|
||||
try {
|
||||
mNetd.addIdleTimer(iface, timeout, type);
|
||||
} catch (Exception e) {
|
||||
@@ -2517,12 +2349,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
/**
|
||||
* Remove data activity tracking when network disconnects.
|
||||
*/
|
||||
private void removeDataActivityTracking(int type) {
|
||||
final NetworkStateTracker net = mNetTrackers[type];
|
||||
final String iface = net.getLinkProperties().getInterfaceName();
|
||||
private void removeDataActivityTracking(NetworkAgentInfo networkAgent) {
|
||||
final String iface = networkAgent.linkProperties.getInterfaceName();
|
||||
final NetworkCapabilities caps = networkAgent.networkCapabilities;
|
||||
|
||||
if (iface != null && (ConnectivityManager.isNetworkTypeMobile(type) ||
|
||||
ConnectivityManager.TYPE_WIFI == type)) {
|
||||
if (iface != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
|
||||
caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) {
|
||||
try {
|
||||
// the call fails silently if no idletimer setup for this interface
|
||||
mNetd.removeIdleTimer(iface);
|
||||
@@ -2537,8 +2369,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
* concerned with making sure that the list of DNS servers is set up
|
||||
* according to which networks are connected, and ensuring that the
|
||||
* right routing table entries exist.
|
||||
*
|
||||
* TODO - delete when we're sure all this functionallity is captured.
|
||||
*/
|
||||
private void handleConnectivityChange(int netType, boolean doReset) {
|
||||
private void handleConnectivityChange(int netType, LinkProperties curLp, boolean doReset) {
|
||||
int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
|
||||
boolean exempt = ConnectivityManager.isNetworkTypeExempt(netType);
|
||||
if (VDBG) {
|
||||
@@ -2552,7 +2386,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
*/
|
||||
handleDnsConfigurationChange(netType);
|
||||
|
||||
LinkProperties curLp = mCurrentLinkProperties[netType];
|
||||
LinkProperties newLp = null;
|
||||
|
||||
if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
|
||||
@@ -2742,26 +2575,30 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
return routesChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Reads the network specific MTU size from reources.
|
||||
* and set it on it's iface.
|
||||
*/
|
||||
private void updateMtuSizeSettings(NetworkStateTracker nt) {
|
||||
final String iface = nt.getLinkProperties().getInterfaceName();
|
||||
final int mtu = nt.getLinkProperties().getMtu();
|
||||
private void updateMtu(LinkProperties newLp, LinkProperties oldLp) {
|
||||
final String iface = newLp.getInterfaceName();
|
||||
final int mtu = newLp.getMtu();
|
||||
if (oldLp != null && newLp.isIdenticalMtu(oldLp)) {
|
||||
if (VDBG) log("identical MTU - not setting");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mtu < 68 || mtu > 10000) {
|
||||
loge("Unexpected mtu value: " + mtu + ", " + nt);
|
||||
return;
|
||||
}
|
||||
if (mtu < 68 || mtu > 10000) {
|
||||
loge("Unexpected mtu value: " + mtu + ", " + iface);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
|
||||
mNetd.setMtu(iface, mtu);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "exception in setMtu()" + e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
|
||||
mNetd.setMtu(iface, mtu);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "exception in setMtu()" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the network specific TCP buffer sizes from SystemProperties
|
||||
@@ -3053,21 +2890,58 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
NetworkInfo info;
|
||||
switch (msg.what) {
|
||||
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
|
||||
AsyncChannel ac = (AsyncChannel) msg.obj;
|
||||
if (mNetworkFactories.contains(ac)) {
|
||||
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
|
||||
if (VDBG) log("NetworkFactory connected");
|
||||
for (int i = 0; i < mNetworkRequests.size(); i++) {
|
||||
ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK,
|
||||
mNetworkRequests.valueAt(i));
|
||||
}
|
||||
} else {
|
||||
loge("Error connecting NetworkFactory");
|
||||
mNetworkFactories.remove((AsyncChannel) msg.obj);
|
||||
}
|
||||
handleAsyncChannelHalfConnect(msg);
|
||||
break;
|
||||
}
|
||||
case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
|
||||
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
|
||||
if (nai != null) nai.asyncChannel.disconnect();
|
||||
break;
|
||||
}
|
||||
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
|
||||
handleAsyncChannelDisconnected(msg);
|
||||
break;
|
||||
}
|
||||
case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
|
||||
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
|
||||
if (nai == null) {
|
||||
loge("EVENT_NETWORK_CAPABILITIES_CHANGED from unknown NetworkAgent");
|
||||
} else {
|
||||
updateCapabilities(nai, (NetworkCapabilities)msg.obj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
|
||||
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
|
||||
if (nai == null) {
|
||||
loge("NetworkAgent not found for EVENT_NETWORK_PROPERTIES_CHANGED");
|
||||
} else {
|
||||
LinkProperties oldLp = nai.linkProperties;
|
||||
nai.linkProperties = (LinkProperties)msg.obj;
|
||||
updateLinkProperties(nai, oldLp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
|
||||
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
|
||||
if (nai == null) {
|
||||
loge("EVENT_NETWORK_INFO_CHANGED from unknown NetworkAgent");
|
||||
break;
|
||||
}
|
||||
info = (NetworkInfo) msg.obj;
|
||||
updateNetworkInfo(nai, info);
|
||||
break;
|
||||
}
|
||||
case NetworkMonitorProtocol.EVENT_NETWORK_VALIDATED: {
|
||||
NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
|
||||
handleConnectionValidated(nai);
|
||||
break;
|
||||
}
|
||||
case NetworkMonitorProtocol.EVENT_NETWORK_LINGER_COMPLETE: {
|
||||
NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
|
||||
handleLingerComplete(nai);
|
||||
break;
|
||||
}
|
||||
case NetworkStateTracker.EVENT_STATE_CHANGED: {
|
||||
info = (NetworkInfo) msg.obj;
|
||||
NetworkInfo.State state = info.getState();
|
||||
@@ -3100,10 +2974,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
EventLogTags.writeConnectivityStateChanged(
|
||||
info.getType(), info.getSubtype(), info.getDetailedState().ordinal());
|
||||
|
||||
if (info.getDetailedState() ==
|
||||
NetworkInfo.DetailedState.FAILED) {
|
||||
handleConnectionFailure(info);
|
||||
} else if (info.isConnectedToProvisioningNetwork()) {
|
||||
if (info.isConnectedToProvisioningNetwork()) {
|
||||
/**
|
||||
* TODO: Create ConnectivityManager.TYPE_MOBILE_PROVISIONING
|
||||
* for now its an in between network, its a network that
|
||||
@@ -3128,18 +2999,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
mNetTrackers[info.getType()].getNetwork().netId);
|
||||
}
|
||||
} else if (state == NetworkInfo.State.DISCONNECTED) {
|
||||
handleDisconnect(info);
|
||||
} else if (state == NetworkInfo.State.SUSPENDED) {
|
||||
// TODO: need to think this over.
|
||||
// the logic here is, handle SUSPENDED the same as
|
||||
// DISCONNECTED. The only difference being we are
|
||||
// broadcasting an intent with NetworkInfo that's
|
||||
// suspended. This allows the applications an
|
||||
// opportunity to handle DISCONNECTED and SUSPENDED
|
||||
// differently, or not.
|
||||
handleDisconnect(info);
|
||||
} else if (state == NetworkInfo.State.CONNECTED) {
|
||||
handleConnect(info);
|
||||
// handleConnect(info);
|
||||
}
|
||||
if (mLockdownTracker != null) {
|
||||
mLockdownTracker.onNetworkInfoChanged(info);
|
||||
@@ -3151,7 +3013,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
// TODO: Temporary allowing network configuration
|
||||
// change not resetting sockets.
|
||||
// @see bug/4455071
|
||||
handleConnectivityChange(info.getType(), false);
|
||||
handleConnectivityChange(info.getType(), mCurrentLinkProperties[info.getType()],
|
||||
false);
|
||||
break;
|
||||
}
|
||||
case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED: {
|
||||
@@ -3164,6 +3027,66 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAsyncChannelHalfConnect(Message msg) {
|
||||
AsyncChannel ac = (AsyncChannel) msg.obj;
|
||||
if (mNetworkFactories.contains(ac)) {
|
||||
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
|
||||
if (VDBG) log("NetworkFactory connected");
|
||||
// A network factory has connected. Send it all current NetworkRequests.
|
||||
for (int i = 0; i < mNetworkRequests.size(); i++) {
|
||||
NetworkRequest request = mNetworkRequests.valueAt(i);
|
||||
NetworkAgentInfo nai = mNetworkForRequestId.get(request.requestId);
|
||||
ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK,
|
||||
(nai != null ? nai.currentScore : 0), 0, request);
|
||||
}
|
||||
} else {
|
||||
loge("Error connecting NetworkFactory");
|
||||
mNetworkFactories.remove(ac);
|
||||
}
|
||||
} else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
|
||||
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
|
||||
if (VDBG) log("NetworkAgent connected");
|
||||
// A network agent has requested a connection. Establish the connection.
|
||||
mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
|
||||
sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
|
||||
} else {
|
||||
loge("Error connecting NetworkAgent");
|
||||
mNetworkAgentInfos.remove(msg.replyTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void handleAsyncChannelDisconnected(Message msg) {
|
||||
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
|
||||
if (nai != null) {
|
||||
if (DBG) log(nai.name() + " got DISCONNECTED");
|
||||
// A network agent has disconnected.
|
||||
// Tell netd to clean up the configuration for this network
|
||||
// (routing rules, DNS, etc).
|
||||
try {
|
||||
mNetd.removeNetwork(nai.network.netId);
|
||||
} catch (Exception e) {
|
||||
loge("Exception removing network: " + e);
|
||||
}
|
||||
notifyNetworkCallbacks(nai, NetworkCallbacks.LOST);
|
||||
mNetworkAgentInfos.remove(nai);
|
||||
// Since we've lost the network, go through all the requests that
|
||||
// it was satisfying and see if any other factory can satisfy them.
|
||||
for (int i = 0; i < nai.networkRequests.size(); i++) {
|
||||
NetworkRequest request = nai.networkRequests.valueAt(i);
|
||||
NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
|
||||
if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
|
||||
mNetworkForRequestId.remove(request.requestId);
|
||||
// TODO Check if any other live network will work
|
||||
sendUpdatedScoreToFactories(request, 0);
|
||||
}
|
||||
}
|
||||
if (nai.networkRequests.get(mDefaultRequest.requestId) != null) {
|
||||
removeDataActivityTracking(nai);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class InternalHandler extends Handler {
|
||||
public InternalHandler(Looper looper) {
|
||||
super(looper);
|
||||
@@ -3204,11 +3127,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
handleInetConditionHoldEnd(netType, sequence);
|
||||
break;
|
||||
}
|
||||
case EVENT_SET_NETWORK_PREFERENCE: {
|
||||
int preference = msg.arg1;
|
||||
handleSetNetworkPreference(preference);
|
||||
break;
|
||||
}
|
||||
case EVENT_SET_MOBILE_DATA: {
|
||||
boolean enabled = (msg.arg1 == ENABLED);
|
||||
handleSetMobileData(enabled);
|
||||
@@ -3266,6 +3184,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
handleRegisterNetworkFactory((Messenger)msg.obj);
|
||||
break;
|
||||
}
|
||||
case EVENT_REGISTER_NETWORK_AGENT: {
|
||||
handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5112,7 +5034,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
|
||||
public void registerNetworkFactory(Messenger messenger) {
|
||||
enforceConnectivityInternalPermission();
|
||||
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, messenger));
|
||||
}
|
||||
|
||||
@@ -5123,5 +5044,335 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
ac.connect(mContext, mTrackerHandler, messenger);
|
||||
}
|
||||
|
||||
// NetworkRequest by requestId
|
||||
private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<NetworkRequest>();
|
||||
|
||||
/**
|
||||
* NetworkAgentInfo supporting a request by requestId.
|
||||
* These have already been vetted (their Capabilities satisfy the request)
|
||||
* and the are the highest scored network available.
|
||||
* the are keyed off the Requests requestId.
|
||||
*/
|
||||
private final SparseArray<NetworkAgentInfo> mNetworkForRequestId =
|
||||
new SparseArray<NetworkAgentInfo>();
|
||||
|
||||
// NetworkAgentInfo keyed off its connecting messenger
|
||||
// TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
|
||||
private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos =
|
||||
new HashMap<Messenger, NetworkAgentInfo>();
|
||||
|
||||
private final NetworkRequest mDefaultRequest;
|
||||
|
||||
public void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
|
||||
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
|
||||
int currentScore) {
|
||||
enforceConnectivityInternalPermission();
|
||||
|
||||
NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), nextNetId(),
|
||||
new NetworkInfo(networkInfo), new LinkProperties(linkProperties),
|
||||
new NetworkCapabilities(networkCapabilities), currentScore);
|
||||
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
|
||||
}
|
||||
|
||||
private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
|
||||
if (VDBG) log("Got NetworkAgent Messenger");
|
||||
mNetworkAgentInfos.put(na.messenger, na);
|
||||
na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
|
||||
NetworkInfo networkInfo = na.networkInfo;
|
||||
na.networkInfo = null;
|
||||
updateNetworkInfo(na, networkInfo);
|
||||
}
|
||||
|
||||
private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties oldLp) {
|
||||
LinkProperties newLp = networkAgent.linkProperties;
|
||||
int netId = networkAgent.network.netId;
|
||||
|
||||
updateMtu(newLp, oldLp);
|
||||
// TODO - figure out what to do for clat
|
||||
// for (LinkProperties lp : newLp.getStackedLinks()) {
|
||||
// updateMtu(lp, null);
|
||||
// }
|
||||
updateRoutes(newLp, oldLp, netId);
|
||||
updateDnses(newLp, oldLp, netId);
|
||||
}
|
||||
private void updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) {
|
||||
CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
|
||||
if (oldLp != null) {
|
||||
routeDiff = oldLp.compareAllRoutes(newLp);
|
||||
} else if (newLp != null) {
|
||||
routeDiff.added = newLp.getAllRoutes();
|
||||
}
|
||||
|
||||
// add routes before removing old in case it helps with continuous connectivity
|
||||
|
||||
// do this twice, adding non-nexthop routes first, then routes they are dependent on
|
||||
for (RouteInfo route : routeDiff.added) {
|
||||
if (route.hasGateway()) continue;
|
||||
try {
|
||||
mNetd.addRoute(netId, route);
|
||||
} catch (Exception e) {
|
||||
loge("Exception in addRoute for non-gateway: " + e);
|
||||
}
|
||||
}
|
||||
for (RouteInfo route : routeDiff.added) {
|
||||
if (route.hasGateway() == false) continue;
|
||||
try {
|
||||
mNetd.addRoute(netId, route);
|
||||
} catch (Exception e) {
|
||||
loge("Exception in addRoute for gateway: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
for (RouteInfo route : routeDiff.removed) {
|
||||
try {
|
||||
mNetd.removeRoute(netId, route);
|
||||
} catch (Exception e) {
|
||||
loge("Exception in removeRoute: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
|
||||
if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) {
|
||||
Collection<InetAddress> dnses = newLp.getDnses();
|
||||
if (dnses.size() == 0 && mDefaultDns != null) {
|
||||
dnses = new ArrayList();
|
||||
dnses.add(mDefaultDns);
|
||||
if (DBG) {
|
||||
loge("no dns provided for netId " + netId + ", so using defaults");
|
||||
}
|
||||
}
|
||||
try {
|
||||
mNetd.setDnsServersForNetwork(netId, NetworkUtils.makeStrings(dnses),
|
||||
newLp.getDomains());
|
||||
} catch (Exception e) {
|
||||
loge("Exception in setDnsServersForNetwork: " + e);
|
||||
}
|
||||
// TODO - setprop "net.dnsX"
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCapabilities(NetworkAgentInfo networkAgent,
|
||||
NetworkCapabilities networkCapabilities) {
|
||||
// TODO - what else here? Verify still satisfies everybody?
|
||||
// Check if satisfies somebody new? call callbacks?
|
||||
networkAgent.networkCapabilities = networkCapabilities;
|
||||
}
|
||||
|
||||
private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
|
||||
if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
|
||||
for (AsyncChannel ac : mNetworkFactories) {
|
||||
ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private void callCallbackForRequest(NetworkRequest networkRequest,
|
||||
NetworkAgentInfo networkAgent, int notificationType) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
|
||||
if (oldNetwork == null) {
|
||||
loge("Unknown NetworkAgentInfo in handleLingerComplete");
|
||||
return;
|
||||
}
|
||||
if (DBG) log("handleLingerComplete for " + oldNetwork.name());
|
||||
if (DBG) {
|
||||
if (oldNetwork.networkRequests.size() != 0) {
|
||||
loge("Dead network still had " + oldNetwork.networkRequests.size() + " requests");
|
||||
}
|
||||
}
|
||||
oldNetwork.asyncChannel.disconnect();
|
||||
}
|
||||
|
||||
private void handleConnectionValidated(NetworkAgentInfo newNetwork) {
|
||||
if (newNetwork == null) {
|
||||
loge("Unknown NetworkAgentInfo in handleConnectionValidated");
|
||||
return;
|
||||
}
|
||||
boolean keep = false;
|
||||
boolean isNewDefault = false;
|
||||
if (DBG) log("handleConnectionValidated for "+newNetwork.name());
|
||||
// check if any NetworkRequest wants this NetworkAgent
|
||||
// first check if it satisfies the NetworkCapabilities
|
||||
for (int i = 0; i < mNetworkRequests.size(); i++) {
|
||||
NetworkRequest nr = mNetworkRequests.valueAt(i);
|
||||
if (nr.networkCapabilities.satisfiedByNetworkCapabilities(
|
||||
newNetwork.networkCapabilities)) {
|
||||
// next check if it's better than any current network we're using for
|
||||
// this request
|
||||
NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nr.requestId);
|
||||
if (VDBG) {
|
||||
log("currentScore = " +
|
||||
(currentNetwork != null ? currentNetwork.currentScore : 0) +
|
||||
", newScore = " + newNetwork.currentScore);
|
||||
}
|
||||
if (currentNetwork == null ||
|
||||
currentNetwork.currentScore < newNetwork.currentScore) {
|
||||
if (currentNetwork != null) {
|
||||
currentNetwork.networkRequests.remove(nr.requestId);
|
||||
currentNetwork.networkListens.add(nr);
|
||||
if (currentNetwork.networkRequests.size() == 0) {
|
||||
// TODO tell current Network to go to linger state
|
||||
|
||||
// fake the linger state:
|
||||
Message message = Message.obtain();
|
||||
message.obj = currentNetwork;
|
||||
message.what = NetworkMonitorProtocol.EVENT_NETWORK_LINGER_COMPLETE;
|
||||
mTrackerHandler.sendMessage(message);
|
||||
|
||||
notifyNetworkCallbacks(currentNetwork, NetworkCallbacks.LOSING);
|
||||
}
|
||||
}
|
||||
mNetworkForRequestId.put(nr.requestId, newNetwork);
|
||||
newNetwork.networkRequests.put(nr.requestId, nr);
|
||||
keep = true;
|
||||
// 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(nr, newNetwork.currentScore);
|
||||
if (mDefaultRequest.requestId == nr.requestId) {
|
||||
isNewDefault = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (keep) {
|
||||
if (isNewDefault) {
|
||||
if (VDBG) log("Switching to new default network: " + newNetwork);
|
||||
setupDataActivityTracking(newNetwork);
|
||||
try {
|
||||
mNetd.setDefaultNetId(newNetwork.network.netId);
|
||||
} catch (Exception e) {
|
||||
loge("Exception setting default network :" + e);
|
||||
}
|
||||
if (newNetwork.equals(mNetworkForRequestId.get(mDefaultRequest.requestId))) {
|
||||
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
|
||||
}
|
||||
synchronized (ConnectivityService.this) {
|
||||
// have a new default network, release the transition wakelock in
|
||||
// a second if it's held. The second pause is to allow apps
|
||||
// to reconnect over the new network
|
||||
if (mNetTransitionWakeLock.isHeld()) {
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(
|
||||
EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
|
||||
mNetTransitionWakeLockSerialNumber, 0),
|
||||
1000);
|
||||
}
|
||||
}
|
||||
|
||||
// this will cause us to come up initially as unconnected and switching
|
||||
// to connected after our normal pause unless somebody reports us as
|
||||
// really disconnected
|
||||
mDefaultInetConditionPublished = 0;
|
||||
mDefaultConnectionSequence++;
|
||||
mInetConditionChangeInFlight = false;
|
||||
// TODO - read the tcp buffer size config string from somewhere
|
||||
// updateNetworkSettings();
|
||||
}
|
||||
// notify battery stats service about this network
|
||||
// try {
|
||||
// TODO
|
||||
//BatteryStatsService.getService().noteNetworkInterfaceType(iface, netType);
|
||||
// } catch (RemoteException e) { }
|
||||
notifyNetworkCallbacks(newNetwork, NetworkCallbacks.AVAILABLE);
|
||||
} else {
|
||||
if (VDBG) log("Validated network turns out to be unwanted. Tear it down.");
|
||||
newNetwork.asyncChannel.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
|
||||
NetworkInfo.State state = newInfo.getState();
|
||||
NetworkInfo oldInfo = networkAgent.networkInfo;
|
||||
networkAgent.networkInfo = newInfo;
|
||||
|
||||
if (oldInfo != null && oldInfo.getState() == state) {
|
||||
if (VDBG) log("ignoring duplicate network state non-change");
|
||||
return;
|
||||
}
|
||||
if (DBG) {
|
||||
log(networkAgent.name() + " EVENT_NETWORK_INFO_CHANGED, going from " +
|
||||
(oldInfo == null ? "null" : oldInfo.getState()) +
|
||||
" to " + state);
|
||||
}
|
||||
if (state == NetworkInfo.State.CONNECTED) {
|
||||
// TODO - check if we want it (optimization)
|
||||
try {
|
||||
mNetd.createNetwork(networkAgent.network.netId,
|
||||
networkAgent.linkProperties.getInterfaceName());
|
||||
} catch (Exception e) {
|
||||
loge("Error creating Network " + networkAgent.network.netId);
|
||||
}
|
||||
updateLinkProperties(networkAgent, null);
|
||||
notifyNetworkCallbacks(networkAgent, NetworkCallbacks.PRECHECK);
|
||||
// TODO - kick the network monitor
|
||||
|
||||
// Fake things by sending self a NETWORK_VALIDATED msg
|
||||
Message message = Message.obtain();
|
||||
message.obj = networkAgent;
|
||||
message.what = NetworkMonitorProtocol.EVENT_NETWORK_VALIDATED;
|
||||
mTrackerHandler.sendMessage(message);
|
||||
} else if (state == NetworkInfo.State.DISCONNECTED ||
|
||||
state == NetworkInfo.State.SUSPENDED) {
|
||||
networkAgent.asyncChannel.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
|
||||
if (VDBG) log("notifyType " + notifyType + " for " + networkAgent.name());
|
||||
boolean needsBroadcasts = false;
|
||||
for (int i = 0; i < networkAgent.networkRequests.size(); i++) {
|
||||
NetworkRequest request = networkAgent.networkRequests.valueAt(i);
|
||||
if (request == null) continue;
|
||||
if (request.needsBroadcasts) needsBroadcasts = true;
|
||||
callCallbackForRequest(request, networkAgent, notifyType);
|
||||
}
|
||||
for (NetworkRequest request : networkAgent.networkListens) {
|
||||
if (request.needsBroadcasts) needsBroadcasts = true;
|
||||
callCallbackForRequest(request, networkAgent, notifyType);
|
||||
}
|
||||
if (needsBroadcasts) {
|
||||
if (notifyType == NetworkCallbacks.AVAILABLE) {
|
||||
sendConnectedBroadcastDelayed(networkAgent.networkInfo,
|
||||
getConnectivityChangeDelay());
|
||||
} else if (notifyType == NetworkCallbacks.LOST) {
|
||||
NetworkInfo info = new NetworkInfo(networkAgent.networkInfo);
|
||||
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);
|
||||
networkAgent.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 (networkAgent.networkRequests.get(mDefaultRequest.requestId) != null) {
|
||||
newDefaultAgent = mNetworkForRequestId.get(mDefaultRequest.requestId);
|
||||
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);
|
||||
final Intent immediateIntent = new Intent(intent);
|
||||
immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
|
||||
sendStickyBroadcast(immediateIntent);
|
||||
sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
|
||||
if (newDefaultAgent != null) {
|
||||
sendConnectedBroadcastDelayed(newDefaultAgent.networkInfo,
|
||||
getConnectivityChangeDelay());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.connectivity;
|
||||
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkRequest;
|
||||
import android.os.Messenger;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.util.AsyncChannel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A bag class used by ConnectivityService for holding a collection of most recent
|
||||
* information published by a particular NetworkAgent as well as the
|
||||
* AsyncChannel/messenger for reaching that NetworkAgent and lists of NetworkRequests
|
||||
* interested in using it.
|
||||
*/
|
||||
public class NetworkAgentInfo {
|
||||
public NetworkInfo networkInfo;
|
||||
public final Network network;
|
||||
public LinkProperties linkProperties;
|
||||
public NetworkCapabilities networkCapabilities;
|
||||
public int currentScore;
|
||||
|
||||
// The list of NetworkRequests being satisfied by this Network.
|
||||
public final SparseArray<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>();
|
||||
|
||||
// The list of NetworkListens listening for changes on this Network.
|
||||
public final ArrayList<NetworkRequest> networkListens = new ArrayList<NetworkRequest>();
|
||||
public final Messenger messenger;
|
||||
public final AsyncChannel asyncChannel;
|
||||
|
||||
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, int netId, NetworkInfo info,
|
||||
LinkProperties lp, NetworkCapabilities nc, int score) {
|
||||
this.messenger = messenger;
|
||||
asyncChannel = ac;
|
||||
network = new Network(netId);
|
||||
networkInfo = info;
|
||||
linkProperties = lp;
|
||||
networkCapabilities = nc;
|
||||
currentScore = score;
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "NetworkAgentInfo{ ni{" + networkInfo + "} network{" +
|
||||
network + "} lp{" +
|
||||
linkProperties + "} nc{" +
|
||||
networkCapabilities + "} Score{" + currentScore + "} }";
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return "NetworkAgentInfo [" + networkInfo.getTypeName() + " (" +
|
||||
networkInfo.getSubtypeName() + ")]";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user