blob: 573a8f873d67a14f730d8aa351c141847043d9f9 [file] [log] [blame]
Hui Lu1c5624a2014-01-15 11:05:36 -05001/*
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 android.net;
18
Hui Lua24bec32014-02-06 14:02:26 -050019import android.content.BroadcastReceiver;
20import android.content.ComponentName;
Hui Lu1c5624a2014-01-15 11:05:36 -050021import android.content.Context;
Hui Lua24bec32014-02-06 14:02:26 -050022import android.content.Intent;
23import android.content.IntentFilter;
24import android.content.ServiceConnection;
25import android.os.Bundle;
Hui Lu1c5624a2014-01-15 11:05:36 -050026import android.os.Handler;
Hui Lua24bec32014-02-06 14:02:26 -050027import android.os.IBinder;
Hui Lu1c5624a2014-01-15 11:05:36 -050028import android.os.Message;
Hui Lua24bec32014-02-06 14:02:26 -050029import android.os.Messenger;
30import android.os.RemoteException;
31import android.os.UserHandle;
Hui Lu1c5624a2014-01-15 11:05:36 -050032import android.util.Log;
33
34import java.net.InetAddress;
35import java.net.UnknownHostException;
Hui Lua24bec32014-02-06 14:02:26 -050036import java.util.concurrent.atomic.AtomicBoolean;
Hui Lu1c5624a2014-01-15 11:05:36 -050037import java.util.concurrent.atomic.AtomicInteger;
38
39/**
40 * A data tracker responsible for bringing up and tearing down the system proxy server.
41 *
42 * {@hide}
43 */
44public class ProxyDataTracker extends BaseNetworkStateTracker {
Hui Lu1c5624a2014-01-15 11:05:36 -050045 private static final String TAG = "ProxyDataTracker";
Hui Lua24bec32014-02-06 14:02:26 -050046 private static final String NETWORK_TYPE = "PROXY";
Hui Lu1c5624a2014-01-15 11:05:36 -050047
48 // TODO: investigate how to get these DNS addresses from the system.
49 private static final String DNS1 = "8.8.8.8";
50 private static final String DNS2 = "8.8.4.4";
51 private static final String REASON_ENABLED = "enabled";
Hui Lua24bec32014-02-06 14:02:26 -050052 private static final String REASON_DISABLED = "disabled";
53 private static final String REASON_PROXY_DOWN = "proxy_down";
Hui Lu1c5624a2014-01-15 11:05:36 -050054
Hui Lua24bec32014-02-06 14:02:26 -050055 private static final int MSG_TEAR_DOWN_REQUEST = 1;
56 private static final int MSG_SETUP_REQUEST = 2;
57
58 private static final String PERMISSION_PROXY_STATUS_SENDER =
59 "android.permission.ACCESS_NETWORK_CONDITIONS";
60 private static final String ACTION_PROXY_STATUS_CHANGE =
61 "com.android.net.PROXY_STATUS_CHANGE";
62 private static final String KEY_IS_PROXY_AVAILABLE = "is_proxy_available";
63 private static final String KEY_REPLY_TO_MESSENGER_BINDER = "reply_to_messenger_binder";
64 private static final String KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE =
65 "reply_to_messenger_binder_bundle";
66
67 private Handler mTarget;
68 private Messenger mProxyStatusService;
69 private AtomicBoolean mReconnectRequested = new AtomicBoolean(false);
70 private AtomicBoolean mIsProxyAvailable = new AtomicBoolean(false);
Hui Lu1c5624a2014-01-15 11:05:36 -050071 private final AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
Hui Lua24bec32014-02-06 14:02:26 -050072
73 private final BroadcastReceiver mProxyStatusServiceListener = new BroadcastReceiver() {
74 @Override
75 public void onReceive(Context context, Intent intent) {
76 if (intent.getAction().equals(ACTION_PROXY_STATUS_CHANGE)) {
77 mIsProxyAvailable.set(intent.getBooleanExtra(KEY_IS_PROXY_AVAILABLE, false));
78 if (mIsProxyAvailable.get()) {
79 Bundle bundle = intent.getBundleExtra(KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE);
80 if (bundle == null || bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER) == null) {
81 Log.e(TAG, "no messenger binder in the intent to send future requests");
82 mIsProxyAvailable.set(false);
83 return;
84 }
85 mProxyStatusService =
86 new Messenger(bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER));
87 // If there is a pending reconnect request, do it now.
88 if (mReconnectRequested.get()) {
89 reconnect();
90 }
91 } else {
92 setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
93 REASON_PROXY_DOWN, null);
94 }
95 } else {
96 Log.d(TAG, "Unrecognized broadcast intent");
97 }
98 }
99 };
Hui Lu1c5624a2014-01-15 11:05:36 -0500100
101 /**
102 * Create a new ProxyDataTracker
103 */
104 public ProxyDataTracker() {
105 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_PROXY, 0, NETWORK_TYPE, "");
Hui Lu1c5624a2014-01-15 11:05:36 -0500106 mLinkProperties = new LinkProperties();
Robert Greenwaltf9cb86a2014-04-08 17:34:00 -0700107 mNetworkCapabilities = new NetworkCapabilities();
Hui Lua24bec32014-02-06 14:02:26 -0500108 mNetworkInfo.setIsAvailable(true);
Hui Lu1c5624a2014-01-15 11:05:36 -0500109 try {
Robert Greenwalt25702b32014-06-06 10:30:11 -0700110 mLinkProperties.addDnsServer(InetAddress.getByName(DNS1));
111 mLinkProperties.addDnsServer(InetAddress.getByName(DNS2));
Hui Lu1c5624a2014-01-15 11:05:36 -0500112 } catch (UnknownHostException e) {
113 Log.e(TAG, "Could not add DNS address", e);
114 }
115 }
116
117 public Object Clone() throws CloneNotSupportedException {
118 throw new CloneNotSupportedException();
119 }
120
Hui Lua24bec32014-02-06 14:02:26 -0500121 @Override
122 public void startMonitoring(Context context, Handler target) {
123 mContext = context;
124 mTarget = target;
125 mContext.registerReceiver(mProxyStatusServiceListener,
126 new IntentFilter(ACTION_PROXY_STATUS_CHANGE),
127 PERMISSION_PROXY_STATUS_SENDER,
128 null);
129 }
130
Hui Lu1c5624a2014-01-15 11:05:36 -0500131 /**
132 * Disable connectivity to the network.
133 */
134 public boolean teardown() {
Hui Lua24bec32014-02-06 14:02:26 -0500135 setTeardownRequested(true);
136 mReconnectRequested.set(false);
137 try {
138 if (mIsProxyAvailable.get() && mProxyStatusService != null) {
139 mProxyStatusService.send(Message.obtain(null, MSG_TEAR_DOWN_REQUEST));
140 }
141 } catch (RemoteException e) {
142 Log.e(TAG, "Unable to connect to proxy status service", e);
143 return false;
144 }
145 setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_DISABLED, null);
Hui Lu1c5624a2014-01-15 11:05:36 -0500146 return true;
147 }
148
149 /**
150 * Re-enable proxy data connectivity after a {@link #teardown()}.
151 */
152 public boolean reconnect() {
Hui Lua24bec32014-02-06 14:02:26 -0500153 mReconnectRequested.set(true);
154 setTeardownRequested(false);
155 if (!mIsProxyAvailable.get()) {
156 Log.w(TAG, "Reconnect requested even though proxy service is not up. Bailing.");
Hui Lu1c5624a2014-01-15 11:05:36 -0500157 return false;
158 }
Hui Lua24bec32014-02-06 14:02:26 -0500159 setDetailedState(NetworkInfo.DetailedState.CONNECTING, REASON_ENABLED, null);
Hui Lu1c5624a2014-01-15 11:05:36 -0500160
Hui Lua24bec32014-02-06 14:02:26 -0500161 try {
162 mProxyStatusService.send(Message.obtain(null, MSG_SETUP_REQUEST));
163 } catch (RemoteException e) {
164 Log.e(TAG, "Unable to connect to proxy status service", e);
165 setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_PROXY_DOWN, null);
166 return false;
167 }
168 // We'll assume proxy is set up successfully. If not, a status change broadcast will be
169 // received afterwards to indicate any failure.
170 setDetailedState(NetworkInfo.DetailedState.CONNECTED, REASON_ENABLED, null);
Hui Lu1c5624a2014-01-15 11:05:36 -0500171 return true;
172 }
173
174 /**
175 * Fetch default gateway address for the network
176 */
177 public int getDefaultGatewayAddr() {
178 return mDefaultGatewayAddr.get();
179 }
180
181 /**
182 * Return the system properties name associated with the tcp buffer sizes
183 * for this network.
184 */
185 public String getTcpBufferSizesPropName() {
186 return "net.tcp.buffersize.wifi";
187 }
188
189 /**
190 * Record the detailed state of a network, and if it is a
191 * change from the previous state, send a notification to
192 * any listeners.
193 * @param state the new @{code DetailedState}
194 * @param reason a {@code String} indicating a reason for the state change,
195 * if one was supplied. May be {@code null}.
196 * @param extraInfo optional {@code String} providing extra information about the state change
197 */
198 private void setDetailedState(NetworkInfo.DetailedState state, String reason,
199 String extraInfo) {
200 mNetworkInfo.setDetailedState(state, reason, extraInfo);
Hui Lua24bec32014-02-06 14:02:26 -0500201 Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
Hui Lu1c5624a2014-01-15 11:05:36 -0500202 msg.sendToTarget();
203 }
204}