M7350/base/services/java/com/android/server/LinkManager.java
2024-09-09 08:52:07 +00:00

724 lines
28 KiB
Java

/*
* Copyright (C) 2010, 2011, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of The Linux Foundation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.android.server;
import com.android.internal.net.IPVersion;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.Phone.DataState;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.ILinkSocketMessageHandler;
import android.net.LinkCapabilities;
import android.net.LinkInfo;
import android.net.LinkProperties;
import android.net.LinkSocket;
import android.net.NetworkInfo;
import android.net.LinkProvider.LinkRequirement;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Public implementation of the ILinkManager interface.
* Provides basic LinkManager functionality.
*/
public class LinkManager implements ILinkManager {
private static final boolean DBG = true;
private static final String TAG = "LinkManager";
private CarrierProfile mCarrierProfile;
private Context mContext;
private ConnectivityService mConnectivityService;
private WifiManager mWifiManager;
private TelephonyManager mTelephonyManager;
private Map<Integer,LinkSocketInfo> mActiveLinks; // SocketID -> LinkSocketInfo
private HandlerThread mHandlerThread;
private LMHandler mHandler;
private int mDefaultNetwork;
/**
* Storage for LinkSocket-related data.
*/
private class LinkSocketInfo {
public int id; // Socket ID
public LinkCapabilities capabilities;
public ILinkSocketMessageHandler callback;
public int assignedNetwork; // ConnectivityManager.TYPE_WIFI or TYPE_MOBILE
public int status;
// State: unassigned, assigned, lost?
static final int UNASSIGNED = 0;
static final int ASSIGNED = 1;
static final int LOST = 2;
static final int NETWORK_UNKNOWN = -1;
}
public LinkManager(Context context, ConnectivityService cs) {
if (DBG) Log.v(TAG, "LinkManager constructor");
mContext = context;
mConnectivityService = cs;
mCarrierProfile = new CarrierProfile();
String carrierPolicyFilename = SystemProperties.get("persist.cne.loc.policy.op");
try {
mCarrierProfile.parse(new FileInputStream(carrierPolicyFilename));
} catch (FileNotFoundException e) {
Log.e(TAG, "Carrier Policy file not found: " + carrierPolicyFilename);
}
mDefaultNetwork = mCarrierProfile.getPreferredNetworks(0).get(0);
if (DBG) Log.v(TAG, "Default network = " + networkIntToString(mDefaultNetwork));
mConnectivityService.setDefaultRoute(mDefaultNetwork);
mHandlerThread = new HandlerThread("LMHandler");
mHandlerThread.start();
mHandler = new LMHandler(mHandlerThread.getLooper());
mActiveLinks = new ConcurrentHashMap<Integer, LinkSocketInfo>();
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
context.registerReceiver(mIntentReceiver, filter);
}
BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
// Turn WiFi Intents into LinkManager Handler events (connected/disconnected)
NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
NetworkInfo.State state = (networkInfo == null ? NetworkInfo.State.UNKNOWN : networkInfo.getState());
if (state == NetworkInfo.State.CONNECTED) {
Message msg = mHandler.obtainMessage(LMHandler.NETWORK_CONNECTED, ConnectivityManager.TYPE_WIFI, 0);
msg.sendToTarget();
} else if (state == NetworkInfo.State.DISCONNECTED) {
Message msg = mHandler.obtainMessage(LMHandler.NETWORK_DISCONNECTED, ConnectivityManager.TYPE_WIFI, 0);
msg.sendToTarget();
}
} else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
// Turn Telephony Intents into LinkManager Handler events (connected/disconnected)
String apnType = intent.getStringExtra(Phone.DATA_APN_TYPES_KEY);
if (apnType.equals(Phone.APN_TYPE_DEFAULT)) {
DataState dataState = Enum.valueOf(Phone.DataState.class, intent.getStringExtra(Phone.DATA_APN_TYPE_STATE));
if (dataState == DataState.CONNECTED) {
Message msg = mHandler.obtainMessage(LMHandler.NETWORK_CONNECTED, ConnectivityManager.TYPE_MOBILE, 0);
msg.sendToTarget();
} else if (dataState == DataState.DISCONNECTED) {
Message msg = mHandler.obtainMessage(LMHandler.NETWORK_DISCONNECTED, ConnectivityManager.TYPE_MOBILE, 0);
msg.sendToTarget();
}
}
} else {
if (DBG) Log.d(TAG, "Received unexpected action: " + action);
}
}
};
/**
* LinkManager event handler class.
* The majority of the LinkManager logic resides here.
*/
class LMHandler extends Handler {
// Message types
static final int REQUEST_LINK = 1;
static final int RELEASE_LINK = 2;
static final int NETWORK_CONNECTED = 3;
static final int NETWORK_DISCONNECTED = 4;
static final int CONNECTION_TIMED_OUT = 5;
// Constants
static final int CONNECTION_TIMEOUT = 10000; // ms
public LMHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
switch (msg.what) {
case REQUEST_LINK:
handleRequestLink(msg);
break;
case RELEASE_LINK:
handleReleaseLink(msg);
break;
case NETWORK_CONNECTED:
handleNetworkConnected(msg);
break;
case NETWORK_DISCONNECTED:
handleNetworkDisconnected(msg);
break;
case CONNECTION_TIMED_OUT:
handleConnectionTimedOut(msg);
break;
default:
if (DBG) Log.d(TAG, "LMHandler handleMessage: unknown message");
break;
}
}
private void handleRequestLink(Message msg) {
int id = msg.arg1;
LinkSocketInfo lsInfo = mActiveLinks.get(id);
LinkCapabilities capabilities = lsInfo.capabilities; // needed capabilities
int role = roleStringToInt(capabilities.get(LinkCapabilities.Key.RW_ROLE));
List<Integer> preferredNetworks = mCarrierProfile.getPreferredNetworks(role);
applyCapabilitiesToNetworks(capabilities, preferredNetworks);
if (DBG) Log.v(TAG, "handleRequestLink id: " + id + " role: " + role);
// assign to the first active network
for (int network : preferredNetworks) {
if (isNetworkConnected(network)) {
getMinAvailableForwardBandwidth(network); // Stub for bandwidth estimation
// TODO: add a timer for bandwidth estimate changed.
if (DBG) Log.v(TAG, "assigning id " + lsInfo.id + " to network " + networkIntToString(network));
lsInfo.assignedNetwork = network;
lsInfo.status = LinkSocketInfo.ASSIGNED;
break;
}
}
if (lsInfo.status == LinkSocketInfo.ASSIGNED) {
// no changes are necessary, send the onLinkAvail notification
try {
lsInfo.callback.onLinkAvail(propertiesForNetwork(lsInfo.assignedNetwork));
} catch (RemoteException e) {
if (DBG) Log.d(TAG, "RemoteException sending onLinkAvail()");
}
} else {
// No active networks are acceptable - bring up the first preference
int network = preferredNetworks.get(0);
lsInfo.assignedNetwork = network;
if (DBG) Log.d(TAG, "cannot assign to available networks - bringing up " + networkIntToString(network));
mConnectivityService.reconnect(network);
// Start timer for connection
Message timeoutMsg = mHandler.obtainMessage(CONNECTION_TIMED_OUT, id, network);
mHandler.sendMessageDelayed(timeoutMsg, CONNECTION_TIMEOUT);
}
}
private void handleReleaseLink(Message msg) {
LinkSocketInfo released = (LinkSocketInfo) msg.obj;
int releasedNetwork = released.assignedNetwork;
if (DBG) Log.v(TAG, "handleReleaseLink net: " + releasedNetwork);
// Trigger teardown if no other links are using the network
// (but don't tear down the last network or the default network)
if (anotherNetworkIsAvailable(releasedNetwork) && releasedNetwork != mDefaultNetwork) {
boolean shouldBringDownNetwork = true;
for (LinkSocketInfo lsInfo : mActiveLinks.values()) {
if (lsInfo.assignedNetwork == releasedNetwork) {
shouldBringDownNetwork = false;
break;
}
}
if (shouldBringDownNetwork) {
if (DBG) Log.v(TAG, "bringing down network: " + releasedNetwork);
mConnectivityService.teardown(releasedNetwork);
}
}
}
private void handleNetworkConnected(Message msg) {
int network = msg.arg1;
if (DBG) Log.v(TAG, "handleNetworkConnected: " + networkIntToString(network));
// check for waiting connections
for (LinkSocketInfo lsInfo : mActiveLinks.values()) {
if (lsInfo.status == LinkSocketInfo.UNASSIGNED && lsInfo.assignedNetwork == network) {
lsInfo.status = LinkSocketInfo.ASSIGNED;
try {
lsInfo.callback.onLinkAvail(propertiesForNetwork(lsInfo.assignedNetwork));
} catch (RemoteException e) {
if (DBG) Log.d(TAG, "RemoteException sending onLinkAvail()");
}
}
}
bringDownUnusedNetworks();
}
private void handleNetworkDisconnected(Message msg) {
int network = msg.arg1;
if (DBG) Log.v(TAG, "handleNetworkDisconnected: " + networkIntToString(network));
// send notifications to all affected links
for (LinkSocketInfo lsInfo : mActiveLinks.values()) {
if (lsInfo.assignedNetwork == network) {
lsInfo.status = LinkSocketInfo.LOST;
try {
lsInfo.callback.onLinkLost();
} catch (RemoteException e) {
if (DBG) Log.d(TAG, "RemoteException sending onLinkLost()");
}
if (anotherNetworkIsAvailable(network)) {
try {
lsInfo.callback.onBetterLinkAvail();
} catch (RemoteException e) {
if (DBG) Log.d(TAG, "RemoteException sending onBetterLinkAvail()");
}
}
}
}
}
private void handleConnectionTimedOut(Message msg) {
int id = msg.arg1;
int network = msg.arg2;
if (DBG) Log.v(TAG, "handleConnectionTimedOut (possibly) id: " + id + " net: " + network);
// check if the connection actually timed out
if (mActiveLinks.get(id).status == LinkSocketInfo.ASSIGNED) return;
if (DBG) Log.v(TAG, "handleConnectionTimedOut actual timeout id: " + id + " net: " + network);
// bring down the failing network
if (network != mDefaultNetwork) {
mConnectivityService.teardown(network);
}
// timed out. send failure.
try {
mActiveLinks.get(id).callback.onGetLinkFailure(LinkSocket.ERROR_ALL_NETWORKS_DOWN);
} catch (RemoteException e) {
if (DBG) Log.d(TAG, "RemoteException sending onGetLinkFailure()");
}
}
private boolean anotherNetworkIsAvailable(int network) {
int otherNetwork = LinkSocketInfo.NETWORK_UNKNOWN;
if (network == ConnectivityManager.TYPE_MOBILE) otherNetwork = ConnectivityManager.TYPE_WIFI;
else otherNetwork = ConnectivityManager.TYPE_MOBILE;
return isNetworkConnected(otherNetwork);
}
private void bringDownUnusedNetworks() {
if (DBG) Log.v(TAG, "bringDownUnusedNetworks() EX");
int[] allNetworks = {ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_WIFI};
for (int i = 0; i < allNetworks.length; i++) {
int network = allNetworks[i];
if (network == mDefaultNetwork) continue; // Don't bring down default network
if (!anotherNetworkIsAvailable(network)) continue; // Don't bring down the only active network
boolean networkInUse = false;
for (LinkSocketInfo lsInfo : mActiveLinks.values()) {
if (lsInfo.assignedNetwork == network) {
networkInUse = true;
break;
}
}
if (!networkInUse) {
if (DBG) Log.v(TAG, "bringing down unused network: " + networkIntToString(network));
mConnectivityService.teardown(network);
}
}
}
/**
* Modifies preferredNetworks list according to keys in capabilities.
*
* @param capabilities The needed LinkCapabilities.
* @param preferredNetworks The list of networks to modify.
*/
private void applyCapabilitiesToNetworks(LinkCapabilities capabilities,
List<Integer> preferredNetworks) {
if (DBG) Log.v(TAG, "applyCapabilitiesToNetworks: caps" + capabilities + "nets" + preferredNetworks);
// Apply "allowed networks" rule
if (capabilities.containsKey(LinkCapabilities.Key.RW_ALLOWED_NETWORKS)) {
String allowed = capabilities.get(LinkCapabilities.Key.RW_ALLOWED_NETWORKS);
List<Integer> allowedNetworks = csNetworkStringToList(allowed);
// remove all networks that aren't allowed
preferredNetworks.retainAll(allowedNetworks);
}
// Apply "prohibited networks" rule
if (capabilities.containsKey(LinkCapabilities.Key.RW_PROHIBITED_NETWORKS)) {
String prohibited = capabilities.get(LinkCapabilities.Key.RW_PROHIBITED_NETWORKS);
List<Integer> prohibitedNetworks = csNetworkStringToList(prohibited);
preferredNetworks.removeAll(prohibitedNetworks);
}
if (DBG) Log.v(TAG, "applyCapabilitiesToNetworks resulting nets: " + preferredNetworks);
}
/**
* Converts a comma-separated list of networks (as used in
* LinkCapabilities) into a list of network ID's, as defined by
* ConnectivityManager.
*
* @param networks Comma-separated network string, e.g. "wifi, mobile"
* @return List of network ID's, e.g. {
* ConnectivityManager.NETWORK_WIFI,
* ConnectivityManager.NETWORK_MOBILE }
*/
private List<Integer> csNetworkStringToList(String networks) {
String[] netNames = networks.split(",\\s?");
List<Integer> netList = new ArrayList<Integer>(netNames.length);
for (String name : netNames) {
int network = networkStringToInt(name);
if (network != LinkSocketInfo.NETWORK_UNKNOWN) {
netList.add(network);
}
}
return netList;
}
}
public int requestLink(LinkCapabilities capabilities, IBinder binder) {
int id = getNextSocketId();
if (DBG) Log.v(TAG, "requestLink capabilities: " + capabilities);
LinkSocketInfo info = new LinkSocketInfo();
info.id = id;
info.capabilities = capabilities;
info.callback = ILinkSocketMessageHandler.Stub.asInterface(binder);
info.assignedNetwork = LinkSocketInfo.NETWORK_UNKNOWN;
info.status = LinkSocketInfo.UNASSIGNED;
mActiveLinks.put(info.id, info);
Message msg = mHandler.obtainMessage(LMHandler.REQUEST_LINK, id, 0);
msg.sendToTarget();
return id;
}
public void releaseLink(int id) {
if (DBG) Log.v(TAG, "releaseLink id: " + id);
LinkSocketInfo removed = mActiveLinks.remove(id);
Message msg = mHandler.obtainMessage(LMHandler.RELEASE_LINK, removed);
msg.sendToTarget();
}
public boolean requestQoS(int id, int localPort, String localAddress) {
if (DBG) Log.e(TAG, "requestQoS is not supported");
return false;
}
/**
* Minimum available forward link (download) bandwidth for the socket. This value is
* in kilobits per second (kbps).
*/
public String getMinAvailableForwardBandwidth(int id) {
// Implementation left to OEMs
return null;
}
/**
* Maximum available forward link (download) bandwidth for the socket. This value is
* in kilobits per second (kbps).
*/
public String getMaxAvailableForwardBandwidth(int id) {
// Implementation left to OEMs
return null;
}
/**
* Minimum available reverse link (upload) bandwidth for the socket. This value is
* in kilobits per second (kbps).
*/
public String getMinAvailableReverseBandwidth(int id) {
// Implementation left to OEMs
return null;
}
/**
* Maximum available reverse link (upload) bandwidth for the socket. This value is
* in kilobits per second (kbps).
*/
public String getMaxAvailableReverseBandwidth(int id) {
// Implementation left to OEMs
return null;
}
/**
* Current estimated downlink latency of the socket, in milliseconds.
*/
public String getCurrentFwdLatency(int id) {
// Implementation left to OEMs
return null;
}
/**
* Current estimated uplink latency of the socket, in milliseconds.
*/
public String getCurrentRevLatency(int id) {
// Implementation left to OEMs
return null;
}
/**
* Current Quality of Service state of the socket
*/
public String getQosState(int id) {
// Implementation left to OEMs
return "inactive";
}
/**
* An integer representing the network type.
* @param id LinkSocket ID
* @see ConnectivityManager
*/
public int getNetworkType(int id) {
int netType = -1;
LinkSocketInfo info = mActiveLinks.get(id);
if (info != null) {
netType = mActiveLinks.get(id).assignedNetwork;
} else {
if (DBG) Log.d(TAG, "getNetworkType called with invalid id: " + id);
}
return netType;
}
/**
* Converts a role string to a role ID (as used in OperatorPolicy.xml)
* @param string Role
* @return Role ID
*/
private int roleStringToInt(String roleString) {
int roleInt = 0;
if (roleString == null) roleInt = 0;
else if (roleString.equals(LinkCapabilities.Role.DEFAULT)) roleInt = 0;
else if (roleString.equals(LinkCapabilities.Role.VIDEO_STREAMING_1080P)) roleInt = 1;
else if (roleString.equals(LinkCapabilities.Role.WEB_BROWSER)) roleInt = 2;
else Log.d(TAG, roleString + " is not a known role.");
return roleInt;
}
/**
* Converts network names (as used in Carrier Profile, e.g. "WWAN"; or in
* LinkCapabilities, e.g. "mobile") to ConnectivityManager constants.
*
* @param network Name of network
* @return The corresponding network constant from ConnectivityManager.
*/
private int networkStringToInt(String network) {
int networkInt = LinkSocketInfo.NETWORK_UNKNOWN;
if (network == null) {
if (DBG) Log.d(TAG, "networkStringToInt: null string");
} else if (network.equals("WLAN") || network.equals("wifi")) {
networkInt = ConnectivityManager.TYPE_WIFI;
} else if (network.equals("WWAN") || network.equals("mobile")) {
networkInt = ConnectivityManager.TYPE_MOBILE;
} else {
if (DBG) Log.d(TAG, network + " is not a known network name.");
}
if (DBG) Log.v(TAG, "networkStringToInt: " + network + ":" + networkInt);
return networkInt;
}
private String networkIntToString(int network) {
switch (network) {
case ConnectivityManager.TYPE_WIFI:
return "WiFi";
case ConnectivityManager.TYPE_MOBILE:
return "Mobile";
default:
// fall through
}
return "unknown network " + network;
}
private boolean isNetworkConnected(int networkType) {
if (DBG) Log.v(TAG, "isNetworkConnected: " + networkIntToString(networkType));
NetworkInfo networkInfo = mConnectivityService.getNetworkInfo(networkType);
return networkInfo.isConnected();
}
// TODO: Find out if there's an easier way to get network addresses. Aren't they saved anywhere already?
private LinkProperties propertiesForNetwork(int assignedNetwork) {
if (assignedNetwork == ConnectivityManager.TYPE_MOBILE) {
return getWwanProperties();
} else if (assignedNetwork == ConnectivityManager.TYPE_WIFI) {
return getWlanProperties();
}
return null;
}
private LinkProperties getWwanProperties() {
LinkProperties props = new LinkProperties();
if (mTelephonyManager == null) {
if (DBG) Log.d(TAG, "mTelephonyManager is null");
return props;
}
String interfaceName = mTelephonyManager.getActiveInterfaceName(Phone.APN_TYPE_DEFAULT, IPVersion.INET);
String addressString = mTelephonyManager.getActiveIpAddress(Phone.APN_TYPE_DEFAULT, IPVersion.INET);
try {
NetworkInterface networkInterface = NetworkInterface.getByName(interfaceName);
props.setInterface(networkInterface);
InetAddress address = InetAddress.getByName(addressString);
props.addAddress(address);
} catch (UnknownHostException e) {
if (DBG) Log.d(TAG, "getWwanProperties: Invalid host name " + addressString);
} catch (SocketException e) {
if (DBG) Log.d(TAG, "could not get network interface for " + interfaceName);
}
return props;
}
private LinkProperties getWlanProperties() {
LinkProperties props = new LinkProperties();
String ipAddr = null;
DhcpInfo dhcpInfo = mWifiManager.getDhcpInfo();
if (dhcpInfo == null) {
if (DBG) Log.d(TAG, "DhcpInfo is null. V4 address is not yet available.");
return props;
}
int ipAddressInt = dhcpInfo.ipAddress;
if (ipAddressInt != 0) {
ipAddr = ((ipAddressInt) & 0xff) + "."
+ ((ipAddressInt >> 8) & 0xff) + "."
+ ((ipAddressInt >> 16) & 0xff) + "."
+ ((ipAddressInt >> 24) & 0xff);
}
try {
InetAddress inetAddr = InetAddress.getByName(ipAddr);
NetworkInterface netIface = NetworkInterface.getByInetAddress(inetAddr);
props.addAddress(inetAddr);
props.setInterface(netIface);
} catch (UnknownHostException e) {
if (DBG) Log.d(TAG, "getWlanProperties: Invalid host name " + ipAddr);
} catch (SocketException e) {
if (DBG) Log.d(TAG, "could not get network interface for " + ipAddr);
}
return props;
}
private static int mSocketId = 0;
synchronized private static int getNextSocketId() {
if (mSocketId == Integer.MAX_VALUE) mSocketId = 0;
return mSocketId++;
}
/**
* The default connection is specified via Carrier Policy. This API is ignored.
*/
public void setDefaultConnectionNwPref(int preference) {
if (DBG) Log.v(TAG, "setDefaultConnectionNwPref " + preference + " ignored");
}
/**
* This seems redundant. We should probably remove this API.
*/
public void sendDefaultNwPref2Cne(int preference) {
setDefaultConnectionNwPref(preference);
}
/* FMC API stubs */
public boolean startFmc(IBinder listener) {
return false;
}
public boolean stopFmc(IBinder listener) {
return false;
}
public boolean getFmcStatus(IBinder listener) {
return false;
}
/* Old LinkProvider API stubs */
public boolean switchLink_LP(int role, int mPid, LinkInfo info, boolean isNotifyBetterLink) {
return false;
}
public boolean reportLinkSatisfaction_LP(int role, int mPid, LinkInfo info,
boolean isSatisfied, boolean isNotifyBetterCon) {
return false;
}
public boolean getLink_LP(int role, Map<LinkRequirement, String> linkReqs, int mPid,
IBinder listener) {
return false;
}
public boolean rejectSwitch_LP(int role, int mPid, LinkInfo info, boolean isNotifyBetterLink) {
return false;
}
public boolean releaseLink_LP(int role, int mPid) {
return false;
}
}