ConnectivityServiceMock.java revision 75dd4e6f367d24ec8ed39618652a57047c1fbb78
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.telephony.mocks;
18
19import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
20import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
21
22import android.annotation.Nullable;
23import android.app.PendingIntent;
24import android.content.Context;
25import android.content.Intent;
26import android.net.ConnectivityManager;
27import android.net.IConnectivityManager;
28import android.net.LinkProperties;
29import android.net.Network;
30import android.net.NetworkCapabilities;
31import android.net.NetworkInfo;
32import android.net.NetworkMisc;
33import android.net.NetworkQuotaInfo;
34import android.net.NetworkRequest;
35import android.net.NetworkState;
36import android.net.ProxyInfo;
37import android.os.Binder;
38import android.os.Bundle;
39import android.os.Handler;
40import android.os.HandlerThread;
41import android.os.IBinder;
42import android.os.Looper;
43import android.os.Message;
44import android.os.Messenger;
45import android.os.ParcelFileDescriptor;
46import android.os.RemoteException;
47import android.os.ResultReceiver;
48import android.util.Slog;
49
50import com.android.internal.annotations.VisibleForTesting;
51import com.android.internal.net.LegacyVpnInfo;
52import com.android.internal.net.VpnConfig;
53import com.android.internal.net.VpnInfo;
54import com.android.internal.net.VpnProfile;
55import com.android.internal.util.AsyncChannel;
56import com.android.server.connectivity.NetworkAgentInfo;
57import com.android.server.connectivity.NetworkMonitor;
58
59import java.io.FileDescriptor;
60import java.io.PrintWriter;
61import java.util.HashMap;
62
63/**
64 * @hide
65 */
66public class ConnectivityServiceMock extends IConnectivityManager.Stub
67        implements PendingIntent.OnFinished {
68    private static final String TAG = "ConnectivityServiceMock";
69    private static final boolean DBG = true;
70    private static final boolean VDBG = true;
71
72    /**
73     * used internally when registering NetworkFactories
74     * obj = NetworkFactoryInfo
75     */
76    private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
77
78    /**
79     * used internally when registering NetworkAgents
80     * obj = Messenger
81     */
82    private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
83
84    /**
85     * used to add a network request
86     * includes a NetworkRequestInfo
87     */
88    private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;
89
90    /**
91     * used to add a network listener - no request
92     * includes a NetworkRequestInfo
93     */
94    private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;
95
96    /**
97     * used to remove a network request, either a listener or a real request
98     * arg1 = UID of caller
99     * obj  = NetworkRequest
100     */
101    private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
102
103    /**
104     * used internally when registering NetworkFactories
105     * obj = Messenger
106     */
107    private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
108
109
110    private final HandlerThread mHandlerThread;
111    /** Handler used for internal events. */
112    final private InternalHandler mHandler;
113    /** Handler used for incoming {@link NetworkStateTracker} events. */
114    final private NetworkStateTrackerHandler mTrackerHandler;
115
116    final private Context mContext;
117
118    public ConnectivityServiceMock(Context context) {
119        if (DBG) log("starting up");
120
121        mContext = context;
122        mHandlerThread = new HandlerThread("ConnectivityServiceMock");
123        mHandlerThread.start();
124        mHandler = new InternalHandler(mHandlerThread.getLooper());
125        mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
126    }
127
128    public void die() {
129        // clean up threads/handlers
130    }
131
132    private class InternalHandler extends Handler {
133        public InternalHandler(Looper looper) {
134            super(looper);
135        }
136
137        @Override
138        public void handleMessage(Message msg) {
139            switch (msg.what) {
140                case EVENT_REGISTER_NETWORK_FACTORY: {
141                    handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
142                    break;
143                }
144                case EVENT_UNREGISTER_NETWORK_FACTORY: {
145                    handleUnregisterNetworkFactory((Messenger)msg.obj);
146                    break;
147                }
148                case EVENT_REGISTER_NETWORK_AGENT: {
149                    handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
150                    break;
151                }
152                case EVENT_REGISTER_NETWORK_REQUEST:
153                case EVENT_REGISTER_NETWORK_LISTENER: {
154                    handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
155                    break;
156                }
157                case EVENT_RELEASE_NETWORK_REQUEST: {
158                    handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
159                    break;
160                }
161            }
162        }
163    }
164
165    private class NetworkStateTrackerHandler extends Handler {
166        public NetworkStateTrackerHandler(Looper looper) {
167            super(looper);
168        }
169
170        @Override
171        public void handleMessage(Message msg) {
172            NetworkInfo info;
173            switch (msg.what) {
174                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
175                    handleAsyncChannelHalfConnect(msg);
176                    break;
177                }
178                case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
179                    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
180                    if (nai != null) nai.asyncChannel.disconnect();
181                    break;
182                }
183                case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
184                    handleAsyncChannelDisconnected(msg);
185                    break;
186                }
187            }
188        }
189    }
190
191    private boolean isRequest(NetworkRequest request) {
192        return mNetworkRequests.get(request).isRequest;
193    }
194
195    private void handleAsyncChannelHalfConnect(Message msg) {
196        AsyncChannel ac = (AsyncChannel) msg.obj;
197        if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
198            if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
199                if (VDBG) log("NetworkFactory connected");
200                // A network factory has connected.  Send it all current NetworkRequests.
201                for (NetworkRequestInfo nri : mNetworkRequests.values()) {
202                    if (nri.isRequest == false) continue;
203                    //NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
204                    NetworkAgentInfo nai = null;
205                    ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
206                            (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
207                }
208            } else {
209                loge("Error connecting NetworkFactory");
210                mNetworkFactoryInfos.remove(msg.obj);
211            }
212        } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
213            if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
214                if (VDBG) log("NetworkAgent connected");
215                // A network agent has requested a connection.  Establish the connection.
216                mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
217                        sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
218            } else {
219                loge("Error connecting NetworkAgent");
220                NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
221                //if (nai != null) {
222                //    final boolean wasDefault = isDefaultNetwork(nai);
223                //    synchronized (mNetworkForNetId) {
224                //        mNetworkForNetId.remove(nai.network.netId);
225                //        mNetIdInUse.delete(nai.network.netId);
226                //    }
227                //    // Just in case.
228                //    mLegacyTypeTracker.remove(nai, wasDefault);
229                //}
230            }
231        }
232    }
233
234    private void handleAsyncChannelDisconnected(Message msg) {
235        NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
236        if (nai != null) {
237            if (DBG) {
238                log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests());
239            }
240            // A network agent has disconnected.
241            // TODO - if we move the logic to the network agent (have them disconnect
242            // because they lost all their requests or because their score isn't good)
243            // then they would disconnect organically, report their new state and then
244            // disconnect the channel.
245            //if (nai.networkInfo.isConnected()) {
246            //    nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
247            //            null, null);
248            //}
249            //final boolean wasDefault = isDefaultNetwork(nai);
250            //if (wasDefault) {
251            //    mDefaultInetConditionPublished = 0;
252            //}
253            //notifyIfacesChanged();
254            // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
255            // by other networks that are already connected. Perhaps that can be done by
256            // sending all CALLBACK_LOST messages (for requests, not listens) at the end
257            // of rematchAllNetworksAndRequests
258            //notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
259            //mKeepaliveTracker.handleStopAllKeepalives(nai,
260            //       ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
261            nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
262            mNetworkAgentInfos.remove(msg.replyTo);
263            //updateClat(null, nai.linkProperties, nai);
264            //synchronized (mNetworkForNetId) {
265            //    // Remove the NetworkAgent, but don't mark the netId as
266            //    // available until we've told netd to delete it below.
267            //    mNetworkForNetId.remove(nai.network.netId);
268            //}
269            // Remove all previously satisfied requests.
270            //for (int i = 0; i < nai.networkRequests.size(); i++) {
271            //    NetworkRequest request = nai.networkRequests.valueAt(i);
272            //    NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
273            //    if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
274            //        mNetworkForRequestId.remove(request.requestId);
275            //        sendUpdatedScoreToFactories(request, 0);
276            //    }
277            //}
278            //if (nai.networkRequests.get(mDefaultRequest.requestId) != null) {
279            //    removeDataActivityTracking(nai);
280            //    notifyLockdownVpn(nai);
281            //    requestNetworkTransitionWakelock(nai.name());
282            //}
283            //mLegacyTypeTracker.remove(nai, wasDefault);
284            //rematchAllNetworksAndRequests(null, 0);
285            //if (nai.created) {
286            //    // Tell netd to clean up the configuration for this network
287            //    // (routing rules, DNS, etc).
288            //    // This may be slow as it requires a lot of netd shelling out to ip and
289            //    // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
290            //    // after we've rematched networks with requests which should make a potential
291            //    // fallback network the default or requested a new network from the
292            //    // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
293            //    // long time.
294            //    try {
295            //        mNetd.removeNetwork(nai.network.netId);
296            //    } catch (Exception e) {
297            //        loge("Exception removing network: " + e);
298            //    }
299            //}
300            //synchronized (mNetworkForNetId) {
301            //    mNetIdInUse.delete(nai.network.netId);
302            //}
303        } else {
304            NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
305            if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
306        }
307    }
308
309    private void log(String str) {
310        Slog.d(TAG, str);
311    }
312    private void loge(String str) {
313        Slog.e(TAG, str);
314    }
315
316    // NetworkAgentInfo keyed off its connecting messenger
317    // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
318    // NOTE: Only should be accessed on ConnectivityServiceThread, except dump().
319    private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos =
320            new HashMap<Messenger, NetworkAgentInfo>();
321    private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
322            new HashMap<Messenger, NetworkFactoryInfo>();
323    private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
324            new HashMap<NetworkRequest, NetworkRequestInfo>();
325
326    private static class NetworkFactoryInfo {
327        public final String name;
328        public final Messenger messenger;
329        public final AsyncChannel asyncChannel;
330
331        public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) {
332            this.name = name;
333            this.messenger = messenger;
334            this.asyncChannel = asyncChannel;
335        }
336    }
337
338    private class NetworkRequestInfo implements IBinder.DeathRecipient {
339        static final boolean REQUEST = true;
340        static final boolean LISTEN = false;
341
342        final NetworkRequest request;
343        final PendingIntent mPendingIntent;
344        boolean mPendingIntentSent;
345        private final IBinder mBinder;
346        final int mPid;
347        final int mUid;
348        final Messenger messenger;
349        final boolean isRequest;
350
351        NetworkRequestInfo(NetworkRequest r, PendingIntent pi, boolean isRequest) {
352            request = r;
353            mPendingIntent = pi;
354            messenger = null;
355            mBinder = null;
356            mPid = getCallingPid();
357            mUid = getCallingUid();
358            this.isRequest = isRequest;
359        }
360
361        NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, boolean isRequest) {
362            super();
363            messenger = m;
364            request = r;
365            mBinder = binder;
366            mPid = getCallingPid();
367            mUid = getCallingUid();
368            this.isRequest = isRequest;
369            mPendingIntent = null;
370
371            try {
372                mBinder.linkToDeath(this, 0);
373            } catch (RemoteException e) {
374                binderDied();
375            }
376        }
377
378        void unlinkDeathRecipient() {
379            if (mBinder != null) {
380                mBinder.unlinkToDeath(this, 0);
381            }
382        }
383
384        public void binderDied() {
385            log("ConnectivityService NetworkRequestInfo binderDied(" +
386                    request + ", " + mBinder + ")");
387            releaseNetworkRequest(request);
388        }
389
390        public String toString() {
391            return (isRequest ? "Request" : "Listen") +
392                    " from uid/pid:" + mUid + "/" + mPid +
393                    " for " + request +
394                    (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
395        }
396    }
397
398
399    // sequence number of NetworkRequests
400    private int mNextNetworkRequestId = 1;
401    private synchronized int nextNetworkRequestId() {
402        return mNextNetworkRequestId++;
403    }
404
405    @Override
406    public NetworkInfo getActiveNetworkInfo() {
407        throw new RuntimeException("not implemented");
408    }
409
410    @Override
411    public Network getActiveNetwork() {
412        throw new RuntimeException("not implemented");
413    }
414
415    @Override
416    public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
417        throw new RuntimeException("not implemented");
418    }
419
420    public NetworkInfo getActiveNetworkInfoUnfiltered() {
421        throw new RuntimeException("not implemented");
422    }
423
424    @Override
425    public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
426        throw new RuntimeException("not implemented");
427    }
428
429    @Override
430    public NetworkInfo getNetworkInfo(int networkType) {
431        throw new RuntimeException("not implemented");
432    }
433
434    @Override
435    public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) {
436        throw new RuntimeException("not implemented");
437    }
438
439    @Override
440    public NetworkInfo[] getAllNetworkInfo() {
441        throw new RuntimeException("not implemented");
442    }
443
444    @Override
445    public Network getNetworkForType(int networkType) {
446        throw new RuntimeException("not implemented");
447    }
448
449    @Override
450    public Network[] getAllNetworks() {
451        throw new RuntimeException("not implemented");
452    }
453
454    @Override
455    public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
456        throw new RuntimeException("not implemented");
457    }
458
459    @Override
460    public boolean isNetworkSupported(int networkType) {
461        throw new RuntimeException("not implemented");
462    }
463
464    @Override
465    public LinkProperties getActiveLinkProperties() {
466        throw new RuntimeException("not implemented");
467    }
468
469    @Override
470    public LinkProperties getLinkPropertiesForType(int networkType) {
471        throw new RuntimeException("not implemented");
472    }
473
474    @Override
475    public LinkProperties getLinkProperties(Network network) {
476        throw new RuntimeException("not implemented");
477    }
478
479    @Override
480    public NetworkCapabilities getNetworkCapabilities(Network network) {
481        throw new RuntimeException("not implemented");
482    }
483
484    @Override
485    public NetworkState[] getAllNetworkState() {
486        throw new RuntimeException("not implemented");
487    }
488
489    @Override
490    public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
491        throw new RuntimeException("not implemented");
492    }
493
494    @Override
495    public boolean isActiveNetworkMetered() {
496        throw new RuntimeException("not implemented");
497    }
498
499    public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
500        throw new RuntimeException("not implemented");
501    }
502
503    @Override
504    public int getRestoreDefaultNetworkDelay(int networkType) {
505        throw new RuntimeException("not implemented");
506    }
507
508    @Override
509    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
510        throw new RuntimeException("not implemented");
511    }
512
513    public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
514        throw new RuntimeException("not implemented");
515    }
516
517    public void setAvoidUnvalidated(Network network) {
518        throw new RuntimeException("not implemented");
519    }
520
521    public int getMultipathPreference(Network network) {
522        throw new RuntimeException("not implemented");
523    }
524
525    public int tether(String iface) {
526        throw new RuntimeException("not implemented");
527    }
528
529    public int untether(String iface) {
530        throw new RuntimeException("not implemented");
531    }
532
533    public int getLastTetherError(String iface) {
534        throw new RuntimeException("not implemented");
535    }
536
537    public String[] getTetherableUsbRegexs() {
538        throw new RuntimeException("not implemented");
539    }
540
541    public String[] getTetherableWifiRegexs() {
542        throw new RuntimeException("not implemented");
543    }
544
545    public String[] getTetherableBluetoothRegexs() {
546        throw new RuntimeException("not implemented");
547    }
548
549    public int setUsbTethering(boolean enable) {
550        throw new RuntimeException("not implemented");
551    }
552
553    public String[] getTetherableIfaces() {
554        throw new RuntimeException("not implemented");
555    }
556
557    public String[] getTetheredIfaces() {
558        throw new RuntimeException("not implemented");
559    }
560
561    public String[] getTetheringErroredIfaces() {
562        throw new RuntimeException("not implemented");
563    }
564
565    public String[] getTetheredDhcpRanges() {
566        throw new RuntimeException("not implemented");
567    }
568
569    @Override
570    public boolean isTetheringSupported() {
571        throw new RuntimeException("not implemented");
572    }
573
574    @Override
575    public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
576        throw new RuntimeException("not implemented");
577    }
578
579    @Override
580    public void stopTethering(int type) {
581        throw new RuntimeException("not implemented");
582    }
583
584
585    public void reportInetCondition(int networkType, int percentage) {
586        throw new RuntimeException("not implemented");
587    }
588
589    public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
590        throw new RuntimeException("not implemented");
591    }
592
593    public ProxyInfo getProxyForNetwork(Network network) {
594        throw new RuntimeException("not implemented");
595    }
596
597    public void setGlobalProxy(ProxyInfo proxyProperties) {
598        throw new RuntimeException("not implemented");
599    }
600
601    public ProxyInfo getGlobalProxy() {
602        throw new RuntimeException("not implemented");
603    }
604
605    @Override
606    public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
607            int userId) {
608        throw new RuntimeException("not implemented");
609    }
610
611    public void setVpnPackageAuthorization(String packageName, int userId, boolean authorized) {
612        throw new RuntimeException("not implemented");
613    }
614
615    @Override
616    public ParcelFileDescriptor establishVpn(VpnConfig config) {
617        throw new RuntimeException("not implemented");
618    }
619
620    @Override
621    public void startLegacyVpn(VpnProfile profile) {
622        throw new RuntimeException("not implemented");
623    }
624
625    @Override
626    public LegacyVpnInfo getLegacyVpnInfo(int userId) {
627        throw new RuntimeException("not implemented");
628    }
629
630    @Override
631    public VpnInfo[] getAllVpnInfo() {
632        throw new RuntimeException("not implemented");
633    }
634
635    @Override
636    public VpnConfig getVpnConfig(int userId) {
637        throw new RuntimeException("not implemented");
638    }
639
640    @Override
641    public boolean updateLockdownVpn() {
642        throw new RuntimeException("not implemented");
643    }
644
645    @Override
646    public boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdownEnabled) {
647        throw new RuntimeException("not implemented");
648    }
649
650    @Override
651    public String getAlwaysOnVpnPackage(int userId) {
652        throw new RuntimeException("not implemented");
653    }
654
655    @Override
656    public int checkMobileProvisioning(int suggestedTimeOutMs) {
657        throw new RuntimeException("not implemented");
658    }
659
660    @Override
661    public String getMobileProvisioningUrl() {
662        throw new RuntimeException("not implemented");
663    }
664
665    @Override
666    public void setProvisioningNotificationVisible(boolean visible, int networkType,
667            String action) {
668        throw new RuntimeException("not implemented");
669    }
670
671    @Override
672    public void setAirplaneMode(boolean enable) {
673        throw new RuntimeException("not implemented");
674    }
675
676    @Override
677    public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
678            Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
679        networkCapabilities = new NetworkCapabilities(networkCapabilities);
680
681        if (timeoutMs < 0) {
682            throw new IllegalArgumentException("Bad timeout specified");
683        }
684
685        NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
686                nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
687        NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder, true);
688        if (DBG) log("requestNetwork for " + nri);
689
690        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
691
692        return networkRequest;
693    }
694
695    @Override
696    public boolean requestBandwidthUpdate(Network network) {
697        throw new RuntimeException("not implemented");
698    }
699
700
701    @Override
702    public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
703            PendingIntent operation) {
704        throw new RuntimeException("not implemented");
705    }
706
707    @Override
708    public void releasePendingNetworkRequest(PendingIntent operation) {
709        throw new RuntimeException("not implemented");
710    }
711
712    @Override
713    public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
714            Messenger messenger, IBinder binder) {
715        throw new RuntimeException("not implemented");
716    }
717
718    @Override
719    public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
720            PendingIntent operation) {
721        throw new RuntimeException("not implemented");
722    }
723
724    @Override
725    public void releaseNetworkRequest(NetworkRequest networkRequest) {
726        mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(),
727                0, networkRequest));
728    }
729
730    @Override
731    public void registerNetworkFactory(Messenger messenger, String name) {
732        NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
733        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
734    }
735
736    private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
737        if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
738        mNetworkFactoryInfos.put(nfi.messenger, nfi);
739        nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
740    }
741
742    @Override
743    public void unregisterNetworkFactory(Messenger messenger) {
744        mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
745    }
746
747    private void handleUnregisterNetworkFactory(Messenger messenger) {
748        NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
749        if (nfi == null) {
750            loge("Failed to find Messenger in unregisterNetworkFactory");
751            return;
752        }
753        if (DBG) log("unregisterNetworkFactory for " + nfi.name);
754    }
755
756    public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
757            LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
758            int currentScore, NetworkMisc networkMisc) {
759//        final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
760//                new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(
761//                linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,
762//                mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
763//        synchronized (this) {
764//            nai.networkMonitor.systemReady = mSystemReady;
765//        }
766//        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
767//        return nai.network.netId;
768        throw new RuntimeException("not implemented");
769    }
770
771    private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
772        if (VDBG) log("Got NetworkAgent Messenger");
773//        mNetworkAgentInfos.put(na.messenger, na);
774//        synchronized (mNetworkForNetId) {
775//            mNetworkForNetId.put(na.network.netId, na);
776//        }
777//        na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
778//        NetworkInfo networkInfo = na.networkInfo;
779//        na.networkInfo = null;
780//        updateNetworkInfo(na, networkInfo);
781    }
782
783
784    private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
785        mNetworkRequests.put(nri.request, nri);
786        if (!nri.isRequest) {
787            for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
788                if (nri.request.networkCapabilities.hasSignalStrength() &&
789                        network.satisfiesImmutableCapabilitiesOf(nri.request)) {
790                }
791            }
792        }
793        rematchAllNetworksAndRequests(null, 0);
794        if (nri.isRequest) {
795            sendUpdatedScoreToFactories(nri.request, 0);
796        }
797    }
798
799    private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
800        NetworkRequestInfo nri = mNetworkRequests.get(request);
801        if (nri != null) {
802            if (DBG) log("releasing NetworkRequest " + request);
803            nri.unlinkDeathRecipient();
804            mNetworkRequests.remove(request);
805            if (nri.isRequest) {
806                // Find all networks that are satisfying this request and remove the request
807                // from their request lists.
808                // TODO - it's my understanding that for a request there is only a single
809                // network satisfying it, so this loop is wasteful
810                //boolean wasKept = false;
811                //for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
812                //    if (nai.networkRequests.get(nri.request.requestId) != null) {
813                //        nai.networkRequests.remove(nri.request.requestId);
814                //        if (DBG) {
815                //            log(" Removing from current network " + nai.name() +
816                //                    ", leaving " + nai.networkRequests.size() +
817                //                    " requests.");
818                //        }
819                //        if (unneeded(nai)) {
820                //            if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
821                //            teardownUnneededNetwork(nai);
822                //        } else {
823                //            // suspect there should only be one pass through here
824                //            // but if any were kept do the check below
825                //            wasKept |= true;
826                //        }
827                //    }
828                //}
829
830                //NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
831                //if (nai != null) {
832                //    mNetworkForRequestId.remove(nri.request.requestId);
833                //}
834                // Maintain the illusion.  When this request arrived, we might have pretended
835                // that a network connected to serve it, even though the network was already
836                // connected.  Now that this request has gone away, we might have to pretend
837                // that the network disconnected.  LegacyTypeTracker will generate that
838                // phantom disconnect for this type.
839                //if (nri.request.legacyType != TYPE_NONE && nai != null) {
840                //    boolean doRemove = true;
841                //    if (wasKept) {
842                //        // check if any of the remaining requests for this network are for the
843                //        // same legacy type - if so, don't remove the nai
844                //        for (int i = 0; i < nai.networkRequests.size(); i++) {
845                //            NetworkRequest otherRequest = nai.networkRequests.valueAt(i);
846                //            if (otherRequest.legacyType == nri.request.legacyType &&
847                //                    isRequest(otherRequest)) {
848                //                if (DBG) log(" still have other legacy request - leaving");
849                //                doRemove = false;
850                //            }
851                //        }
852                //    }
853                //
854                //    if (doRemove) {
855                //        mLegacyTypeTracker.remove(nri.request.legacyType, nai, false);
856                //    }
857                //}
858
859                for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
860                    nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
861                            nri.request);
862                }
863            } else {
864                // listens don't have a singular affectedNetwork.  Check all networks to see
865                // if this listen request applies and remove it.
866                //for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
867                //    nai.networkRequests.remove(nri.request.requestId);
868                //    if (nri.request.networkCapabilities.hasSignalStrength() &&
869                //            nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
870                //        updateSignalStrengthThresholds(nai, "RELEASE", nri.request);
871                //    }
872                //}
873            }
874            //callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED);
875        }
876    }
877
878    private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {
879        for (int i = 0; i < nai.numNetworkRequests(); i++) {
880            NetworkRequest nr = nai.requestAt(i);
881            // Don't send listening requests to factories. b/17393458
882            if (!isRequest(nr)) continue;
883                sendUpdatedScoreToFactories(nr, nai.getCurrentScore());
884        }
885    }
886
887    private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
888        if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
889        for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
890            nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,
891                    networkRequest);
892        }
893    }
894
895    private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
896    }
897
898    @Override
899    public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
900            String resultData, Bundle resultExtras) {
901        throw new RuntimeException("not implemented");
902    }
903
904    @Override
905    public boolean addVpnAddress(String address, int prefixLength) {
906        throw new RuntimeException("not implemented");
907    }
908
909    @Override
910    public boolean removeVpnAddress(String address, int prefixLength) {
911        throw new RuntimeException("not implemented");
912    }
913
914    @Override
915    public boolean setUnderlyingNetworksForVpn(Network[] networks) {
916        throw new RuntimeException("not implemented");
917    }
918
919    @Override
920    public String getCaptivePortalServerUrl() {
921        throw new RuntimeException("not implemented");
922    }
923
924    @Override
925    public void startNattKeepalive(Network network, int intervalSeconds, Messenger messenger,
926            IBinder binder, String srcAddr, int srcPort, String dstAddr) {
927        throw new RuntimeException("not implemented");
928    }
929
930    @Override
931    public void stopKeepalive(Network network, int slot) {
932        throw new RuntimeException("not implemented");
933    }
934
935    @Override
936    public void factoryReset() {
937        throw new RuntimeException("not implemented");
938    }
939
940    @VisibleForTesting
941    public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
942            NetworkAgentInfo nai, NetworkRequest defaultRequest) {
943        throw new RuntimeException("not implemented");
944    }
945
946    @VisibleForTesting
947    public NetworkRequest defaultRequest = null;
948    @VisibleForTesting
949    public synchronized void addDefaultRequest() {
950        if (defaultRequest != null) return;
951        NetworkCapabilities netCap = new NetworkCapabilities();
952        netCap.addCapability(NET_CAPABILITY_INTERNET);
953        netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
954        defaultRequest = requestNetwork(netCap, null, 0, new Binder(),
955                ConnectivityManager.TYPE_NONE);
956    }
957
958    @VisibleForTesting
959    public synchronized void setCurrentScoreForRequest(NetworkRequest nr, int score) {
960        sendUpdatedScoreToFactories(nr, score);
961    }
962
963    @VisibleForTesting
964    public synchronized void removeDefaultRequest() {
965        if (defaultRequest == null) return;
966        releaseNetworkRequest(defaultRequest);
967        defaultRequest = null;
968    }
969
970
971}
972