NetlinkTracker.java revision 10accbb46e82b3178ff26124041f3ab7d6c1802d
1/*
2 * Copyright (C) 2014 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.server.net;
18
19import android.net.LinkAddress;
20import android.net.LinkProperties;
21import android.util.Log;
22
23/**
24 * Keeps track of link configuration received from Netlink.
25 *
26 * Instances of this class are expected to be owned by subsystems such as Wi-Fi
27 * or Ethernet that manage one or more network interfaces. Each interface to be
28 * tracked needs its own {@code NetlinkTracker}.
29 *
30 * An instance of this class is constructed by passing in an interface name and
31 * a callback. The owner is then responsible for registering the tracker with
32 * NetworkManagementService. When the class receives update notifications from
33 * the NetworkManagementService notification threads, it applies the update to
34 * its local LinkProperties, and if something has changed, notifies its owner of
35 * the update via the callback.
36 *
37 * The owner can then call {@code getLinkProperties()} in order to find out
38 * what changed. If in the meantime the LinkProperties stored here have changed,
39 * this class will return the current LinkProperties. Because each change
40 * triggers an update callback after the change is made, the owner may get more
41 * callbacks than strictly necessary (some of which may be no-ops), but will not
42 * be out of sync once all callbacks have been processed.
43 *
44 * Threading model:
45 *
46 * - The owner of this class is expected to create it, register it, and call
47 *   getLinkProperties or clearLinkProperties on its thread.
48 * - Most of the methods in the class are inherited from BaseNetworkObserver
49 *   and are called by NetworkManagementService notification threads.
50 * - All accesses to mLinkProperties must be synchronized(this). All the other
51 *   member variables are immutable once the object is constructed.
52 *
53 * This class currently tracks IPv4 and IPv6 addresses. In the future it will
54 * track routes and DNS servers.
55 *
56 * @hide
57 */
58public class NetlinkTracker extends BaseNetworkObserver {
59
60    private final String TAG;
61
62    public interface Callback {
63        public void update();
64    }
65
66    private final String mInterfaceName;
67    private final Callback mCallback;
68    private final LinkProperties mLinkProperties;
69
70    private static final boolean DBG = true;
71
72    public NetlinkTracker(String iface, Callback callback) {
73        TAG = "NetlinkTracker/" + iface;
74        mInterfaceName = iface;
75        mCallback = callback;
76        mLinkProperties = new LinkProperties();
77        mLinkProperties.setInterfaceName(mInterfaceName);
78    }
79
80    private void maybeLog(String operation, String iface, LinkAddress address) {
81        if (DBG) {
82            Log.d(TAG, operation + ": " + address + " on " + iface +
83                    " flags " + address.getFlags() + " scope " + address.getScope());
84        }
85    }
86
87    @Override
88    public void addressUpdated(String iface, LinkAddress address) {
89        if (mInterfaceName.equals(iface)) {
90            maybeLog("addressUpdated", iface, address);
91            boolean changed;
92            synchronized (this) {
93                changed = mLinkProperties.addLinkAddress(address);
94            }
95            if (changed) {
96                mCallback.update();
97            }
98        }
99    }
100
101    @Override
102    public void addressRemoved(String iface, LinkAddress address) {
103        if (mInterfaceName.equals(iface)) {
104            maybeLog("addressRemoved", iface, address);
105            boolean changed;
106            synchronized (this) {
107                changed = mLinkProperties.removeLinkAddress(address);
108            }
109            if (changed) {
110                mCallback.update();
111            }
112        }
113    }
114
115    /**
116     * Returns a copy of this object's LinkProperties.
117     */
118    public synchronized LinkProperties getLinkProperties() {
119        return new LinkProperties(mLinkProperties);
120    }
121
122    public synchronized void clearLinkProperties() {
123        mLinkProperties.clear();
124        mLinkProperties.setInterfaceName(mInterfaceName);
125    }
126}
127