/* * Copyright (C) 2008 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.internal.telephony.mocks; import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeValid; import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import android.annotation.Nullable; import android.app.AlarmManager; import android.app.BroadcastOptions; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.ConnectivityManager.PacketKeepalive; import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.INetworkPolicyListener; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.LinkProperties; import android.net.LinkProperties.CompareResult; import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkCapabilities; import android.net.NetworkConfig; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkMisc; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; import android.net.NetworkState; import android.net.NetworkUtils; import android.net.Proxy; import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.UidRange; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.FileUtils; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.security.Credentials; import android.security.KeyStore; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.LocalLog; import android.util.LocalLog.ReadOnlyLocalLog; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.Xml; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnInfo; import com.android.internal.net.VpnProfile; import com.android.internal.util.AsyncChannel; import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkMonitor; import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.SortedSet; import java.util.TreeSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; /** * @hide */ public class ConnectivityServiceMock extends IConnectivityManager.Stub implements PendingIntent.OnFinished { private static final String TAG = "ConnectivityServiceMock"; private static final boolean DBG = true; private static final boolean VDBG = true; /** * used internally when registering NetworkFactories * obj = NetworkFactoryInfo */ 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; /** * used to add a network request * includes a NetworkRequestInfo */ private static final int EVENT_REGISTER_NETWORK_REQUEST = 19; /** * used to add a network listener - no request * includes a NetworkRequestInfo */ private static final int EVENT_REGISTER_NETWORK_LISTENER = 21; /** * used to remove a network request, either a listener or a real request * arg1 = UID of caller * obj = NetworkRequest */ private static final int EVENT_RELEASE_NETWORK_REQUEST = 22; /** * used internally when registering NetworkFactories * obj = Messenger */ private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23; private final HandlerThread mHandlerThread; /** Handler used for internal events. */ final private InternalHandler mHandler; /** Handler used for incoming {@link NetworkStateTracker} events. */ final private NetworkStateTrackerHandler mTrackerHandler; final private Context mContext; public ConnectivityServiceMock(Context context) { if (DBG) log("starting up"); mContext = context; mHandlerThread = new HandlerThread("ConnectivityServiceMock"); mHandlerThread.start(); mHandler = new InternalHandler(mHandlerThread.getLooper()); mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper()); } public void die() { // clean up threads/handlers } private class InternalHandler extends Handler { public InternalHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { switch (msg.what) { case EVENT_REGISTER_NETWORK_FACTORY: { handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj); break; } case EVENT_UNREGISTER_NETWORK_FACTORY: { handleUnregisterNetworkFactory((Messenger)msg.obj); break; } case EVENT_REGISTER_NETWORK_AGENT: { handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj); break; } case EVENT_REGISTER_NETWORK_REQUEST: case EVENT_REGISTER_NETWORK_LISTENER: { handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj); break; } case EVENT_RELEASE_NETWORK_REQUEST: { handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1); break; } } } } private class NetworkStateTrackerHandler extends Handler { public NetworkStateTrackerHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { NetworkInfo info; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 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; } } } } private boolean isRequest(NetworkRequest request) { return mNetworkRequests.get(request).isRequest; } private void handleAsyncChannelHalfConnect(Message msg) { AsyncChannel ac = (AsyncChannel) msg.obj; if (mNetworkFactoryInfos.containsKey(msg.replyTo)) { if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { if (VDBG) log("NetworkFactory connected"); // A network factory has connected. Send it all current NetworkRequests. for (NetworkRequestInfo nri : mNetworkRequests.values()) { if (nri.isRequest == false) continue; //NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId); NetworkAgentInfo nai = null; ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, (nai != null ? nai.getCurrentScore() : 0), 0, nri.request); } } else { loge("Error connecting NetworkFactory"); mNetworkFactoryInfos.remove(msg.obj); } } 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"); NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo); //if (nai != null) { // final boolean wasDefault = isDefaultNetwork(nai); // synchronized (mNetworkForNetId) { // mNetworkForNetId.remove(nai.network.netId); // mNetIdInUse.delete(nai.network.netId); // } // // Just in case. // mLegacyTypeTracker.remove(nai, wasDefault); //} } } } private void handleAsyncChannelDisconnected(Message msg) { NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo); if (nai != null) { if (DBG) { log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests()); } // A network agent has disconnected. // TODO - if we move the logic to the network agent (have them disconnect // because they lost all their requests or because their score isn't good) // then they would disconnect organically, report their new state and then // disconnect the channel. //if (nai.networkInfo.isConnected()) { // nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, // null, null); //} //final boolean wasDefault = isDefaultNetwork(nai); //if (wasDefault) { // mDefaultInetConditionPublished = 0; //} //notifyIfacesChanged(); // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied // by other networks that are already connected. Perhaps that can be done by // sending all CALLBACK_LOST messages (for requests, not listens) at the end // of rematchAllNetworksAndRequests //notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST); //mKeepaliveTracker.handleStopAllKeepalives(nai, // ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED); mNetworkAgentInfos.remove(msg.replyTo); //updateClat(null, nai.linkProperties, nai); //synchronized (mNetworkForNetId) { // // Remove the NetworkAgent, but don't mark the netId as // // available until we've told netd to delete it below. // mNetworkForNetId.remove(nai.network.netId); //} // Remove all previously satisfied requests. //for (int i = 0; i < nai.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); // sendUpdatedScoreToFactories(request, 0); // } //} //if (nai.networkRequests.get(mDefaultRequest.requestId) != null) { // removeDataActivityTracking(nai); // notifyLockdownVpn(nai); // requestNetworkTransitionWakelock(nai.name()); //} //mLegacyTypeTracker.remove(nai, wasDefault); //rematchAllNetworksAndRequests(null, 0); //if (nai.created) { // // Tell netd to clean up the configuration for this network // // (routing rules, DNS, etc). // // This may be slow as it requires a lot of netd shelling out to ip and // // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it // // after we've rematched networks with requests which should make a potential // // fallback network the default or requested a new network from the // // NetworkFactories, so network traffic isn't interrupted for an unnecessarily // // long time. // try { // mNetd.removeNetwork(nai.network.netId); // } catch (Exception e) { // loge("Exception removing network: " + e); // } //} //synchronized (mNetworkForNetId) { // mNetIdInUse.delete(nai.network.netId); //} } else { NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo); if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name); } } private void log(String str) { Slog.d(TAG, str); } private void loge(String str) { Slog.e(TAG, str); } // NetworkAgentInfo keyed off its connecting messenger // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays // NOTE: Only should be accessed on ConnectivityServiceThread, except dump(). private final HashMap mNetworkAgentInfos = new HashMap(); private final HashMap mNetworkFactoryInfos = new HashMap(); private final HashMap mNetworkRequests = new HashMap(); private static class NetworkFactoryInfo { public final String name; public final Messenger messenger; public final AsyncChannel asyncChannel; public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) { this.name = name; this.messenger = messenger; this.asyncChannel = asyncChannel; } } private class NetworkRequestInfo implements IBinder.DeathRecipient { static final boolean REQUEST = true; static final boolean LISTEN = false; final NetworkRequest request; final PendingIntent mPendingIntent; boolean mPendingIntentSent; private final IBinder mBinder; final int mPid; final int mUid; final Messenger messenger; final boolean isRequest; NetworkRequestInfo(NetworkRequest r, PendingIntent pi, boolean isRequest) { request = r; mPendingIntent = pi; messenger = null; mBinder = null; mPid = getCallingPid(); mUid = getCallingUid(); this.isRequest = isRequest; } NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, boolean isRequest) { super(); messenger = m; request = r; mBinder = binder; mPid = getCallingPid(); mUid = getCallingUid(); this.isRequest = isRequest; mPendingIntent = null; try { mBinder.linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); } } void unlinkDeathRecipient() { if (mBinder != null) { mBinder.unlinkToDeath(this, 0); } } public void binderDied() { log("ConnectivityService NetworkRequestInfo binderDied(" + request + ", " + mBinder + ")"); releaseNetworkRequest(request); } public String toString() { return (isRequest ? "Request" : "Listen") + " from uid/pid:" + mUid + "/" + mPid + " for " + request + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent); } } // sequence number of NetworkRequests private int mNextNetworkRequestId = 1; private synchronized int nextNetworkRequestId() { return mNextNetworkRequestId++; } @Override public NetworkInfo getActiveNetworkInfo() { throw new RuntimeException("not implemented"); } @Override public Network getActiveNetwork() { throw new RuntimeException("not implemented"); } @Override public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) { throw new RuntimeException("not implemented"); } public NetworkInfo getActiveNetworkInfoUnfiltered() { throw new RuntimeException("not implemented"); } @Override public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) { throw new RuntimeException("not implemented"); } @Override public NetworkInfo getNetworkInfo(int networkType) { throw new RuntimeException("not implemented"); } @Override public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) { throw new RuntimeException("not implemented"); } @Override public NetworkInfo[] getAllNetworkInfo() { throw new RuntimeException("not implemented"); } @Override public Network getNetworkForType(int networkType) { throw new RuntimeException("not implemented"); } @Override public Network[] getAllNetworks() { throw new RuntimeException("not implemented"); } @Override public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) { throw new RuntimeException("not implemented"); } @Override public boolean isNetworkSupported(int networkType) { throw new RuntimeException("not implemented"); } @Override public LinkProperties getActiveLinkProperties() { throw new RuntimeException("not implemented"); } @Override public LinkProperties getLinkPropertiesForType(int networkType) { throw new RuntimeException("not implemented"); } @Override public LinkProperties getLinkProperties(Network network) { throw new RuntimeException("not implemented"); } @Override public void requestLinkProperties(NetworkRequest networkRequest) { throw new RuntimeException("not implemented"); } @Override public NetworkCapabilities getNetworkCapabilities(Network network) { throw new RuntimeException("not implemented"); } @Override public void requestNetworkCapabilities(NetworkRequest networkRequest) { throw new RuntimeException("not implemented"); } @Override public NetworkState[] getAllNetworkState() { throw new RuntimeException("not implemented"); } @Override public NetworkQuotaInfo getActiveNetworkQuotaInfo() { throw new RuntimeException("not implemented"); } @Override public boolean isActiveNetworkMetered() { throw new RuntimeException("not implemented"); } public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) { throw new RuntimeException("not implemented"); } @Override public int getRestoreDefaultNetworkDelay(int networkType) { throw new RuntimeException("not implemented"); } @Override protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { throw new RuntimeException("not implemented"); } public void setAcceptUnvalidated(Network network, boolean accept, boolean always) { throw new RuntimeException("not implemented"); } public void setAvoidUnvalidated(Network network) { throw new RuntimeException("not implemented"); } public int tether(String iface) { throw new RuntimeException("not implemented"); } public int untether(String iface) { throw new RuntimeException("not implemented"); } public int getLastTetherError(String iface) { throw new RuntimeException("not implemented"); } public String[] getTetherableUsbRegexs() { throw new RuntimeException("not implemented"); } public String[] getTetherableWifiRegexs() { throw new RuntimeException("not implemented"); } public String[] getTetherableBluetoothRegexs() { throw new RuntimeException("not implemented"); } public int setUsbTethering(boolean enable) { throw new RuntimeException("not implemented"); } public String[] getTetherableIfaces() { throw new RuntimeException("not implemented"); } public String[] getTetheredIfaces() { throw new RuntimeException("not implemented"); } public String[] getTetheringErroredIfaces() { throw new RuntimeException("not implemented"); } public String[] getTetheredDhcpRanges() { throw new RuntimeException("not implemented"); } @Override public boolean isTetheringSupported() { throw new RuntimeException("not implemented"); } @Override public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) { throw new RuntimeException("not implemented"); } @Override public void stopTethering(int type) { throw new RuntimeException("not implemented"); } public void reportInetCondition(int networkType, int percentage) { throw new RuntimeException("not implemented"); } public void reportNetworkConnectivity(Network network, boolean hasConnectivity) { throw new RuntimeException("not implemented"); } public ProxyInfo getProxyForNetwork(Network network) { throw new RuntimeException("not implemented"); } public void setGlobalProxy(ProxyInfo proxyProperties) { throw new RuntimeException("not implemented"); } public ProxyInfo getGlobalProxy() { throw new RuntimeException("not implemented"); } @Override public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, int userId) { throw new RuntimeException("not implemented"); } public void setVpnPackageAuthorization(String packageName, int userId, boolean authorized) { throw new RuntimeException("not implemented"); } @Override public ParcelFileDescriptor establishVpn(VpnConfig config) { throw new RuntimeException("not implemented"); } @Override public void startLegacyVpn(VpnProfile profile) { throw new RuntimeException("not implemented"); } @Override public LegacyVpnInfo getLegacyVpnInfo(int userId) { throw new RuntimeException("not implemented"); } @Override public VpnInfo[] getAllVpnInfo() { throw new RuntimeException("not implemented"); } @Override public VpnConfig getVpnConfig(int userId) { throw new RuntimeException("not implemented"); } @Override public boolean updateLockdownVpn() { throw new RuntimeException("not implemented"); } @Override public boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdownEnabled) { throw new RuntimeException("not implemented"); } @Override public String getAlwaysOnVpnPackage(int userId) { throw new RuntimeException("not implemented"); } @Override public int checkMobileProvisioning(int suggestedTimeOutMs) { throw new RuntimeException("not implemented"); } @Override public String getMobileProvisioningUrl() { throw new RuntimeException("not implemented"); } @Override public void setProvisioningNotificationVisible(boolean visible, int networkType, String action) { throw new RuntimeException("not implemented"); } @Override public void setAirplaneMode(boolean enable) { throw new RuntimeException("not implemented"); } @Override public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, int timeoutMs, IBinder binder, int legacyType) { networkCapabilities = new NetworkCapabilities(networkCapabilities); if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) { throw new IllegalArgumentException("Bad timeout specified"); } NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType, nextNetworkRequestId(), NetworkRequest.Type.REQUEST); NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder, true); if (DBG) log("requestNetwork for " + nri); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri)); return networkRequest; } @Override public boolean requestBandwidthUpdate(Network network) { throw new RuntimeException("not implemented"); } @Override public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation) { throw new RuntimeException("not implemented"); } @Override public void releasePendingNetworkRequest(PendingIntent operation) { throw new RuntimeException("not implemented"); } @Override public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, IBinder binder) { throw new RuntimeException("not implemented"); } @Override public void pendingListenForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation) { throw new RuntimeException("not implemented"); } @Override public void releaseNetworkRequest(NetworkRequest networkRequest) { mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest)); } @Override public void registerNetworkFactory(Messenger messenger, String name) { NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel()); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi)); } private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) { if (DBG) log("Got NetworkFactory Messenger for " + nfi.name); mNetworkFactoryInfos.put(nfi.messenger, nfi); nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger); } @Override public void unregisterNetworkFactory(Messenger messenger) { mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger)); } private void handleUnregisterNetworkFactory(Messenger messenger) { NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger); if (nfi == null) { loge("Failed to find Messenger in unregisterNetworkFactory"); return; } if (DBG) log("unregisterNetworkFactory for " + nfi.name); } public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkMisc networkMisc) { // final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), // new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties( // linkProperties), new NetworkCapabilities(networkCapabilities), currentScore, // mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this); // synchronized (this) { // nai.networkMonitor.systemReady = mSystemReady; // } // mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai)); // return nai.network.netId; throw new RuntimeException("not implemented"); } private void handleRegisterNetworkAgent(NetworkAgentInfo na) { if (VDBG) log("Got NetworkAgent Messenger"); // mNetworkAgentInfos.put(na.messenger, na); // synchronized (mNetworkForNetId) { // mNetworkForNetId.put(na.network.netId, na); // } // na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger); // NetworkInfo networkInfo = na.networkInfo; // na.networkInfo = null; // updateNetworkInfo(na, networkInfo); } private void handleRegisterNetworkRequest(NetworkRequestInfo nri) { mNetworkRequests.put(nri.request, nri); if (!nri.isRequest) { for (NetworkAgentInfo network : mNetworkAgentInfos.values()) { if (nri.request.networkCapabilities.hasSignalStrength() && network.satisfiesImmutableCapabilitiesOf(nri.request)) { } } } rematchAllNetworksAndRequests(null, 0); if (nri.isRequest) { sendUpdatedScoreToFactories(nri.request, 0); } } private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) { NetworkRequestInfo nri = mNetworkRequests.get(request); if (nri != null) { if (DBG) log("releasing NetworkRequest " + request); nri.unlinkDeathRecipient(); mNetworkRequests.remove(request); if (nri.isRequest) { // Find all networks that are satisfying this request and remove the request // from their request lists. // TODO - it's my understanding that for a request there is only a single // network satisfying it, so this loop is wasteful //boolean wasKept = false; //for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { // if (nai.networkRequests.get(nri.request.requestId) != null) { // nai.networkRequests.remove(nri.request.requestId); // if (DBG) { // log(" Removing from current network " + nai.name() + // ", leaving " + nai.networkRequests.size() + // " requests."); // } // if (unneeded(nai)) { // if (DBG) log("no live requests for " + nai.name() + "; disconnecting"); // teardownUnneededNetwork(nai); // } else { // // suspect there should only be one pass through here // // but if any were kept do the check below // wasKept |= true; // } // } //} //NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId); //if (nai != null) { // mNetworkForRequestId.remove(nri.request.requestId); //} // Maintain the illusion. When this request arrived, we might have pretended // that a network connected to serve it, even though the network was already // connected. Now that this request has gone away, we might have to pretend // that the network disconnected. LegacyTypeTracker will generate that // phantom disconnect for this type. //if (nri.request.legacyType != TYPE_NONE && nai != null) { // boolean doRemove = true; // if (wasKept) { // // check if any of the remaining requests for this network are for the // // same legacy type - if so, don't remove the nai // for (int i = 0; i < nai.networkRequests.size(); i++) { // NetworkRequest otherRequest = nai.networkRequests.valueAt(i); // if (otherRequest.legacyType == nri.request.legacyType && // isRequest(otherRequest)) { // if (DBG) log(" still have other legacy request - leaving"); // doRemove = false; // } // } // } // // if (doRemove) { // mLegacyTypeTracker.remove(nri.request.legacyType, nai, false); // } //} for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) { nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST, nri.request); } } else { // listens don't have a singular affectedNetwork. Check all networks to see // if this listen request applies and remove it. //for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { // nai.networkRequests.remove(nri.request.requestId); // if (nri.request.networkCapabilities.hasSignalStrength() && // nai.satisfiesImmutableCapabilitiesOf(nri.request)) { // updateSignalStrengthThresholds(nai, "RELEASE", nri.request); // } //} } //callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED); } } private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) { for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest nr = nai.requestAt(i); // Don't send listening requests to factories. b/17393458 if (!isRequest(nr)) continue; sendUpdatedScoreToFactories(nr, nai.getCurrentScore()); } } private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) { if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString()); for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) { nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0, networkRequest); } } private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) { } @Override public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras) { throw new RuntimeException("not implemented"); } @Override public boolean addVpnAddress(String address, int prefixLength) { throw new RuntimeException("not implemented"); } @Override public boolean removeVpnAddress(String address, int prefixLength) { throw new RuntimeException("not implemented"); } @Override public boolean setUnderlyingNetworksForVpn(Network[] networks) { throw new RuntimeException("not implemented"); } @Override public String getCaptivePortalServerUrl() { throw new RuntimeException("not implemented"); } @Override public void startNattKeepalive(Network network, int intervalSeconds, Messenger messenger, IBinder binder, String srcAddr, int srcPort, String dstAddr) { throw new RuntimeException("not implemented"); } @Override public void stopKeepalive(Network network, int slot) { throw new RuntimeException("not implemented"); } @Override public void factoryReset() { throw new RuntimeException("not implemented"); } @VisibleForTesting public NetworkMonitor createNetworkMonitor(Context context, Handler handler, NetworkAgentInfo nai, NetworkRequest defaultRequest) { throw new RuntimeException("not implemented"); } @VisibleForTesting public NetworkRequest defaultRequest = null; @VisibleForTesting public synchronized void addDefaultRequest() { if (defaultRequest != null) return; NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addCapability(NET_CAPABILITY_INTERNET); netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED); defaultRequest = requestNetwork(netCap, null, 0, new Binder(), ConnectivityManager.TYPE_NONE); } @VisibleForTesting public synchronized void setCurrentScoreForRequest(NetworkRequest nr, int score) { sendUpdatedScoreToFactories(nr, score); } @VisibleForTesting public synchronized void removeDefaultRequest() { if (defaultRequest == null) return; releaseNetworkRequest(defaultRequest); defaultRequest = null; } }