mTrackingInterfaces =
59 | new ConcurrentHashMap<>();
60 | private final Handler mHandler;
61 | private final Context mContext;
62 |
63 | public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) {
64 | super(handler.getLooper(), context, NETWORK_TYPE, filter);
65 |
66 | if (DBG) {
67 | Log.d(TAG, "EthernetNetworkFactory new");
68 | }
69 | mHandler = handler;
70 | mContext = context;
71 |
72 | setScoreFilter(NETWORK_SCORE);
73 | }
74 |
75 | @Override
76 | public boolean acceptRequest(NetworkRequest request, int score) {
77 | if (DBG) {
78 | Log.d(TAG, "acceptRequest, request: " + request + ", score: " + score);
79 | }
80 |
81 | return networkForRequest(request) != null;
82 | }
83 |
84 | @Override
85 | protected void needNetworkFor(NetworkRequest networkRequest, int score) {
86 | NetworkInterfaceState network = networkForRequest(networkRequest);
87 |
88 | if (network == null) {
89 | Log.e(TAG, "needNetworkFor, failed to get a network for start" + networkRequest);
90 | return;
91 | }
92 |
93 | if (++network.refCount == 1) {
94 | Log.d(TAG, "+needNetworkFor, " + networkRequest);
95 |
96 | network.start();
97 | }
98 | }
99 |
100 | @Override
101 | protected void releaseNetworkFor(NetworkRequest networkRequest) {
102 | NetworkInterfaceState network = networkForRequest(networkRequest);
103 | if (network == null) {
104 | Log.e(TAG, "needNetworkFor, failed to get a network for stop" + networkRequest);
105 | return;
106 | }
107 |
108 | if (--network.refCount == 1) {
109 | Log.d(TAG, "-needNetworkFor, " + networkRequest);
110 | network.stop();
111 | }
112 | }
113 |
114 | /**
115 | * Returns an array of available interface names. The array is sorted: unrestricted interfaces
116 | * goes first, then sorted by name.
117 | */
118 | String[] getAvailableInterfaces(boolean includeRestricted) {
119 | return mTrackingInterfaces.values()
120 | .stream()
121 | .filter(iface -> !iface.isRestricted() || includeRestricted)
122 | .sorted((iface1, iface2) -> {
123 | int r = Boolean.compare(iface1.isRestricted(), iface2.isRestricted());
124 | return r == 0 ? iface1.name.compareTo(iface2.name) : r;
125 | })
126 | .map(iface -> iface.name)
127 | .toArray(String[]::new);
128 | }
129 |
130 | void addInterface(String ifaceName, String hwAddress, NetworkCapabilities capabilities,
131 | IpConfiguration ipConfiguration) {
132 | if (mTrackingInterfaces.containsKey(ifaceName)) {
133 | Log.e(TAG, "Interface with name " + ifaceName + " already exists.");
134 | return;
135 | }
136 |
137 | if (DBG) {
138 | Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities);
139 | }
140 |
141 | NetworkInterfaceState iface = new NetworkInterfaceState(
142 | ifaceName, hwAddress, mHandler, mContext, capabilities);
143 | iface.setIpConfig(ipConfiguration);
144 | mTrackingInterfaces.put(ifaceName, iface);
145 |
146 | updateCapabilityFilter();
147 | }
148 |
149 | private void updateCapabilityFilter() {
150 | NetworkCapabilities capabilitiesFilter = new NetworkCapabilities();
151 | capabilitiesFilter.clearAll();
152 |
153 | for (NetworkInterfaceState iface: mTrackingInterfaces.values()) {
154 | capabilitiesFilter.combineCapabilities(iface.mCapabilities);
155 | }
156 |
157 | if (DBG) Log.d(TAG, "updateCapabilityFilter: " + capabilitiesFilter);
158 | setCapabilityFilter(capabilitiesFilter);
159 | }
160 |
161 | void removeInterface(String interfaceName) {
162 | NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName);
163 | if (DBG) {
164 | Log.d(TAG, "removeInterface iface=" + iface + " interfaceName=" + interfaceName);
165 | }
166 | if (iface != null) {
167 | iface.stop();
168 | }
169 |
170 | updateCapabilityFilter();
171 | }
172 |
173 | /** Returns true if state has been modified */
174 | boolean updateInterfaceLinkState(String ifaceName, boolean up) {
175 | if (!mTrackingInterfaces.containsKey(ifaceName)) {
176 | return false;
177 | }
178 |
179 | if (DBG) {
180 | Log.d(TAG, "updateInterfaceLinkState, iface: " + ifaceName + ", up: " + up);
181 | }
182 |
183 | NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName);
184 | return iface.updateLinkState(up);
185 | }
186 |
187 | boolean hasInterface(String interfacName) {
188 | return mTrackingInterfaces.containsKey(interfacName);
189 | }
190 |
191 | void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) {
192 | NetworkInterfaceState network = mTrackingInterfaces.get(iface);
193 | if (network != null) {
194 | network.setIpConfig(ipConfiguration);
195 | }
196 | }
197 |
198 | private NetworkInterfaceState networkForRequest(NetworkRequest request) {
199 | String requestedIface = null;
200 |
201 | NetworkSpecifier specifier = request.networkCapabilities.getNetworkSpecifier();
202 | if (specifier instanceof StringNetworkSpecifier) {
203 | requestedIface = ((StringNetworkSpecifier) specifier).specifier;
204 | }
205 |
206 | NetworkInterfaceState network = null;
207 | if (!TextUtils.isEmpty(requestedIface)) {
208 | NetworkInterfaceState n = mTrackingInterfaces.get(requestedIface);
209 | if (n != null && n.statisified(request.networkCapabilities)) {
210 | network = n;
211 | }
212 | } else {
213 | for (NetworkInterfaceState n : mTrackingInterfaces.values()) {
214 | if (n.statisified(request.networkCapabilities)) {
215 | network = n;
216 | break;
217 | }
218 | }
219 | }
220 |
221 | if (DBG) {
222 | Log.i(TAG, "networkForRequest, request: " + request + ", network: " + network);
223 | }
224 |
225 | return network;
226 | }
227 |
228 | private static class NetworkInterfaceState {
229 | final String name;
230 |
231 | private final String mHwAddress;
232 | private final NetworkCapabilities mCapabilities;
233 | private final Handler mHandler;
234 | private final Context mContext;
235 | private final NetworkInfo mNetworkInfo;
236 |
237 | private static String sTcpBufferSizes = null; // Lazy initialized.
238 |
239 | private boolean mLinkUp;
240 | private LinkProperties mLinkProperties = new LinkProperties();
241 |
242 | private IpClient mIpClient;
243 | private NetworkAgent mNetworkAgent;
244 | private IpConfiguration mIpConfig;
245 |
246 | long refCount = 0;
247 |
248 | private final IpClient.Callback mIpClientCallback = new IpClient.Callback() {
249 | @Override
250 | public void onProvisioningSuccess(LinkProperties newLp) {
251 | mHandler.post(() -> onIpLayerStarted(newLp));
252 | }
253 |
254 | @Override
255 | public void onProvisioningFailure(LinkProperties newLp) {
256 | mHandler.post(() -> onIpLayerStopped(newLp));
257 | }
258 |
259 | @Override
260 | public void onLinkPropertiesChange(LinkProperties newLp) {
261 | mHandler.post(() -> updateLinkProperties(newLp));
262 | }
263 | };
264 |
265 | NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context,
266 | NetworkCapabilities capabilities) {
267 | name = ifaceName;
268 | mCapabilities = capabilities;
269 | mHandler = handler;
270 | mContext = context;
271 |
272 | mHwAddress = hwAddress;
273 | mNetworkInfo = new NetworkInfo(TYPE_ETHERNET, 0, NETWORK_TYPE, "");
274 | mNetworkInfo.setExtraInfo(mHwAddress);
275 | mNetworkInfo.setIsAvailable(true);
276 | }
277 |
278 | void setIpConfig(IpConfiguration ipConfig) {
279 |
280 | this.mIpConfig = ipConfig;
281 | }
282 |
283 | boolean statisified(NetworkCapabilities requestedCapabilities) {
284 | return requestedCapabilities.satisfiedByNetworkCapabilities(mCapabilities);
285 | }
286 |
287 | boolean isRestricted() {
288 | return mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
289 | }
290 |
291 | private void start() {
292 | if (mIpClient != null) {
293 | if (DBG) Log.d(TAG, "IpClient already started");
294 | return;
295 | }
296 | if (DBG) {
297 | Log.d(TAG, String.format("starting IpClient(%s): mNetworkInfo=%s", name,
298 | mNetworkInfo));
299 | }
300 |
301 | mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddress);
302 |
303 | mIpClient = new IpClient(mContext, name, mIpClientCallback);
304 |
305 | if (sTcpBufferSizes == null) {
306 | sTcpBufferSizes = mContext.getResources().getString(
307 | com.android.internal.R.string.config_ethernet_tcp_buffers);
308 | }
309 |
310 | provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes);
311 |
312 | }
313 |
314 | void onIpLayerStarted(LinkProperties linkProperties) {
315 | if (mNetworkAgent != null) {
316 | Log.e(TAG, "Already have a NetworkAgent - aborting new request");
317 | stop();
318 | return;
319 | }
320 | mLinkProperties = linkProperties;
321 | mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddress);
322 | mNetworkInfo.setIsAvailable(true);
323 |
324 | // Create our NetworkAgent.
325 | mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext,
326 | NETWORK_TYPE, mNetworkInfo, mCapabilities, mLinkProperties,
327 | NETWORK_SCORE) {
328 | public void unwanted() {
329 | if (this == mNetworkAgent) {
330 | stop();
331 | } else if (mNetworkAgent != null) {
332 | Log.d(TAG, "Ignoring unwanted as we have a more modern " +
333 | "instance");
334 | } // Otherwise, we've already called stop.
335 | }
336 | };
337 | }
338 |
339 | void onIpLayerStopped(LinkProperties linkProperties) {
340 | // This cannot happen due to provisioning timeout, because our timeout is 0. It can only
341 | // happen if we're provisioned and we lose provisioning.
342 | Log.e(TAG, "onIpLayerStopped");
343 | stop();
344 | start();
345 | }
346 |
347 | void updateLinkProperties(LinkProperties linkProperties) {
348 | mLinkProperties = linkProperties;
349 | if (mNetworkAgent != null) {
350 | mNetworkAgent.sendLinkProperties(linkProperties);
351 | }
352 | }
353 |
354 | /** Returns true if state has been modified */
355 | boolean updateLinkState(boolean up) {
356 | if (mLinkUp == up) return false;
357 | mLinkUp = up;
358 |
359 | Log.e(TAG, "updateLinkState");
360 | stop();
361 | if (up) {
362 | start();
363 | }
364 |
365 | return true;
366 | }
367 |
368 | void stop() {
369 | if (mIpClient != null) {
370 | mIpClient.shutdown();
371 | mIpClient.awaitShutdown();
372 | mIpClient = null;
373 | }
374 |
375 | // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object
376 | // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here:
377 | // that sets the state to IDLE, and ConnectivityService will still think we're connected.
378 | //
379 | mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddress);
380 | if (mNetworkAgent != null) {
381 | updateAgent();
382 | mNetworkAgent = null;
383 | }
384 | clear();
385 | }
386 |
387 | private void updateAgent() {
388 | if (mNetworkAgent == null) return;
389 | if (DBG) {
390 | Log.i(TAG, "Updating mNetworkAgent with: " +
391 | mCapabilities + ", " +
392 | mNetworkInfo + ", " +
393 | mLinkProperties);
394 | }
395 | mNetworkAgent.sendNetworkCapabilities(mCapabilities);
396 | mNetworkAgent.sendNetworkInfo(mNetworkInfo);
397 | mNetworkAgent.sendLinkProperties(mLinkProperties);
398 | // never set the network score below 0.
399 | mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0);
400 | }
401 |
402 | private void clear() {
403 | mLinkProperties.clear();
404 | mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null);
405 | mNetworkInfo.setIsAvailable(false);
406 | }
407 |
408 | private static void provisionIpClient(IpClient ipClient, IpConfiguration config,
409 | String tcpBufferSizes) {
410 | if (config.getProxySettings() == ProxySettings.STATIC ||
411 | config.getProxySettings() == ProxySettings.PAC) {
412 | ipClient.setHttpProxy(config.getHttpProxy());
413 | }
414 |
415 | if (!TextUtils.isEmpty(tcpBufferSizes)) {
416 | ipClient.setTcpBufferSizes(tcpBufferSizes);
417 | }
418 |
419 | final ProvisioningConfiguration provisioningConfiguration;
420 | if (config.getIpAssignment() == IpAssignment.STATIC) {
421 | provisioningConfiguration = IpClient.buildProvisioningConfiguration()
422 | .withStaticConfiguration(config.getStaticIpConfiguration())
423 | .build();
424 | } else {
425 | provisioningConfiguration = IpClient.buildProvisioningConfiguration()
426 | .withProvisioningTimeoutMs(0)
427 | .build();
428 | }
429 |
430 | ipClient.startProvisioning(provisioningConfiguration);
431 | }
432 |
433 | @Override
434 | public String toString() {
435 | return getClass().getSimpleName() + "{ "
436 | + "iface: " + name + ", "
437 | + "up: " + mLinkUp + ", "
438 | + "hwAddress: " + mHwAddress + ", "
439 | + "networkInfo: " + mNetworkInfo + ", "
440 | + "networkAgent: " + mNetworkAgent + ", "
441 | + "ipClient: " + mIpClient + ","
442 | + "linkProperties: " + mLinkProperties
443 | + "}";
444 | }
445 | }
446 |
447 | void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
448 | super.dump(fd, pw, args);
449 | pw.println(getClass().getSimpleName());
450 | pw.println("Tracking interfaces:");
451 | pw.increaseIndent();
452 | for (String iface: mTrackingInterfaces.keySet()) {
453 | NetworkInterfaceState ifaceState = mTrackingInterfaces.get(iface);
454 | pw.println(iface + ":" + ifaceState);
455 | pw.increaseIndent();
456 | final IpClient ipClient = ifaceState.mIpClient;
457 | if (ipClient != null) {
458 | ipClient.dump(fd, pw, args);
459 | } else {
460 | pw.println("IpClient is null");
461 | }
462 | pw.decreaseIndent();
463 | }
464 | pw.decreaseIndent();
465 | }
466 | }
467 |
--------------------------------------------------------------------------------
/frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java:
--------------------------------------------------------------------------------
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 |
17 | package com.android.server.ethernet;
18 |
19 | import android.content.Context;
20 | import android.content.pm.PackageManager;
21 | import android.net.EthernetManager;
22 | import android.net.IEthernetManager;
23 | import android.net.IEthernetServiceListener;
24 | import android.net.IpConfiguration;
25 | import android.os.Binder;
26 | import android.os.Handler;
27 | import android.os.HandlerThread;
28 | import android.os.Looper;
29 | import android.os.RemoteException;
30 | import android.util.Log;
31 | import android.util.PrintWriterPrinter;
32 |
33 | import com.android.internal.util.IndentingPrintWriter;
34 |
35 | import java.io.FileDescriptor;
36 | import java.io.PrintWriter;
37 | import java.util.concurrent.atomic.AtomicBoolean;
38 |
39 | import android.net.Uri;
40 | import android.provider.Settings.System;
41 | import android.net.StaticIpConfiguration;
42 | import android.net.LinkAddress;
43 | import java.net.InetAddress;
44 | import android.provider.Settings;
45 | /**
46 | * EthernetServiceImpl handles remote Ethernet operation requests by implementing
47 | * the IEthernetManager interface.
48 | */
49 | public class EthernetServiceImpl extends IEthernetManager.Stub {
50 | private static final String TAG = "EthernetServiceImpl";
51 |
52 | private final Context mContext;
53 | private final AtomicBoolean mStarted = new AtomicBoolean(false);
54 |
55 | private Handler mHandler;
56 | private EthernetTracker mTracker;
57 |
58 | public EthernetServiceImpl(Context context) {
59 | mContext = context;
60 | }
61 |
62 | private void enforceAccessPermission() {
63 | mContext.enforceCallingOrSelfPermission(
64 | android.Manifest.permission.ACCESS_NETWORK_STATE,
65 | "EthernetService");
66 | }
67 |
68 | private void enforceConnectivityInternalPermission() {
69 | mContext.enforceCallingOrSelfPermission(
70 | android.Manifest.permission.CONNECTIVITY_INTERNAL,
71 | "ConnectivityService");
72 | }
73 |
74 | private void enforceUseRestrictedNetworksPermission() {
75 | mContext.enforceCallingOrSelfPermission(
76 | android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS,
77 | "ConnectivityService");
78 | }
79 |
80 | private boolean checkUseRestrictedNetworksPermission() {
81 | return mContext.checkCallingOrSelfPermission(
82 | android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS)
83 | == PackageManager.PERMISSION_GRANTED;
84 | }
85 |
86 | public void start() {
87 | Log.i(TAG, "Starting Ethernet service");
88 |
89 | HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");
90 | handlerThread.start();
91 | mHandler = new Handler(handlerThread.getLooper());
92 |
93 | int enable = Settings.Global.getInt(mContext.getContentResolver(),
94 | Settings.Global.ETHERNET_ON, 0);
95 | if(enable != EthernetManager.ETHERNET_STATE_ENABLED) {
96 | Log.i(TAG, "Ethernet is not enable");
97 | return;
98 | }
99 |
100 | mTracker = new EthernetTracker(mContext, mHandler);
101 | mTracker.start();
102 |
103 | mStarted.set(true);
104 | }
105 | public void trackStart() {
106 | Log.i(TAG, "trackStart");
107 | new Thread(new Runnable() {
108 | public void run() {
109 | Looper.prepare();
110 | if(null == mTracker){
111 | Log.i(TAG, "Starting EthernetTracker");
112 | mTracker = new EthernetTracker(mContext, mHandler);
113 | mTracker.start();
114 | mStarted.set(true);
115 | }else{
116 | mTracker.enable();
117 | }
118 | Looper.loop();
119 | }
120 | }).start();;
121 | }
122 |
123 | public void trackStop() {
124 | Log.i(TAG, "trackStop");
125 | new Thread(new Runnable() {
126 | public void run() {
127 | Looper.prepare();
128 | mTracker.disable();
129 | Looper.loop();
130 | }
131 | }).start();;
132 | }
133 |
134 | @Override
135 | public String[] getAvailableInterfaces() throws RemoteException {
136 | return mTracker.getInterfaces(checkUseRestrictedNetworksPermission());
137 | }
138 |
139 | /**
140 | * Get Ethernet configuration
141 | * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
142 | */
143 | @Override
144 | public IpConfiguration getConfiguration(String iface) {
145 | enforceAccessPermission();
146 |
147 | if (mTracker.isRestrictedInterface(iface)) {
148 | enforceUseRestrictedNetworksPermission();
149 | }
150 |
151 | return new IpConfiguration(mTracker.getIpConfiguration(iface));
152 | }
153 |
154 | /**
155 | * Set Ethernet configuration
156 | */
157 | @Override
158 | public void setConfiguration(String iface, IpConfiguration config) {
159 | if (!mStarted.get()) {
160 | Log.w(TAG, "System isn't ready enough to change ethernet configuration");
161 | }
162 |
163 | enforceConnectivityInternalPermission();
164 |
165 | if (mTracker.isRestrictedInterface(iface)) {
166 | enforceUseRestrictedNetworksPermission();
167 | }
168 |
169 | // TODO: this does not check proxy settings, gateways, etc.
170 | // Fix this by making IpConfiguration a complete representation of static configuration.
171 | mTracker.updateIpConfiguration(iface, new IpConfiguration(config));
172 | }
173 |
174 | /**
175 | * Indicates whether given interface is available.
176 | */
177 | @Override
178 | public boolean isAvailable(String iface) {
179 | enforceAccessPermission();
180 |
181 | if (mTracker.isRestrictedInterface(iface)) {
182 | enforceUseRestrictedNetworksPermission();
183 | }
184 |
185 | return mTracker.isTrackingInterface(iface);
186 | }
187 |
188 | /**
189 | * Adds a listener.
190 | * @param listener A {@link IEthernetServiceListener} to add.
191 | */
192 | public void addListener(IEthernetServiceListener listener) {
193 | if (listener == null) {
194 | throw new IllegalArgumentException("listener must not be null");
195 | }
196 | enforceAccessPermission();
197 | mTracker.addListener(listener, checkUseRestrictedNetworksPermission());
198 | }
199 |
200 | /**
201 | * Removes a listener.
202 | * @param listener A {@link IEthernetServiceListener} to remove.
203 | */
204 | public void removeListener(IEthernetServiceListener listener) {
205 | if (listener == null) {
206 | throw new IllegalArgumentException("listener must not be null");
207 | }
208 | enforceAccessPermission();
209 | mTracker.removeListener(listener);
210 | }
211 |
212 | @Override
213 | protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
214 | final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
215 | if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
216 | != PackageManager.PERMISSION_GRANTED) {
217 | pw.println("Permission Denial: can't dump EthernetService from pid="
218 | + Binder.getCallingPid()
219 | + ", uid=" + Binder.getCallingUid());
220 | return;
221 | }
222 |
223 | pw.println("Current Ethernet state: ");
224 | pw.increaseIndent();
225 | mTracker.dump(fd, pw, args);
226 | pw.decreaseIndent();
227 |
228 | pw.println("Handler:");
229 | pw.increaseIndent();
230 | mHandler.dump(new PrintWriterPrinter(pw), "EthernetServiceImpl");
231 | pw.decreaseIndent();
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 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 |
17 | package com.android.server.ethernet;
18 |
19 | import android.annotation.Nullable;
20 | import android.content.Context;
21 | import android.net.IEthernetServiceListener;
22 | import android.net.InterfaceConfiguration;
23 | import android.net.IpConfiguration;
24 | import android.net.IpConfiguration.IpAssignment;
25 | import android.net.IpConfiguration.ProxySettings;
26 | import android.net.LinkAddress;
27 | import android.net.NetworkCapabilities;
28 | import android.net.StaticIpConfiguration;
29 | import android.os.Handler;
30 | import android.os.IBinder;
31 | import android.os.INetworkManagementService;
32 | import android.os.RemoteCallbackList;
33 | import android.os.RemoteException;
34 | import android.os.ServiceManager;
35 | import android.text.TextUtils;
36 | import android.util.ArrayMap;
37 | import android.util.Log;
38 | import android.provider.Settings;
39 |
40 | import com.android.internal.annotations.VisibleForTesting;
41 | import com.android.internal.util.IndentingPrintWriter;
42 | import com.android.server.net.BaseNetworkObserver;
43 |
44 | import java.io.FileDescriptor;
45 | import java.net.InetAddress;
46 | import java.util.ArrayList;
47 | import java.util.concurrent.ConcurrentHashMap;
48 |
49 | /**
50 | * Tracks Ethernet interfaces and manages interface configurations.
51 | *
52 | * Interfaces may have different {@link android.net.NetworkCapabilities}. This mapping is defined
53 | * in {@code config_ethernet_interfaces}. Notably, some interfaces could be marked as restricted by
54 | * not specifying {@link android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED} flag.
55 | * Interfaces could have associated {@link android.net.IpConfiguration}.
56 | * Ethernet Interfaces may be present at boot time or appear after boot (e.g., for Ethernet adapters
57 | * connected over USB). This class supports multiple interfaces. When an interface appears on the
58 | * system (or is present at boot time) this class will start tracking it and bring it up. Only
59 | * interfaces whose names match the {@code config_ethernet_iface_regex} regular expression are
60 | * tracked.
61 | *
62 | *
All public or package private methods must be thread-safe unless stated otherwise.
63 | */
64 | final class EthernetTracker {
65 | private final static String TAG = EthernetTracker.class.getSimpleName();
66 | private final static boolean DBG = EthernetNetworkFactory.DBG;
67 |
68 | /** Product-dependent regular expression of interface names we track. */
69 | private final String mIfaceMatch;
70 |
71 | /** Mapping between {iface name | mac address} -> {NetworkCapabilities} */
72 | private final ConcurrentHashMap mNetworkCapabilities =
73 | new ConcurrentHashMap<>();
74 | private final ConcurrentHashMap mIpConfigurations =
75 | new ConcurrentHashMap<>();
76 |
77 | private final INetworkManagementService mNMService;
78 | private final Handler mHandler;
79 | private final EthernetNetworkFactory mFactory;
80 | private final EthernetConfigStore mConfigStore;
81 | private InterfaceObserver mInterfaceObserver;
82 | private boolean mEnabled;
83 |
84 | private final RemoteCallbackList mListeners =
85 | new RemoteCallbackList<>();
86 |
87 | private volatile IpConfiguration mIpConfigForDefaultInterface;
88 |
89 | EthernetTracker(Context context, Handler handler) {
90 | if (DBG) {
91 | Log.d(TAG, "EthernetTracker new");
92 | }
93 | mHandler = handler;
94 |
95 | // The services we use.
96 | IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
97 | mNMService = INetworkManagementService.Stub.asInterface(b);
98 |
99 | // Interface match regex.
100 | mIfaceMatch = context.getResources().getString(
101 | com.android.internal.R.string.config_ethernet_iface_regex);
102 |
103 | // Read default Ethernet interface configuration from resources
104 | final String[] interfaceConfigs = context.getResources().getStringArray(
105 | com.android.internal.R.array.config_ethernet_interfaces);
106 | for (String strConfig : interfaceConfigs) {
107 | parseEthernetConfig(strConfig);
108 | }
109 |
110 | mConfigStore = new EthernetConfigStore();
111 |
112 | NetworkCapabilities nc = createNetworkCapabilities(true /* clear default capabilities */);
113 | mFactory = new EthernetNetworkFactory(handler, context, nc);
114 | mFactory.register();
115 | }
116 |
117 | void start() {
118 | if (DBG) {
119 | Log.d(TAG, "EthernetTracker start");
120 | }
121 | mConfigStore.read();
122 |
123 | // Default interface is just the first one we want to track.
124 | mIpConfigForDefaultInterface = mConfigStore.getIpConfigurationForDefaultInterface();
125 | final ArrayMap configs = mConfigStore.getIpConfigurations();
126 | for (int i = 0; i < configs.size(); i++) {
127 | mIpConfigurations.put(configs.keyAt(i), configs.valueAt(i));
128 | }
129 |
130 | mInterfaceObserver = new InterfaceObserver();
131 | try {
132 | mNMService.registerObserver(mInterfaceObserver);
133 | } catch (RemoteException e) {
134 | Log.e(TAG, "Could not register InterfaceObserver " + e);
135 | }
136 |
137 | mEnabled = true;
138 | mHandler.post(this::trackAvailableInterfaces);
139 | }
140 |
141 | void enable(){
142 | if (DBG) {
143 | Log.d(TAG, "EthernetTracker enable");
144 | }
145 |
146 | //mFactory.register();
147 |
148 | mEnabled = true;
149 | mHandler.post(this::trackAvailableInterfaces);
150 | if(isTrackingInterface(Settings.Global.INTERFACE_ETH0)){
151 | updateInterfaceState(Settings.Global.INTERFACE_ETH0,true);
152 | }
153 |
154 | if(isTrackingInterface(Settings.Global.INTERFACE_ETH1)){
155 | updateInterfaceState(Settings.Global.INTERFACE_ETH1,true);
156 | }
157 | }
158 |
159 | void disable(){
160 | if (DBG) {
161 | Log.d(TAG, "EthernetTracker disable");
162 | }
163 | updateInterfaceState(Settings.Global.INTERFACE_ETH0,false);
164 | updateInterfaceState(Settings.Global.INTERFACE_ETH1,false);
165 |
166 | //mFactory.unregister();
167 | mEnabled = false;
168 |
169 | }
170 |
171 | void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) {
172 | if (DBG) {
173 | Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration);
174 | }
175 |
176 | mConfigStore.write(iface, ipConfiguration);
177 | mIpConfigurations.put(iface, ipConfiguration);
178 |
179 | mHandler.post(() -> mFactory.updateIpConfiguration(iface, ipConfiguration));
180 | }
181 |
182 | IpConfiguration getIpConfiguration(String iface) {
183 | return mIpConfigurations.get(iface);
184 | }
185 |
186 | boolean isTrackingInterface(String iface) {
187 | return mFactory.hasInterface(iface);
188 | }
189 |
190 | String[] getInterfaces(boolean includeRestricted) {
191 | return mFactory.getAvailableInterfaces(includeRestricted);
192 | }
193 |
194 | /**
195 | * Returns true if given interface was configured as restricted (doesn't have
196 | * NET_CAPABILITY_NOT_RESTRICTED) capability. Otherwise, returns false.
197 | */
198 | boolean isRestrictedInterface(String iface) {
199 | final NetworkCapabilities nc = mNetworkCapabilities.get(iface);
200 | return nc != null && !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
201 | }
202 |
203 | void addListener(IEthernetServiceListener listener, boolean canUseRestrictedNetworks) {
204 | mListeners.register(listener, new ListenerInfo(canUseRestrictedNetworks));
205 | }
206 |
207 | void removeListener(IEthernetServiceListener listener) {
208 | mListeners.unregister(listener);
209 | }
210 |
211 | private void removeInterface(String iface) {
212 | mFactory.removeInterface(iface);
213 | }
214 |
215 | private void addInterface(String iface) {
216 | InterfaceConfiguration config = null;
217 | // Bring up the interface so we get link status indications.
218 | try {
219 | mNMService.setInterfaceUp(iface);
220 | config = mNMService.getInterfaceConfig(iface);
221 | } catch (RemoteException | IllegalStateException e) {
222 | // Either the system is crashing or the interface has disappeared. Just ignore the
223 | // error; we haven't modified any state because we only do that if our calls succeed.
224 | Log.e(TAG, "Error upping interface " + iface, e);
225 | }
226 |
227 | if (config == null) {
228 | Log.e(TAG, "Null interface config for " + iface + ". Bailing out.");
229 | return;
230 | }
231 |
232 | final String hwAddress = config.getHardwareAddress();
233 |
234 | NetworkCapabilities nc = mNetworkCapabilities.get(iface);
235 | if (nc == null) {
236 | // Try to resolve using mac address
237 | nc = mNetworkCapabilities.get(hwAddress);
238 | if (nc == null) {
239 | nc = createDefaultNetworkCapabilities();
240 | }
241 | }
242 | IpConfiguration ipConfiguration = mIpConfigurations.get(iface);
243 | if (ipConfiguration == null) {
244 | ipConfiguration = createDefaultIpConfiguration();
245 | }
246 |
247 | Log.d(TAG, "Started tracking interface " + iface);
248 | mFactory.addInterface(iface, hwAddress, nc, ipConfiguration);
249 |
250 | if(iface.equals(Settings.Global.INTERFACE_ETH0)){
251 | return;
252 | }
253 |
254 | if(iface.equals(Settings.Global.INTERFACE_ETH1)){
255 | return;
256 | }
257 | // Note: if the interface already has link (e.g., if we crashed and got
258 | // restarted while it was running), we need to fake a link up notification so we
259 | // start configuring it.
260 | if (config.hasFlag("running")) {
261 | updateInterfaceState(iface, true);
262 | }
263 | }
264 |
265 | private void updateInterfaceState(String iface, boolean up) {
266 | if(!mEnabled && up){
267 | return;
268 | }
269 | boolean modified = mFactory.updateInterfaceLinkState(iface, up);
270 | if (modified) {
271 | boolean restricted = isRestrictedInterface(iface);
272 | int n = mListeners.beginBroadcast();
273 | for (int i = 0; i < n; i++) {
274 | try {
275 | if (restricted) {
276 | ListenerInfo listenerInfo = (ListenerInfo) mListeners.getBroadcastCookie(i);
277 | if (!listenerInfo.canUseRestrictedNetworks) {
278 | continue;
279 | }
280 | }
281 | mListeners.getBroadcastItem(i).onAvailabilityChanged(iface, up);
282 | } catch (RemoteException e) {
283 | // Do nothing here.
284 | }
285 | }
286 | mListeners.finishBroadcast();
287 | }
288 | }
289 |
290 | private void maybeTrackInterface(String iface) {
291 | if (DBG) Log.i(TAG, "maybeTrackInterface " + iface);
292 | // If we don't already track this interface, and if this interface matches
293 | // our regex, start tracking it.
294 | if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface)) {
295 | return;
296 | }
297 |
298 | if (mIpConfigForDefaultInterface != null) {
299 | updateIpConfiguration(iface, mIpConfigForDefaultInterface);
300 | mIpConfigForDefaultInterface = null;
301 | }
302 |
303 | addInterface(iface);
304 | }
305 |
306 | private void trackAvailableInterfaces() {
307 | try {
308 | final String[] ifaces = mNMService.listInterfaces();
309 | for (String iface : ifaces) {
310 | maybeTrackInterface(iface);
311 | }
312 | } catch (RemoteException | IllegalStateException e) {
313 | Log.e(TAG, "Could not get list of interfaces " + e);
314 | }
315 | }
316 |
317 |
318 | private class InterfaceObserver extends BaseNetworkObserver {
319 |
320 | @Override
321 | public void interfaceLinkStateChanged(String iface, boolean up) {
322 | if (DBG) {
323 | Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up);
324 | }
325 | mHandler.post(() -> updateInterfaceState(iface, up));
326 | }
327 |
328 | @Override
329 | public void interfaceAdded(String iface) {
330 | mHandler.post(() -> maybeTrackInterface(iface));
331 | }
332 |
333 | @Override
334 | public void interfaceRemoved(String iface) {
335 | mHandler.post(() -> removeInterface(iface));
336 | }
337 | }
338 |
339 | private static class ListenerInfo {
340 |
341 | boolean canUseRestrictedNetworks = false;
342 |
343 | ListenerInfo(boolean canUseRestrictedNetworks) {
344 | this.canUseRestrictedNetworks = canUseRestrictedNetworks;
345 | }
346 | }
347 |
348 | private void parseEthernetConfig(String configString) {
349 | String[] tokens = configString.split(";");
350 | String name = tokens[0];
351 | String capabilities = tokens.length > 1 ? tokens[1] : null;
352 | NetworkCapabilities nc = createNetworkCapabilities(
353 | !TextUtils.isEmpty(capabilities) /* clear default capabilities */, capabilities);
354 | mNetworkCapabilities.put(name, nc);
355 |
356 | if (tokens.length > 2 && !TextUtils.isEmpty(tokens[2])) {
357 | IpConfiguration ipConfig = parseStaticIpConfiguration(tokens[2]);
358 | mIpConfigurations.put(name, ipConfig);
359 | }
360 | }
361 |
362 | private static NetworkCapabilities createDefaultNetworkCapabilities() {
363 | NetworkCapabilities nc = createNetworkCapabilities(false /* clear default capabilities */);
364 | nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
365 | nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
366 | nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
367 | nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
368 | nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
369 |
370 | return nc;
371 | }
372 |
373 | private static NetworkCapabilities createNetworkCapabilities(boolean clearDefaultCapabilities) {
374 | return createNetworkCapabilities(clearDefaultCapabilities, null);
375 | }
376 |
377 | private static NetworkCapabilities createNetworkCapabilities(
378 | boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities) {
379 |
380 | NetworkCapabilities nc = new NetworkCapabilities();
381 | if (clearDefaultCapabilities) {
382 | nc.clearAll(); // Remove default capabilities.
383 | }
384 | nc.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET);
385 | nc.setLinkUpstreamBandwidthKbps(100 * 1000);
386 | nc.setLinkDownstreamBandwidthKbps(100 * 1000);
387 |
388 | if (!TextUtils.isEmpty(commaSeparatedCapabilities)) {
389 | for (String strNetworkCapability : commaSeparatedCapabilities.split(",")) {
390 | if (!TextUtils.isEmpty(strNetworkCapability)) {
391 | nc.addCapability(Integer.valueOf(strNetworkCapability));
392 | }
393 | }
394 | }
395 |
396 | return nc;
397 | }
398 |
399 | /**
400 | * Parses static IP configuration.
401 | *
402 | * @param staticIpConfig represents static IP configuration in the following format: {@code
403 | * ip= gateway= dns=
404 | * domains=}
405 | */
406 | @VisibleForTesting
407 | static IpConfiguration parseStaticIpConfiguration(String staticIpConfig) {
408 | StaticIpConfiguration ipConfig = new StaticIpConfiguration();
409 |
410 | for (String keyValueAsString : staticIpConfig.trim().split(" ")) {
411 | if (TextUtils.isEmpty(keyValueAsString)) continue;
412 |
413 | String[] pair = keyValueAsString.split("=");
414 | if (pair.length != 2) {
415 | throw new IllegalArgumentException("Unexpected token: " + keyValueAsString
416 | + " in " + staticIpConfig);
417 | }
418 |
419 | String key = pair[0];
420 | String value = pair[1];
421 |
422 | switch (key) {
423 | case "ip":
424 | ipConfig.ipAddress = new LinkAddress(value);
425 | break;
426 | case "domains":
427 | ipConfig.domains = value;
428 | break;
429 | case "gateway":
430 | ipConfig.gateway = InetAddress.parseNumericAddress(value);
431 | break;
432 | case "dns": {
433 | ArrayList dnsAddresses = new ArrayList<>();
434 | for (String address: value.split(",")) {
435 | dnsAddresses.add(InetAddress.parseNumericAddress(address));
436 | }
437 | ipConfig.dnsServers.addAll(dnsAddresses);
438 | break;
439 | }
440 | default : {
441 | throw new IllegalArgumentException("Unexpected key: " + key
442 | + " in " + staticIpConfig);
443 | }
444 | }
445 | }
446 | return new IpConfiguration(IpAssignment.STATIC, ProxySettings.NONE, ipConfig, null);
447 | }
448 |
449 | private static IpConfiguration createDefaultIpConfiguration() {
450 | return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null);
451 | }
452 |
453 | private void postAndWaitForRunnable(Runnable r) {
454 | mHandler.runWithScissors(r, 2000L /* timeout */);
455 | }
456 |
457 | void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
458 | postAndWaitForRunnable(() -> {
459 | pw.println(getClass().getSimpleName());
460 | pw.println("Ethernet interface name filter: " + mIfaceMatch);
461 | pw.println("Listeners: " + mListeners.getRegisteredCallbackCount());
462 | pw.println("IP Configurations:");
463 | pw.increaseIndent();
464 | for (String iface : mIpConfigurations.keySet()) {
465 | pw.println(iface + ": " + mIpConfigurations.get(iface));
466 | }
467 | pw.decreaseIndent();
468 | pw.println();
469 |
470 | pw.println("Network Capabilities:");
471 | pw.increaseIndent();
472 | for (String iface : mNetworkCapabilities.keySet()) {
473 | pw.println(iface + ": " + mNetworkCapabilities.get(iface));
474 | }
475 | pw.decreaseIndent();
476 | pw.println();
477 |
478 | mFactory.dump(fd, pw, args);
479 | });
480 | }
481 | }
482 |
--------------------------------------------------------------------------------
/packages/apps/Settings/res/layout/ethernet_configure.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
28 |
29 |
33 |
34 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
58 |
62 |
63 |
69 |
70 |
71 |
77 |
78 |
79 |
80 |
81 |
82 |
88 |
89 |
96 |
97 |
102 |
103 |
110 |
111 |
116 |
117 |
118 |
125 |
126 |
131 |
132 |
139 |
140 |
145 |
146 |
153 |
154 |
159 |
160 |
161 |
162 |
163 |
164 |
--------------------------------------------------------------------------------
/packages/apps/Settings/src/com/android/settings/ethernet/EthernetDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 SIMCOM Corp.
3 | *
4 | * The main interface to control ethernet setting param.
5 | * Athor: Mr. Tsao Bo, SIMCOM.
6 | * Restructured on 2020.11.10, for USB ethernet( A.K.A, eth1 ) connection.
7 | *
8 | */
9 |
10 | package com.android.settings.ethernet;
11 |
12 | import com.android.settings.R;
13 | import com.android.settings.ethernet.ip.IPView;
14 |
15 | import android.app.AlertDialog;
16 | import android.content.Context;
17 | import android.content.DialogInterface;
18 | import android.os.Bundle;
19 | import android.view.View;
20 | import android.widget.Button;
21 | import android.widget.EditText;
22 | import android.widget.CompoundButton;
23 | import android.widget.RadioButton;
24 | import android.util.Log;
25 | import android.view.inputmethod.InputMethodManager;
26 | import android.net.IpConfiguration;
27 | import android.net.IpConfiguration.IpAssignment;
28 | import android.net.IpConfiguration.ProxySettings;
29 | import android.os.Environment;
30 | import android.util.SparseArray;
31 | import android.net.StaticIpConfiguration;
32 | import android.net.EthernetManager;
33 | import android.text.TextUtils;
34 | import android.net.LinkAddress;
35 | import android.net.NetworkUtils;
36 | import android.net.ConnectivityManager;
37 | import android.net.LinkProperties;
38 | import android.os.RemoteException;
39 | import com.android.settings.Utils;
40 | import android.widget.Toast;
41 | import android.net.EthernetManager;
42 | import android.provider.Settings.Global;
43 | import com.zanshang.wifi.ExtraWifiService;
44 | import android.provider.Settings;
45 | import android.widget.Button;
46 |
47 |
48 | import java.net.InetAddress;
49 | import java.net.Inet4Address;
50 | import java.net.UnknownHostException;
51 | import java.util.Iterator;
52 | import java.util.regex.Pattern;
53 |
54 |
55 | class EthernetDialog extends AlertDialog implements DialogInterface.OnClickListener, DialogInterface.OnShowListener,
56 | DialogInterface.OnDismissListener{
57 | private final String TAG = "EthernetDialog";
58 | private static final boolean localLOGV = true;
59 |
60 |
61 | private View mView;
62 | private RadioButton mIpTypeDhcp;
63 | private RadioButton mIpTypeManual;
64 | private RadioButton eth0Radio;
65 | private RadioButton eth1Radio;
66 |
67 | private StaticIpViews mStaticIpViews;
68 | private RJ45StaticIpViews mRJ45StaticIpViews;
69 | private UsbCardStaticIpViews mUsbCardStaticIpViews;
70 |
71 |
72 | private Context mContext;
73 | private EthernetManager mEthManager;
74 | private ConnectivityManager mCM;
75 |
76 | public EthernetDialog(Context context,EthernetManager EthManager,ConnectivityManager cm) {
77 | super(context);
78 | mContext = context;
79 | mEthManager = EthManager;
80 | mCM = cm;
81 |
82 | createDialogContent();
83 |
84 | setOnShowListener(this);
85 | setOnDismissListener(this);
86 |
87 | }
88 |
89 | public void onShow(DialogInterface dialog) {
90 | if (localLOGV) Log.d(TAG, "onShow");
91 |
92 | UpdateViewContent();
93 |
94 | // soft keyboard pops up on the disabled EditText. Hide it.
95 | InputMethodManager imm = (InputMethodManager)mContext.getSystemService(
96 | Context.INPUT_METHOD_SERVICE);
97 | imm.hideSoftInputFromWindow(mView.getWindowToken(),
98 | InputMethodManager.HIDE_IMPLICIT_ONLY);
99 |
100 | /* Tsao Bo:The reason we listen click event on postive_button's View rather than the button */
101 | /* is because we'd like to manually handle the dialog dismiss.*/
102 | Button positive_button = getButton(BUTTON_POSITIVE);
103 | positive_button.setOnClickListener(new View.OnClickListener() {
104 | @Override
105 | public void onClick(View v) {
106 | handle_saveconf();
107 | }
108 | });
109 | }
110 |
111 | public void onClick(DialogInterface dialog, int which){
112 |
113 | }
114 |
115 | public void onDismiss(DialogInterface dialog) {
116 | if (localLOGV) Log.d(TAG, "onDismiss");
117 | }
118 |
119 | private void createDialogContent() {
120 | this.setTitle(R.string.eth_config_title);
121 | this.setView(mView = getLayoutInflater().inflate(R.layout.ethernet_configure, null));
122 |
123 | eth0Radio = (RadioButton) mView.findViewById(R.id.eth0_radio);
124 | eth1Radio = (RadioButton) mView.findViewById(R.id.eth1_radio);
125 |
126 | mIpTypeDhcp = (RadioButton) mView.findViewById(R.id.dhcp_radio);
127 | mIpTypeManual = (RadioButton) mView.findViewById(R.id.manual_radio);
128 |
129 | IPView Ipaddr = (IPView)mView.findViewById(R.id.ipaddr_edit);
130 | IPView NetMask = (IPView)mView.findViewById(R.id.mask_edit);
131 | IPView Gw = (IPView)mView.findViewById(R.id.eth_gw_edit);
132 | IPView Dns1 = (IPView)mView.findViewById(R.id.eth_dns_edit1);
133 | IPView Dns2 = (IPView)mView.findViewById(R.id.eth_dns_edit2);
134 |
135 | mRJ45StaticIpViews = new RJ45StaticIpViews(Ipaddr,NetMask,Gw,Dns1,Dns2);
136 | mUsbCardStaticIpViews = new UsbCardStaticIpViews(Ipaddr,NetMask,Gw,Dns1,Dns2);
137 |
138 | String ifaceType = getInterfaceSetting();
139 | if(ifaceType.equals(Settings.Global.INTERFACE_ETH0)){
140 | mStaticIpViews = mRJ45StaticIpViews;
141 | }else{
142 | mStaticIpViews = mUsbCardStaticIpViews;
143 | }
144 | mStaticIpViews.disableAllViews();
145 |
146 | setButton(BUTTON_POSITIVE, mContext.getText(R.string.menu_save), (DialogInterface.OnClickListener)null);
147 | setButton(BUTTON_NEGATIVE, mContext.getText(R.string.menu_cancel), this);
148 |
149 | updateRadioButtonState();
150 |
151 | setInverseBackgroundForced(true);
152 |
153 |
154 | eth0Radio.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
155 | @Override
156 | public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
157 | Log.i("eth0Radio","onCheckedChanged isChecked:"+isChecked);
158 | if(isChecked){
159 | mStaticIpViews = mRJ45StaticIpViews;
160 |
161 | setInterfaceSetting(Settings.Global.INTERFACE_ETH0);
162 |
163 | updateIpTypeRadioButtonState();
164 | mStaticIpViews.clearAllViews();
165 | mStaticIpViews.loadSettings();
166 | }
167 | }
168 | });
169 |
170 | eth1Radio.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
171 | @Override
172 | public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
173 | Log.i("eth1Radio","onCheckedChanged isChecked:"+isChecked);
174 | if(isChecked){
175 | mStaticIpViews = mUsbCardStaticIpViews;
176 |
177 | setInterfaceSetting(Settings.Global.INTERFACE_ETH1);
178 |
179 | updateIpTypeRadioButtonState();
180 | mStaticIpViews.clearAllViews();
181 | mStaticIpViews.loadSettings();
182 | }
183 | }
184 | });
185 |
186 | mIpTypeDhcp.setOnClickListener(new RadioButton.OnClickListener() {
187 | public void onClick(View v) {
188 | mStaticIpViews.setIpTypeSetting(Settings.Global.TYPE_DHCP);
189 |
190 | mStaticIpViews.disableAllViews();
191 | mStaticIpViews.clearAllViews();
192 | }
193 | });
194 |
195 | mIpTypeManual.setOnClickListener(new RadioButton.OnClickListener() {
196 | public void onClick(View v) {
197 | mStaticIpViews.setIpTypeSetting(Settings.Global.TYPE_STATIC);
198 |
199 | mStaticIpViews.enableAllViews();
200 | mStaticIpViews.clearAllViews();
201 | mStaticIpViews.loadSettings();
202 | }
203 | });
204 |
205 | UpdateViewContent();
206 |
207 | }
208 |
209 | private void UpdateViewContent() {
210 | int enable = Global.getInt(mContext.getContentResolver(), Global.ETHERNET_ON, EthernetManager.ETHERNET_STATE_UNKNOWN);
211 | if (localLOGV) Log.d(TAG, "UpdateViewContent enable=" + enable);
212 |
213 | if(enable == EthernetManager.ETHERNET_STATE_ENABLED) {
214 | String ifaceType = getInterfaceSetting();
215 |
216 | IpConfiguration ipinfo = mEthManager.getConfiguration(ifaceType);
217 |
218 | if((ipinfo.ipAssignment == IpAssignment.DHCP) ||(ipinfo.ipAssignment == IpAssignment.UNASSIGNED) ) {
219 | mIpTypeDhcp.setChecked(true);
220 | mStaticIpViews.disableAllViews();
221 | mStaticIpViews.clearAllViews();
222 | } else {
223 | mIpTypeManual.setChecked(true);
224 | mStaticIpViews.enableAllViews();
225 |
226 | StaticIpConfiguration staticConfig = ipinfo.getStaticIpConfiguration();
227 | Log.d(TAG, "UpdateViewContent staticConfig=" + staticConfig);
228 |
229 | mStaticIpViews.updateViews(staticConfig);
230 | }
231 | }
232 | }
233 |
234 | private String updateIfaceTypeRadioButtonState(){
235 | String ifaceType = getInterfaceSetting();
236 | if(ifaceType.equals(Settings.Global.INTERFACE_ETH0)){
237 | eth0Radio.setChecked(true);
238 | }else if(ifaceType.equals(Settings.Global.INTERFACE_ETH1)){
239 | eth1Radio.setChecked(true);
240 | }
241 | return ifaceType;
242 | }
243 |
244 | private String updateIpTypeRadioButtonState(){
245 | String ipType = mStaticIpViews.getIpTypeSetting();
246 | if(ipType.equals(Settings.Global.TYPE_DHCP)){
247 | mIpTypeDhcp.setChecked(true);
248 | mIpTypeManual.setChecked(false);
249 | }else if(ipType.equals(Settings.Global.TYPE_STATIC)){
250 | mIpTypeDhcp.setChecked(false);
251 | mIpTypeManual.setChecked(true);
252 | }
253 |
254 | return ipType;
255 | }
256 | private void updateRadioButtonState(){
257 | updateIfaceTypeRadioButtonState();
258 |
259 | updateIpTypeRadioButtonState();
260 | }
261 |
262 | private String getInterfaceSetting(){
263 | String ifaceType = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.ETHERNET_IFACE_TYPE);
264 |
265 | return ifaceType;
266 | }
267 |
268 | private boolean setInterfaceSetting(String iface){
269 | return Settings.Global.putString(mContext.getContentResolver(), Settings.Global.ETHERNET_IFACE_TYPE, iface);
270 |
271 | }
272 |
273 | private void handle_saveconf() {
274 | IpAssignment ipAssignment = (mIpTypeDhcp.isChecked() ? IpAssignment.DHCP:IpAssignment.STATIC);
275 |
276 | String iface;
277 | if(eth0Radio.isChecked()){
278 | iface = Settings.Global.INTERFACE_ETH0;
279 | }else{
280 | iface = Settings.Global.INTERFACE_ETH1;
281 | }
282 |
283 | if(IpAssignment.DHCP == ipAssignment){
284 | mEthManager.setConfiguration(iface,new IpConfiguration(ipAssignment, ProxySettings.NONE,
285 | null, null));
286 | dismiss();
287 | }else{
288 | StaticIpConfiguration staticIpConfiguration = mStaticIpViews.generateStaticIpConfiguration();
289 |
290 | if(staticIpConfiguration == null){
291 | Toast.makeText(mContext, R.string.eth_settings_error, Toast.LENGTH_SHORT).show();
292 | }else{
293 | mEthManager.setConfiguration(iface,new IpConfiguration(ipAssignment, ProxySettings.NONE,
294 | staticIpConfiguration, null));
295 | Log.d(TAG,"mode static ip ++ staticIpConfiguration=" + staticIpConfiguration);
296 |
297 | mStaticIpViews.saveSettings();
298 | dismiss();
299 | }
300 |
301 | }
302 |
303 | }
304 |
305 |
306 | private abstract class StaticIpViews{
307 | private final String TAG = "StaticIpViews";
308 |
309 | protected IPView mIpaddr;
310 | protected IPView mNetMask;
311 | protected IPView mGw;
312 | protected IPView mDns1;
313 | protected IPView mDns2;
314 |
315 |
316 | public StaticIpViews(IPView ipaddr, IPView netMask, IPView gateway, IPView dns1, IPView dns2){
317 | mIpaddr = ipaddr;
318 | mNetMask = netMask;
319 | mGw = gateway;
320 | mDns1 = dns1;
321 | mDns2 = dns2;
322 | }
323 |
324 | public void updateViews(StaticIpConfiguration staticIpConfig ){
325 | if (staticIpConfig != null) {
326 | if (staticIpConfig.ipAddress != null) {
327 | mIpaddr.setIp(staticIpConfig.ipAddress.getAddress().getHostAddress());
328 |
329 | String prefix=interMask2String(staticIpConfig.ipAddress.getPrefixLength());
330 | Log.d(TAG, "updateViews prefix=" + prefix);
331 | mNetMask.setIp(prefix);
332 | }
333 |
334 | if (staticIpConfig.gateway != null) {
335 | mGw.setIp(staticIpConfig.gateway.getHostAddress());
336 | }
337 |
338 | Iterator dnsIterator = staticIpConfig.dnsServers.iterator();
339 | if(dnsIterator.hasNext()){
340 | InetAddress ia = dnsIterator.next();
341 | mDns1.setIp(ia.getHostAddress());
342 | }
343 | if(dnsIterator.hasNext()){
344 | InetAddress ia = dnsIterator.next();
345 | mDns2.setIp(ia.getHostAddress());
346 | }
347 |
348 | }
349 | }
350 |
351 | public void enableAllViews(){
352 | setAllViewsEnabled(true);
353 | }
354 |
355 | public void disableAllViews(){
356 | setAllViewsEnabled(false);
357 | }
358 |
359 | private void setAllViewsEnabled(boolean enabled){
360 | mIpaddr.setEnabled(enabled);
361 | mNetMask.setEnabled(enabled);
362 | mGw.setEnabled(enabled);
363 | mDns1.setEnabled(enabled);
364 | mDns2.setEnabled(enabled);
365 | }
366 |
367 | public void clearAllViews(){
368 | mIpaddr.clear();
369 | mNetMask.clear();
370 | mGw.clear();
371 | mDns1.clear();
372 | mDns2.clear();
373 | }
374 |
375 | public abstract void saveSettings();
376 |
377 | public abstract void loadSettings();
378 |
379 | public abstract String getIpTypeSetting();
380 |
381 | public abstract boolean setIpTypeSetting(String ipType);
382 |
383 | public void readSettingsToIPView(IPView ipv, String settingString){
384 | String data = Global.getString(mContext.getContentResolver(), settingString);
385 | if(data != null && isIpAddress(data)) {
386 | ipv.setIp(data);
387 | }
388 | }
389 |
390 | public StaticIpConfiguration generateStaticIpConfiguration(){
391 |
392 | String ipaddr = mIpaddr.getText();
393 | String netMask = mNetMask.getText();
394 | String gateway = mGw.getText();
395 | String dns1 = mDns1.getText();
396 | String dns2 = mDns2.getText();
397 |
398 | InvalidInputHandler invalidInputHandler = new InvalidInputHandler();
399 | StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
400 |
401 | if (TextUtils.isEmpty(ipaddr)) {
402 | invalidInputHandler.addResult(ConfigErrorCodeEnum.CONFIG_STR_EMPTY);
403 | }else{
404 | Inet4Address inetAddr = getIPv4Address(ipaddr);
405 |
406 | if (inetAddr == null || inetAddr.equals(Inet4Address.ANY)) {
407 | invalidInputHandler.addResult(ConfigErrorCodeEnum.CONFIG_INVAILD_IP);
408 | }else{
409 |
410 | int networkPrefixLength = -1;
411 | try {
412 | networkPrefixLength = maskStr2InetMask(netMask);
413 | staticIpConfiguration.ipAddress = new LinkAddress(inetAddr, networkPrefixLength);
414 | } catch (NumberFormatException e) {
415 | // Set the hint as default after user types in ip address
416 | invalidInputHandler.addResult(ConfigErrorCodeEnum.CONFI_ERROR);
417 | } catch (IllegalArgumentException e) {
418 | invalidInputHandler.addResult(ConfigErrorCodeEnum.CONFI_ERROR);
419 | }
420 | }
421 | }
422 |
423 | if (!TextUtils.isEmpty(gateway)) {
424 | InetAddress gatewayAddr = getIPv4Address(gateway);
425 | if (gatewayAddr == null) {
426 | invalidInputHandler.addResult(ConfigErrorCodeEnum.CONFIG_INVAILD_GATEWAY);
427 | }
428 | if (gatewayAddr.isMulticastAddress()) {
429 | invalidInputHandler.addResult(ConfigErrorCodeEnum.CONFIG_INVAILD_GATEWAY);
430 | }
431 | staticIpConfiguration.gateway = gatewayAddr;
432 | }
433 |
434 | InetAddress dnsAddr = null;
435 | if (dns1 != null && !TextUtils.isEmpty(dns1)) {
436 | dnsAddr = getIPv4Address(dns1);
437 | if (dnsAddr == null) {
438 | invalidInputHandler.addResult(ConfigErrorCodeEnum.CONFIG_INVAILD_DNS);
439 | }
440 | staticIpConfiguration.dnsServers.add(dnsAddr);
441 | }
442 |
443 | if (dns2 != null && !TextUtils.isEmpty(dns2)) {
444 | dnsAddr = getIPv4Address(dns2);
445 | if (dnsAddr == null) {
446 | invalidInputHandler.addResult(ConfigErrorCodeEnum.CONFIG_INVAILD_DNS);
447 | }
448 | staticIpConfiguration.dnsServers.add(dnsAddr);
449 | }
450 |
451 | Log.d(TAG, "generateStaticIpConfiguration result=" + invalidInputHandler.getResults());
452 | if(0 == invalidInputHandler.getResults()){
453 | return staticIpConfiguration;
454 | }else{
455 | return null;
456 | }
457 | }
458 |
459 | public String interMask2String(int prefixLength) {
460 | String netMask = null;
461 | int inetMask = prefixLength;
462 |
463 | int part = inetMask / 8;
464 | int remainder = inetMask % 8;
465 | int sum = 0;
466 |
467 | for (int i = 8; i > 8 - remainder; i--) {
468 | sum = sum + (int) Math.pow(2, i - 1);
469 | }
470 |
471 | if (part == 0) {
472 | netMask = sum + ".0.0.0";
473 | } else if (part == 1) {
474 | netMask = "255." + sum + ".0.0";
475 | } else if (part == 2) {
476 | netMask = "255.255." + sum + ".0";
477 | } else if (part == 3) {
478 | netMask = "255.255.255." + sum;
479 | } else if (part == 4) {
480 | netMask = "255.255.255.255";
481 | }
482 |
483 | return netMask;
484 | }
485 |
486 | /*
487 | * convert subMask string to prefix length
488 | */
489 | public int maskStr2InetMask(String maskStr) {
490 | StringBuffer sb ;
491 | String str;
492 | int inetmask = 0;
493 | int count = 0;
494 | /*
495 | * check the subMask format
496 | */
497 | Pattern pattern = Pattern.compile("(^((\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])$)|^(\\d|[1-2]\\d|3[0-2])$");
498 | if (pattern.matcher(maskStr).matches() == false) {
499 | Log.e(TAG,"subMask is error");
500 | return 0;
501 | }
502 |
503 | String[] ipSegment = maskStr.split("\\.");
504 | for(int n =0; n 255) || (block < 0)) {
540 | return false;
541 | }
542 | } catch (NumberFormatException e) {
543 | return false;
544 | }
545 |
546 | numBlocks++;
547 |
548 | start = end + 1;
549 | end = value.indexOf('.', start);
550 | }
551 | return numBlocks == 4;
552 | }
553 |
554 | }
555 |
556 | private class RJ45StaticIpViews extends StaticIpViews{
557 | public RJ45StaticIpViews (IPView ipaddr, IPView netMask, IPView gateway, IPView dns1, IPView dns2){
558 | super(ipaddr,netMask,gateway,dns1,dns2);
559 | }
560 |
561 | @Override
562 | public void saveSettings(){
563 | Global.putString(mContext.getContentResolver(), Global.RJ45_STATIC_IP,
564 | mIpaddr.getText());
565 | Global.putString(mContext.getContentResolver(), Global.RJ45_STATIC_NETMASK,
566 | mNetMask.getText().toString());
567 | Global.putString(mContext.getContentResolver(), Global.RJ45_STATIC_GATEWAY,
568 | mGw.getText());
569 | Global.putString(mContext.getContentResolver(), Global.RJ45_STATIC_DNS1,
570 | mDns1.getText());
571 | Global.putString(mContext.getContentResolver(), Global.RJ45_STATIC_DNS2,
572 | mDns2.getText());
573 | }
574 |
575 | @Override
576 | public void loadSettings(){
577 | String ipType = getIpTypeSetting();
578 | if (localLOGV) Log.d(TAG, "ipType =" + ipType );
579 |
580 | if(ipType.equals(Settings.Global.TYPE_STATIC)){
581 | readSettingsToIPView(mIpaddr,Global.RJ45_STATIC_IP);
582 | readSettingsToIPView(mNetMask,Global.RJ45_STATIC_NETMASK);
583 | readSettingsToIPView(mGw,Global.RJ45_STATIC_GATEWAY);
584 | readSettingsToIPView(mDns1,Global.RJ45_STATIC_DNS1);
585 | readSettingsToIPView(mDns2,Global.RJ45_STATIC_DNS2);
586 | enableAllViews();
587 | }else{
588 | disableAllViews();
589 | clearAllViews();
590 | }
591 | }
592 |
593 | @Override
594 | public String getIpTypeSetting(){
595 | String ipType = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.ETHERNET_IP_TYPE_ETH0);
596 |
597 | return ipType;
598 | }
599 |
600 | @Override
601 | public boolean setIpTypeSetting(String ipType){
602 | return Settings.Global.putString(mContext.getContentResolver(), Settings.Global.ETHERNET_IP_TYPE_ETH0, ipType);
603 | }
604 |
605 | }
606 |
607 | private class UsbCardStaticIpViews extends StaticIpViews{
608 | public UsbCardStaticIpViews (IPView ipaddr, IPView netMask, IPView gateway, IPView dns1, IPView dns2){
609 | super(ipaddr,netMask,gateway,dns1,dns2);
610 | }
611 |
612 | @Override
613 | public void saveSettings(){
614 | Global.putString(mContext.getContentResolver(), Global.USB_CARD_STATIC_IP,
615 | mIpaddr.getText());
616 | Global.putString(mContext.getContentResolver(), Global.USB_CARD_STATIC_NETMASK,
617 | mNetMask.getText().toString());
618 | Global.putString(mContext.getContentResolver(), Global.USB_CARD_STATIC_GATEWAY,
619 | mGw.getText());
620 | Global.putString(mContext.getContentResolver(), Global.USB_CARD_STATIC_DNS1,
621 | mDns1.getText());
622 | Global.putString(mContext.getContentResolver(), Global.USB_CARD_STATIC_DNS2,
623 | mDns2.getText());
624 | }
625 |
626 | @Override
627 | public void loadSettings(){
628 | String ipType = getIpTypeSetting();
629 | if (localLOGV) Log.d(TAG, "ipType =" + ipType );
630 |
631 | if(ipType.equals(Settings.Global.TYPE_STATIC)){
632 | readSettingsToIPView(mIpaddr,Global.USB_CARD_STATIC_IP);
633 | readSettingsToIPView(mNetMask,Global.USB_CARD_STATIC_NETMASK);
634 | readSettingsToIPView(mGw,Global.USB_CARD_STATIC_GATEWAY);
635 | readSettingsToIPView(mDns1,Global.USB_CARD_STATIC_DNS1);
636 | readSettingsToIPView(mDns2,Global.USB_CARD_STATIC_DNS2);
637 | enableAllViews();
638 | }else{
639 | disableAllViews();
640 | clearAllViews();
641 | }
642 |
643 | }
644 |
645 | @Override
646 | public String getIpTypeSetting(){
647 | String ipType = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.ETHERNET_IP_TYPE_ETH1);
648 |
649 | return ipType;
650 | }
651 |
652 | @Override
653 | public boolean setIpTypeSetting(String ipType){
654 | return Settings.Global.putString(mContext.getContentResolver(), Settings.Global.ETHERNET_IP_TYPE_ETH1, ipType);
655 | }
656 | }
657 |
658 | private class InvalidInputHandler{
659 |
660 | public static final int STR_EMPTY_MASK = ~0x01;
661 | private int mResults;
662 |
663 | public InvalidInputHandler(){
664 | mResults = ConfigErrorCodeEnum.CONFIG_OK.getCode();
665 | }
666 |
667 | public void addResult(ConfigErrorCodeEnum resultEnum){
668 | mResults |=resultEnum.getCode();
669 | }
670 |
671 | public int getResults(){
672 | return mResults;
673 | }
674 |
675 | public void popupIndication(){
676 |
677 | }
678 |
679 | }
680 |
681 |
682 | public static enum ConfigErrorCodeEnum{
683 | CONFIG_OK(0,0),
684 | CONFIG_STR_EMPTY(0x01, R.string.eth_settings_empty),
685 | CONFIG_INVAILD_IP(0x02, R.string.eth_settings_invalid_ip_address),
686 | CONFIG_INVAILD_GATEWAY(0x04, R.string.eth_settings_invalid_gateway),
687 | CONFIG_INVAILD_DNS(0x08, R.string.eth_settings_invalid_dns),
688 | CONFI_ERROR(0x10, R.string.eth_settings_error);
689 |
690 | private int mCode;
691 | private int mTextId;
692 |
693 | private ConfigErrorCodeEnum(int code, int textId){
694 | mCode = code;
695 | mTextId = textId;
696 | }
697 |
698 | public int getCode(){
699 | return mCode;
700 | }
701 |
702 | public static int getTextIdByCode(int code ){
703 | int rTextId = 0;
704 | for(ConfigErrorCodeEnum errorCode:values()){
705 | if(errorCode.mCode == code){
706 | rTextId = errorCode.mTextId;
707 | break;
708 | }
709 | }
710 |
711 | return rTextId;
712 | }
713 | }
714 |
715 |
716 | }
717 |
--------------------------------------------------------------------------------
/packages/apps/Settings/src/com/android/settings/ethernet/EthernetEnabler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 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 |
17 | package com.android.settings.ethernet;
18 |
19 | import android.content.ContentResolver;
20 | import android.content.Context;
21 | import android.content.Intent;
22 | import android.content.IntentFilter;
23 | import android.os.Bundle;
24 | import android.os.RemoteException;
25 | import android.os.SystemProperties;
26 | import android.preference.ListPreference;
27 | import android.preference.Preference;
28 | import android.preference.PreferenceScreen;
29 | import android.provider.Settings;
30 | import android.provider.Settings.SettingNotFoundException;
31 | import android.util.AttributeSet;
32 | import android.util.Log;
33 | import android.view.View;
34 | import android.preference.CheckBoxPreference;
35 |
36 | import java.util.ArrayList;
37 | import com.android.settings.SettingsPreferenceFragment;
38 | import com.android.settings.R;
39 | import com.android.settings.widget.SwitchBar;
40 | import com.android.settings.widget.SwitchBarController;
41 | import com.android.settings.SettingsActivity;
42 | import android.widget.Switch;
43 | import android.net.EthernetManager;
44 | import android.provider.Settings;
45 |
46 | public class EthernetEnabler implements SwitchBarController.OnSwitchChangeListener {
47 | private final String TAG = "EthernetEnabler";
48 | private Context mContext;
49 | private SwitchBarController mSwitchBarController;
50 | private EthernetDialog mEthDialog = null;
51 | private EthernetManager mEthManager;
52 | public void setConfigDialog(EthernetDialog Dialog) {
53 | mEthDialog = Dialog;
54 | }
55 |
56 | public EthernetEnabler(Context context, SwitchBarController switchWidget,EthernetManager ethernetManager) {
57 | mContext = context;
58 | mSwitchBarController = switchWidget;
59 | mEthManager = ethernetManager;
60 | setupSwitchBar();
61 | }
62 |
63 | public void resume(Context context) {
64 | Log.d(TAG,"resume ");
65 | mContext = context;
66 | }
67 |
68 | public void pause() {
69 | Log.d(TAG,"pause ");
70 | }
71 |
72 | public void setupSwitchBar() {
73 | int enable = Settings.Global.getInt(mContext.getContentResolver(),Settings.Global.ETHERNET_ON,EthernetManager.ETHERNET_STATE_UNKNOWN);
74 | Log.d(TAG,"setupSwitchBar enable="+ enable);
75 | if(enable == EthernetManager.ETHERNET_STATE_ENABLED) {
76 | mSwitchBarController.setChecked(true);
77 | } else {
78 | mSwitchBarController.setChecked(false);
79 | }
80 | mSwitchBarController.setListener(this);
81 | mSwitchBarController.startListening();
82 | mSwitchBarController.setupView();
83 |
84 | }
85 |
86 | public void teardownSwitchBar() {
87 | Log.d(TAG,"teardownSwitchBar ");
88 | mSwitchBarController.stopListening();
89 | mSwitchBarController.teardownView();
90 | }
91 |
92 | @Override
93 | public boolean onSwitchToggled( boolean isChecked) {
94 | Log.d(TAG,"onSwitchToggled isChecked= " + isChecked);
95 | if(isChecked) {
96 | if(mEthManager != null){
97 | mEthManager.start();
98 | }
99 | Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ETHERNET_ON,EthernetManager.ETHERNET_STATE_ENABLED);
100 | } else {
101 | if(mEthManager != null){
102 | mEthManager.stop();
103 | }
104 | Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ETHERNET_ON,EthernetManager.ETHERNET_STATE_DISABLED);
105 | }
106 | return true;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/packages/apps/Settings/src/com/android/settings/ethernet/EthernetSettings.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 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 |
17 | package com.android.settings.ethernet;
18 |
19 | import android.content.ContentResolver;
20 | import android.content.Context;
21 | import android.content.Intent;
22 | import android.content.IntentFilter;
23 | import android.os.Bundle;
24 | import android.os.RemoteException;
25 | import android.os.SystemProperties;
26 | import android.support.v7.preference.Preference;
27 | import android.support.v7.preference.Preference.OnPreferenceChangeListener;
28 | import android.support.v7.preference.PreferenceScreen;
29 | import android.provider.Settings;
30 | import android.provider.Settings.SettingNotFoundException;
31 | import android.util.AttributeSet;
32 | import android.util.Log;
33 | import android.view.View;
34 | import android.preference.CheckBoxPreference;
35 |
36 | import java.util.ArrayList;
37 |
38 | import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
39 | import com.android.settings.dashboard.SummaryLoader;
40 | import com.android.settings.SettingsPreferenceFragment;
41 | import com.android.settings.R;
42 | import com.android.settings.widget.SwitchBar;
43 | import com.android.settings.widget.SwitchBarController;
44 | import com.android.settings.SettingsActivity;
45 |
46 | import android.widget.Switch;
47 | import android.app.Activity;
48 | import android.app.ActivityManager;
49 | import android.net.DhcpInfo;
50 | import android.net.EthernetManager;
51 | import android.content.Context;
52 | import android.net.ConnectivityManager;
53 | import android.widget.Toast;
54 | import android.os.Looper;
55 |
56 | public class EthernetSettings extends SettingsPreferenceFragment implements OnPreferenceChangeListener{
57 | private static final String TAG = "EthernetSettings";
58 | private EthernetEnabler mEthEnabler;
59 | private static final String KEY_CONF_ETH = "ethernet_config";
60 | private EthernetDialog mEthernetDialog = null;
61 | private Preference mEthConfigPref;
62 | private ConnectivityManager mCM;
63 | private DhcpInfo mDhcpinfo;
64 |
65 | @Override
66 | public void onCreate(Bundle savedInstanceState) {
67 | super.onCreate(savedInstanceState);
68 | addPreferencesFromResource(R.xml.ethernet_settings);
69 | final PreferenceScreen preferenceScreen = getPreferenceScreen();
70 | mEthConfigPref = preferenceScreen.findPreference(KEY_CONF_ETH);
71 | }
72 |
73 | @Override
74 | public void onStart() {
75 | super.onStart();
76 | // On/off switch is hidden for Setup Wizard (returns null)
77 | mEthEnabler = createEthernetEnabler();
78 | mCM = (ConnectivityManager)getActivity().getSystemService(
79 | Context.CONNECTIVITY_SERVICE);
80 | mEthernetDialog = new EthernetDialog(getActivity(),
81 | (EthernetManager)getSystemService(Context.ETHERNET_SERVICE), mCM);
82 | mEthEnabler.setConfigDialog(mEthernetDialog);
83 | }
84 |
85 | @Override
86 | public void onResume() {
87 | super.onResume();
88 | final Activity activity = getActivity();
89 | if (mEthEnabler != null) {
90 | mEthEnabler.resume(activity);
91 | }
92 | }
93 |
94 | @Override
95 | public void onPause() {
96 | super.onPause();
97 | if (mEthEnabler != null) {
98 | mEthEnabler.pause();
99 | }
100 | }
101 |
102 | @Override
103 | public void onDestroyView() {
104 | super.onDestroyView();
105 |
106 | if (mEthEnabler != null) {
107 | mEthEnabler.teardownSwitchBar();
108 | }
109 | }
110 |
111 | @Override
112 | public int getMetricsCategory() {
113 | return MetricsEvent.ETHERNET;
114 | }
115 |
116 | /**
117 | * @return new EthernetEnabler or null
118 | */
119 | /* package */
120 | EthernetEnabler createEthernetEnabler() {
121 | final SettingsActivity activity = (SettingsActivity) getActivity();
122 | SwitchBar bar = activity.getSwitchBar();
123 | return new EthernetEnabler(activity, new SwitchBarController(activity.getSwitchBar()),
124 | (EthernetManager)getSystemService(Context.ETHERNET_SERVICE));
125 | }
126 |
127 | @Override
128 | public boolean onPreferenceChange(Preference preference, Object newValue) {
129 | return true;
130 | }
131 |
132 | @Override
133 | public boolean onPreferenceTreeClick(Preference preference) {
134 | if (preference == mEthConfigPref) {
135 | final SettingsActivity activity = (SettingsActivity) getActivity();
136 | if(activity.getSwitchBar().isChecked()) {
137 | if(mEthernetDialog != null)
138 | mEthernetDialog.show();
139 | } else {
140 | Toast.makeText(getActivity(), R.string.eth_open_ethernet_tip, Toast.LENGTH_LONG).show();
141 | }
142 | }
143 | return super.onPreferenceTreeClick(preference);
144 | }
145 |
146 | private static class SummaryProvider implements SummaryLoader.SummaryProvider {
147 |
148 | private final Context mContext;
149 | private final SummaryLoader mSummaryLoader;
150 |
151 | public SummaryProvider(Context context, SummaryLoader summaryLoader) {
152 | mContext = context;
153 | mSummaryLoader = summaryLoader;
154 | }
155 |
156 | @Override
157 | public void setListening(boolean listening) {
158 | if (listening) {
159 | int enable = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ETHERNET_ON, 0);
160 | if(enable == EthernetManager.ETHERNET_STATE_ENABLED) {
161 | mSummaryLoader.setSummary(this, mContext.getString(R.string.eth_state_on));
162 | } else {
163 | mSummaryLoader.setSummary(this, mContext.getString(R.string.eth_state_off));
164 | }
165 | }
166 | }
167 | }
168 |
169 | public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
170 | = new SummaryLoader.SummaryProviderFactory() {
171 | @Override
172 | public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
173 | SummaryLoader summaryLoader) {
174 | return new SummaryProvider(activity, summaryLoader);
175 | }
176 | };
177 | }
178 |
--------------------------------------------------------------------------------
/packages/apps/Settings/src/com/android/settings/ethernet/ip/AbsEditText.java:
--------------------------------------------------------------------------------
1 | package com.android.settings.ethernet.ip;
2 |
3 | import android.content.Context;
4 | import android.text.InputFilter;
5 | import android.text.InputType;
6 | import android.text.method.NumberKeyListener;
7 | import android.util.AttributeSet;
8 | import android.widget.EditText;
9 |
10 | public abstract class AbsEditText extends EditText {
11 | public AbsEditText(Context context) {
12 | this(context,null,0);
13 | }
14 |
15 | public AbsEditText(Context context, AttributeSet attrs) {
16 | this(context, attrs,0);
17 | }
18 |
19 | public AbsEditText(Context context, AttributeSet attrs, int defStyleAttr) {
20 | super(context, attrs, defStyleAttr);
21 | setMaxLength();
22 | addInputFilter();
23 | }
24 |
25 | protected void setMaxLength(){
26 | setFilters(new InputFilter[]{new InputFilter.LengthFilter(getMaxLength())});
27 | }
28 |
29 | protected void addInputFilter(){
30 | setKeyListener(new NumberKeyListener() {
31 | @Override
32 | protected char[] getAcceptedChars() {
33 | return getInputFilterAcceptedChars();
34 | }
35 |
36 | @Override
37 | public int getInputType() {
38 | return InputType.TYPE_CLASS_NUMBER;
39 | }
40 | });
41 | }
42 |
43 | public abstract int getMaxLength();
44 |
45 | public abstract char[] getInputFilterAcceptedChars();
46 |
47 | public abstract boolean checkInputValue();
48 |
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/packages/apps/Settings/src/com/android/settings/ethernet/ip/AbsEditTextGroup.java:
--------------------------------------------------------------------------------
1 | package com.android.settings.ethernet.ip;
2 |
3 | import android.content.Context;
4 | import android.text.Editable;
5 | import android.text.TextUtils;
6 | import android.text.TextWatcher;
7 | import android.util.AttributeSet;
8 | import android.util.Log;
9 | import android.view.Gravity;
10 | import android.view.KeyEvent;
11 | import android.view.View;
12 | import android.widget.LinearLayout;
13 | import android.widget.TextView;
14 | import android.widget.Toast;
15 |
16 | import com.android.settings.R;
17 |
18 | import java.util.ArrayList;
19 |
20 | public abstract class AbsEditTextGroup extends LinearLayout implements TextWatcher {
21 |
22 | protected float sp16 = 16.0f;
23 | protected int dp4 = 4;
24 | private ArrayList editTexts = new ArrayList();
25 |
26 | public AbsEditTextGroup(Context context) {
27 | this(context, null, 0);
28 | }
29 |
30 | public AbsEditTextGroup(Context context, AttributeSet attrs) {
31 | this(context, attrs, 0);
32 | }
33 |
34 | public AbsEditTextGroup(Context context, AttributeSet attrs, int defStyleAttr) {
35 | super(context, attrs, defStyleAttr);
36 | addViews();
37 | buildListener();
38 | }
39 |
40 | protected void addViews() {
41 | for (int i = 0; i < getChildCount(); i++) {
42 | if (i%2==0) {
43 | AbsEditText absEditText= createAbsEditText();
44 | editTexts.add(absEditText);
45 | addView(absEditText);
46 | } else {
47 | addView(createSemicolonTextView());
48 | }
49 | }
50 | }
51 |
52 | protected AbsEditText createAbsEditText() {
53 |
54 | AbsEditText absEditText = getAbsEditText();
55 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT);
56 | params.weight = 1;
57 | absEditText.setLayoutParams(params);
58 | absEditText.setTextSize(sp16);
59 | absEditText.setTextColor(0xFF222222);
60 | absEditText.setGravity(Gravity.CENTER);
61 | absEditText.setPadding(dp4, dp4, dp4, dp4);
62 | absEditText.setSingleLine();
63 | absEditText.setFocusableInTouchMode(true);
64 | absEditText.setBackgroundColor(0xFFFFFFFF);
65 | applyEditTextTheme(absEditText);
66 | return absEditText;
67 | }
68 |
69 | protected TextView createSemicolonTextView() {
70 | TextView textView = new TextView(getContext());
71 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
72 | textView.setLayoutParams(params);
73 | textView.setTextSize(sp16);
74 | textView.setTextColor(0xFF444444);
75 | textView.setText(getSemicolomText());
76 | applySemicolonTextViewTheme(textView);
77 | return textView;
78 | }
79 |
80 | protected void buildListener() {
81 | for (int i = 0; i < editTexts.size(); i++) {
82 | editTexts.get(i).addTextChangedListener(this);
83 | if(i!=0){
84 | editTexts.get(i).setOnKeyListener(new OnDelKeyListener(editTexts.get(i-1), editTexts.get(i)));
85 | }
86 | }
87 | }
88 |
89 | @Override
90 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
91 |
92 | }
93 |
94 | @Override
95 | public void onTextChanged(CharSequence s, int start, int before, int count) {
96 | android.util.Log.i("zhouyj", "start = " + start + " before = " + before + " count = " + count);
97 | }
98 |
99 | @Override
100 | public void afterTextChanged(Editable s) {
101 | String text = s.toString().trim();
102 | if (text.length() > 0 && Integer.parseInt(text.toString().trim()) > 255) {
103 | s.delete(text.length() - 2, 1);
104 | Toast.makeText(getContext(), R.string.eth_settings_error, Toast.LENGTH_SHORT).show();
105 | } else if (text.length() == getDelMaxLength()) {
106 | for (int i=0; i< editTexts.size()-1; i++){
107 | if(editTexts.get(i).hasFocus()){
108 | editTexts.get(i).clearFocus();
109 | editTexts.get(i+1).requestFocus();
110 | break;
111 | }
112 | }
113 | }
114 | }
115 |
116 | public boolean checkInputValue(AbsEditText... params) {
117 | boolean result = true;
118 | for (int i = 0; i < params.length - 1; i++) {
119 | if (!params[i].checkInputValue()) {
120 | result = false;
121 | break;
122 | }
123 | }
124 |
125 | return result;
126 | }
127 |
128 | public void setIp(String ip) {
129 | if (!TextUtils.isEmpty(ip)) {
130 | String[] ips = ip.split("\\" + getSemicolomText());
131 | for (int i = 0; i < editTexts.size(); i++) {
132 | editTexts.get(i).setText(ips[i]);
133 | }
134 | }
135 | }
136 |
137 | public String getText() {
138 | StringBuffer sb = new StringBuffer();
139 | for (int i = 0; i < editTexts.size(); i++) {
140 | String ip = editTexts.get(i).getText().toString();
141 | if (!TextUtils.isEmpty(ip)) {
142 | sb.append(ip);
143 | if (i != editTexts.size() -1) {
144 | sb.append(getSemicolomText());
145 | }
146 | }
147 | }
148 | return sb.toString();
149 | }
150 |
151 | public void clear() {
152 | for (int i = 0; i < editTexts.size(); i++) {
153 | editTexts.get(i).setText("");
154 | }
155 | }
156 |
157 | class OnDelKeyListener implements View.OnKeyListener {
158 |
159 | private AbsEditText clearEditText;
160 | private AbsEditText requestEditText;
161 |
162 | public OnDelKeyListener(AbsEditText requestEditText, AbsEditText clearEditText){
163 | this.requestEditText = requestEditText;
164 | this.clearEditText = clearEditText;
165 | }
166 | @Override
167 | public boolean onKey(View v, int keyCode, KeyEvent event) {
168 | if (keyCode == KeyEvent.KEYCODE_DEL
169 | && event.getAction() == KeyEvent.ACTION_DOWN
170 | && clearEditText.getSelectionStart() == 0) {
171 | clearEditText.clearFocus();
172 | requestEditText.requestFocus();
173 | requestEditText.setSelection(requestEditText.length());
174 | return true;
175 | }
176 | return false;
177 | }
178 | }
179 |
180 | public abstract int getChildCount();
181 |
182 | public abstract AbsEditText getAbsEditText();
183 |
184 | public abstract String getSemicolomText();
185 |
186 | public abstract int getDelMaxLength();
187 |
188 | public abstract void applySemicolonTextViewTheme(TextView semicolonTextView);
189 |
190 | public abstract void applyEditTextTheme(AbsEditText absEditText);
191 |
192 |
193 | }
194 |
--------------------------------------------------------------------------------
/packages/apps/Settings/src/com/android/settings/ethernet/ip/IPEditText.java:
--------------------------------------------------------------------------------
1 | package com.android.settings.ethernet.ip;
2 |
3 | import android.content.Context;
4 | import android.text.InputFilter;
5 | import android.text.InputType;
6 | import android.text.method.NumberKeyListener;
7 | import android.util.AttributeSet;
8 | import android.widget.EditText;
9 |
10 | public class IPEditText extends AbsEditText {
11 |
12 | public IPEditText(Context context) {
13 | this(context, null, 0);
14 | }
15 |
16 | public IPEditText(Context context, AttributeSet attrs) {
17 | this(context, attrs, 0);
18 | }
19 |
20 | public IPEditText(Context context, AttributeSet attrs, int defStyleAttr) {
21 | super(context, attrs, defStyleAttr);
22 | }
23 |
24 | @Override
25 | public int getMaxLength() {
26 | return 3;
27 | }
28 |
29 | @Override
30 | public char[] getInputFilterAcceptedChars() {
31 | return new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
32 | }
33 |
34 | @Override
35 | public boolean checkInputValue() {
36 | return getText().length() != 0;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/packages/apps/Settings/src/com/android/settings/ethernet/ip/IPView.java:
--------------------------------------------------------------------------------
1 | package com.android.settings.ethernet.ip;
2 |
3 | import android.content.Context;
4 | import android.text.Editable;
5 | import android.text.TextWatcher;
6 | import android.util.AttributeSet;
7 | import android.view.Gravity;
8 | import android.view.KeyEvent;
9 | import android.view.View;
10 | import android.widget.LinearLayout;
11 | import android.widget.TextView;
12 |
13 | import java.util.ArrayList;
14 |
15 | public class IPView extends AbsEditTextGroup {
16 | public IPView(Context context) {
17 | super(context);
18 | }
19 |
20 | public IPView(Context context, AttributeSet attrs) {
21 | super(context, attrs);
22 | }
23 |
24 | public IPView(Context context, AttributeSet attrs, int defStyleAttr) {
25 | super(context, attrs, defStyleAttr);
26 | }
27 |
28 | @Override
29 | public void setEnabled(boolean enabled) {
30 | super.setEnabled(enabled);
31 | for (int i = 0; i < getChildCount(); i++) {
32 | if (i % 2 == 0) {
33 | AbsEditText absEditText= (AbsEditText) getChildAt(i);
34 | absEditText.setEnabled(enabled);
35 | }
36 | }
37 | }
38 |
39 | @Override
40 | public int getChildCount() {
41 | return 7;
42 | }
43 |
44 | @Override
45 | public AbsEditText getAbsEditText() {
46 | return new IPEditText(getContext());
47 | }
48 |
49 | @Override
50 | public String getSemicolomText() {
51 | return ".";
52 | }
53 |
54 | @Override
55 | public int getDelMaxLength() {
56 | return 3;
57 | }
58 |
59 | @Override
60 | public void applySemicolonTextViewTheme(TextView semicolonTextView) {
61 | semicolonTextView.setPadding(0,0,0,5);
62 | semicolonTextView.getPaint().setFakeBoldText(true);
63 | semicolonTextView.setBackgroundColor(0xFFFFFFFF);
64 | semicolonTextView.setGravity(Gravity.BOTTOM);
65 | }
66 |
67 | @Override
68 | public void applyEditTextTheme(AbsEditText absEditText) {
69 |
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------