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.IEthernetManager; 22 import android.net.IEthernetServiceListener; 23 import android.net.ITetheredInterfaceCallback; 24 import android.net.IpConfiguration; 25 import android.net.NetworkStack; 26 import android.os.Binder; 27 import android.os.Handler; 28 import android.os.HandlerThread; 29 import android.os.RemoteException; 30 import android.provider.Settings; 31 import android.util.Log; 32 import android.util.PrintWriterPrinter; 33 34 import com.android.internal.util.IndentingPrintWriter; 35 36 import java.io.FileDescriptor; 37 import java.io.PrintWriter; 38 import java.util.concurrent.atomic.AtomicBoolean; 39 40 /** 41 * EthernetServiceImpl handles remote Ethernet operation requests by implementing 42 * the IEthernetManager interface. 43 */ 44 public class EthernetServiceImpl extends IEthernetManager.Stub { 45 private static final String TAG = "EthernetServiceImpl"; 46 47 private final Context mContext; 48 private final AtomicBoolean mStarted = new AtomicBoolean(false); 49 50 private Handler mHandler; 51 private EthernetTracker mTracker; 52 EthernetServiceImpl(Context context)53 public EthernetServiceImpl(Context context) { 54 mContext = context; 55 } 56 enforceAccessPermission()57 private void enforceAccessPermission() { 58 mContext.enforceCallingOrSelfPermission( 59 android.Manifest.permission.ACCESS_NETWORK_STATE, 60 "EthernetService"); 61 } 62 enforceUseRestrictedNetworksPermission()63 private void enforceUseRestrictedNetworksPermission() { 64 mContext.enforceCallingOrSelfPermission( 65 android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS, 66 "ConnectivityService"); 67 } 68 checkUseRestrictedNetworksPermission()69 private boolean checkUseRestrictedNetworksPermission() { 70 return mContext.checkCallingOrSelfPermission( 71 android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS) 72 == PackageManager.PERMISSION_GRANTED; 73 } 74 start()75 public void start() { 76 Log.i(TAG, "Starting Ethernet service"); 77 78 HandlerThread handlerThread = new HandlerThread("EthernetServiceThread"); 79 handlerThread.start(); 80 mHandler = new Handler(handlerThread.getLooper()); 81 82 mTracker = new EthernetTracker(mContext, mHandler); 83 mTracker.start(); 84 85 mStarted.set(true); 86 } 87 88 @Override getAvailableInterfaces()89 public String[] getAvailableInterfaces() throws RemoteException { 90 enforceAccessPermission(); 91 92 return mTracker.getInterfaces(checkUseRestrictedNetworksPermission()); 93 } 94 95 /** 96 * Get Ethernet configuration 97 * @return the Ethernet Configuration, contained in {@link IpConfiguration}. 98 */ 99 @Override getConfiguration(String iface)100 public IpConfiguration getConfiguration(String iface) { 101 enforceAccessPermission(); 102 103 if (mTracker.isRestrictedInterface(iface)) { 104 enforceUseRestrictedNetworksPermission(); 105 } 106 107 return new IpConfiguration(mTracker.getIpConfiguration(iface)); 108 } 109 110 /** 111 * Set Ethernet configuration 112 */ 113 @Override setConfiguration(String iface, IpConfiguration config)114 public void setConfiguration(String iface, IpConfiguration config) { 115 if (!mStarted.get()) { 116 Log.w(TAG, "System isn't ready enough to change ethernet configuration"); 117 } 118 119 NetworkStack.checkNetworkStackPermission(mContext); 120 121 if (mTracker.isRestrictedInterface(iface)) { 122 enforceUseRestrictedNetworksPermission(); 123 } 124 125 // TODO: this does not check proxy settings, gateways, etc. 126 // Fix this by making IpConfiguration a complete representation of static configuration. 127 mTracker.updateIpConfiguration(iface, new IpConfiguration(config)); 128 } 129 130 /** 131 * Indicates whether given interface is available. 132 */ 133 @Override isAvailable(String iface)134 public boolean isAvailable(String iface) { 135 enforceAccessPermission(); 136 137 if (mTracker.isRestrictedInterface(iface)) { 138 enforceUseRestrictedNetworksPermission(); 139 } 140 141 return mTracker.isTrackingInterface(iface); 142 } 143 144 /** 145 * Adds a listener. 146 * @param listener A {@link IEthernetServiceListener} to add. 147 */ addListener(IEthernetServiceListener listener)148 public void addListener(IEthernetServiceListener listener) { 149 if (listener == null) { 150 throw new IllegalArgumentException("listener must not be null"); 151 } 152 enforceAccessPermission(); 153 mTracker.addListener(listener, checkUseRestrictedNetworksPermission()); 154 } 155 156 /** 157 * Removes a listener. 158 * @param listener A {@link IEthernetServiceListener} to remove. 159 */ removeListener(IEthernetServiceListener listener)160 public void removeListener(IEthernetServiceListener listener) { 161 if (listener == null) { 162 throw new IllegalArgumentException("listener must not be null"); 163 } 164 enforceAccessPermission(); 165 mTracker.removeListener(listener); 166 } 167 168 @Override setIncludeTestInterfaces(boolean include)169 public void setIncludeTestInterfaces(boolean include) { 170 NetworkStack.checkNetworkStackPermissionOr(mContext, 171 android.Manifest.permission.NETWORK_SETTINGS); 172 mTracker.setIncludeTestInterfaces(include); 173 } 174 175 @Override requestTetheredInterface(ITetheredInterfaceCallback callback)176 public void requestTetheredInterface(ITetheredInterfaceCallback callback) { 177 NetworkStack.checkNetworkStackPermissionOr(mContext, 178 android.Manifest.permission.NETWORK_SETTINGS); 179 mTracker.requestTetheredInterface(callback); 180 } 181 182 @Override releaseTetheredInterface(ITetheredInterfaceCallback callback)183 public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { 184 NetworkStack.checkNetworkStackPermissionOr(mContext, 185 android.Manifest.permission.NETWORK_SETTINGS); 186 mTracker.releaseTetheredInterface(callback); 187 } 188 189 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)190 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 191 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 192 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 193 != PackageManager.PERMISSION_GRANTED) { 194 pw.println("Permission Denial: can't dump EthernetService from pid=" 195 + Binder.getCallingPid() 196 + ", uid=" + Binder.getCallingUid()); 197 return; 198 } 199 200 pw.println("Current Ethernet state: "); 201 pw.increaseIndent(); 202 mTracker.dump(fd, pw, args); 203 pw.decreaseIndent(); 204 205 pw.println("Handler:"); 206 pw.increaseIndent(); 207 mHandler.dump(new PrintWriterPrinter(pw), "EthernetServiceImpl"); 208 pw.decreaseIndent(); 209 } 210 } 211