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