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 static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; 20 import static android.net.NetworkCapabilities.TRANSPORT_TEST; 21 22 import android.annotation.CheckResult; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.content.Context; 26 import android.content.pm.PackageManager; 27 import android.net.EthernetNetworkSpecifier; 28 import android.net.EthernetNetworkUpdateRequest; 29 import android.net.IEthernetManager; 30 import android.net.IEthernetServiceListener; 31 import android.net.INetworkInterfaceOutcomeReceiver; 32 import android.net.ITetheredInterfaceCallback; 33 import android.net.IpConfiguration; 34 import android.net.NetworkCapabilities; 35 import android.net.NetworkSpecifier; 36 import android.os.Handler; 37 import android.os.RemoteException; 38 import android.util.Log; 39 import android.util.PrintWriterPrinter; 40 41 import com.android.internal.annotations.VisibleForTesting; 42 import com.android.internal.util.IndentingPrintWriter; 43 import com.android.net.module.util.PermissionUtils; 44 45 import java.io.FileDescriptor; 46 import java.io.PrintWriter; 47 import java.util.List; 48 import java.util.Objects; 49 import java.util.concurrent.atomic.AtomicBoolean; 50 51 /** 52 * EthernetServiceImpl handles remote Ethernet operation requests by implementing 53 * the IEthernetManager interface. 54 */ 55 public class EthernetServiceImpl extends IEthernetManager.Stub { 56 private static final String TAG = "EthernetServiceImpl"; 57 58 @VisibleForTesting 59 final AtomicBoolean mStarted = new AtomicBoolean(false); 60 private final Context mContext; 61 private final Handler mHandler; 62 private final EthernetTracker mTracker; 63 EthernetServiceImpl(@onNull final Context context, @NonNull final Handler handler, @NonNull final EthernetTracker tracker)64 EthernetServiceImpl(@NonNull final Context context, @NonNull final Handler handler, 65 @NonNull final EthernetTracker tracker) { 66 mContext = context; 67 mHandler = handler; 68 mTracker = tracker; 69 } 70 enforceAutomotiveDevice(final @NonNull String methodName)71 private void enforceAutomotiveDevice(final @NonNull String methodName) { 72 PermissionUtils.enforceSystemFeature(mContext, PackageManager.FEATURE_AUTOMOTIVE, 73 methodName + " is only available on automotive devices."); 74 } 75 76 @CheckResult hasUseRestrictedNetworksPermission()77 private boolean hasUseRestrictedNetworksPermission() { 78 return PermissionUtils.hasAnyPermissionOf(mContext, 79 android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS); 80 } 81 start()82 public void start() { 83 Log.i(TAG, "Starting Ethernet service"); 84 mTracker.start(); 85 mStarted.set(true); 86 } 87 throwIfEthernetNotStarted()88 private void throwIfEthernetNotStarted() { 89 if (!mStarted.get()) { 90 throw new IllegalStateException("System isn't ready to change ethernet configurations"); 91 } 92 } 93 94 @Override getAvailableInterfaces()95 public String[] getAvailableInterfaces() throws RemoteException { 96 PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); 97 return mTracker.getClientModeInterfaces(hasUseRestrictedNetworksPermission()); 98 } 99 100 /** 101 * Get Ethernet configuration 102 * @return the Ethernet Configuration, contained in {@link IpConfiguration}. 103 */ 104 @Override getConfiguration(String iface)105 public IpConfiguration getConfiguration(String iface) { 106 PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); 107 if (mTracker.isRestrictedInterface(iface)) { 108 PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG); 109 } 110 111 return new IpConfiguration(mTracker.getIpConfiguration(iface)); 112 } 113 114 /** 115 * Set Ethernet configuration 116 */ 117 @Override setConfiguration(String iface, IpConfiguration config)118 public void setConfiguration(String iface, IpConfiguration config) { 119 throwIfEthernetNotStarted(); 120 121 PermissionUtils.enforceNetworkStackPermission(mContext); 122 if (mTracker.isRestrictedInterface(iface)) { 123 PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG); 124 } 125 126 // TODO: this does not check proxy settings, gateways, etc. 127 // Fix this by making IpConfiguration a complete representation of static configuration. 128 mTracker.updateIpConfiguration(iface, new IpConfiguration(config)); 129 } 130 131 /** 132 * Indicates whether given interface is available. 133 */ 134 @Override isAvailable(String iface)135 public boolean isAvailable(String iface) { 136 PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); 137 if (mTracker.isRestrictedInterface(iface)) { 138 PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG); 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) throws RemoteException { 149 Objects.requireNonNull(listener, "listener must not be null"); 150 PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); 151 mTracker.addListener(listener, hasUseRestrictedNetworksPermission()); 152 } 153 154 /** 155 * Removes a listener. 156 * @param listener A {@link IEthernetServiceListener} to remove. 157 */ removeListener(IEthernetServiceListener listener)158 public void removeListener(IEthernetServiceListener listener) { 159 if (listener == null) { 160 throw new IllegalArgumentException("listener must not be null"); 161 } 162 PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); 163 mTracker.removeListener(listener); 164 } 165 166 @Override setIncludeTestInterfaces(boolean include)167 public void setIncludeTestInterfaces(boolean include) { 168 PermissionUtils.enforceNetworkStackPermissionOr(mContext, 169 android.Manifest.permission.NETWORK_SETTINGS); 170 mTracker.setIncludeTestInterfaces(include); 171 } 172 173 @Override requestTetheredInterface(ITetheredInterfaceCallback callback)174 public void requestTetheredInterface(ITetheredInterfaceCallback callback) { 175 Objects.requireNonNull(callback, "callback must not be null"); 176 PermissionUtils.enforceNetworkStackPermissionOr(mContext, 177 android.Manifest.permission.NETWORK_SETTINGS); 178 mTracker.requestTetheredInterface(callback); 179 } 180 181 @Override releaseTetheredInterface(ITetheredInterfaceCallback callback)182 public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { 183 Objects.requireNonNull(callback, "callback must not be null"); 184 PermissionUtils.enforceNetworkStackPermissionOr(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 (!PermissionUtils.hasDumpPermission(mContext, TAG, pw)) return; 193 194 pw.println("Current Ethernet state: "); 195 pw.increaseIndent(); 196 mTracker.dump(fd, pw, args); 197 pw.decreaseIndent(); 198 199 pw.println("Handler:"); 200 pw.increaseIndent(); 201 mHandler.dump(new PrintWriterPrinter(pw), "EthernetServiceImpl"); 202 pw.decreaseIndent(); 203 } 204 enforceNetworkManagementPermission()205 private void enforceNetworkManagementPermission() { 206 mContext.enforceCallingOrSelfPermission( 207 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS, 208 "EthernetServiceImpl"); 209 } 210 enforceManageTestNetworksPermission()211 private void enforceManageTestNetworksPermission() { 212 mContext.enforceCallingOrSelfPermission( 213 android.Manifest.permission.MANAGE_TEST_NETWORKS, 214 "EthernetServiceImpl"); 215 } 216 validateOrSetNetworkSpecifier(String iface, NetworkCapabilities nc)217 private void validateOrSetNetworkSpecifier(String iface, NetworkCapabilities nc) { 218 final NetworkSpecifier spec = nc.getNetworkSpecifier(); 219 if (spec == null) { 220 nc.setNetworkSpecifier(new EthernetNetworkSpecifier(iface)); 221 return; 222 } 223 if (!(spec instanceof EthernetNetworkSpecifier)) { 224 throw new IllegalArgumentException("Invalid specifier type for request."); 225 } 226 if (!((EthernetNetworkSpecifier) spec).getInterfaceName().matches(iface)) { 227 throw new IllegalArgumentException("Invalid interface name set on specifier."); 228 } 229 } 230 maybeValidateTestCapabilities(String iface, NetworkCapabilities nc)231 private void maybeValidateTestCapabilities(String iface, NetworkCapabilities nc) { 232 if (!mTracker.isValidTestInterface(iface)) { 233 return; 234 } 235 if (!nc.hasTransport(TRANSPORT_TEST)) { 236 throw new IllegalArgumentException( 237 "Updates to test interfaces must have NetworkCapabilities.TRANSPORT_TEST."); 238 } 239 } 240 maybeValidateEthernetTransport(String iface, NetworkCapabilities nc)241 private void maybeValidateEthernetTransport(String iface, NetworkCapabilities nc) { 242 if (mTracker.isValidTestInterface(iface)) { 243 return; 244 } 245 if (!nc.hasSingleTransport(TRANSPORT_ETHERNET)) { 246 throw new IllegalArgumentException("Invalid transport type for request."); 247 } 248 } 249 enforceAdminPermission(final String iface, boolean enforceAutomotive, final String logMessage)250 private void enforceAdminPermission(final String iface, boolean enforceAutomotive, 251 final String logMessage) { 252 if (mTracker.isValidTestInterface(iface)) { 253 enforceManageTestNetworksPermission(); 254 } else { 255 enforceNetworkManagementPermission(); 256 if (enforceAutomotive) { 257 enforceAutomotiveDevice(logMessage); 258 } 259 } 260 } 261 262 @Override updateConfiguration(@onNull final String iface, @NonNull final EthernetNetworkUpdateRequest request, @Nullable final INetworkInterfaceOutcomeReceiver cb)263 public void updateConfiguration(@NonNull final String iface, 264 @NonNull final EthernetNetworkUpdateRequest request, 265 @Nullable final INetworkInterfaceOutcomeReceiver cb) { 266 Objects.requireNonNull(iface); 267 Objects.requireNonNull(request); 268 throwIfEthernetNotStarted(); 269 270 // TODO: validate that iface is listed in overlay config_ethernet_interfaces 271 // only automotive devices are allowed to set the NetworkCapabilities using this API 272 final NetworkCapabilities nc = request.getNetworkCapabilities(); 273 enforceAdminPermission( 274 iface, nc != null, "updateConfiguration() with non-null capabilities"); 275 if (nc != null) { 276 validateOrSetNetworkSpecifier(iface, nc); 277 maybeValidateTestCapabilities(iface, nc); 278 maybeValidateEthernetTransport(iface, nc); 279 } 280 281 mTracker.updateConfiguration( 282 iface, request.getIpConfiguration(), nc, new EthernetCallback(cb)); 283 } 284 285 @Override enableInterface(@onNull final String iface, @Nullable final INetworkInterfaceOutcomeReceiver cb)286 public void enableInterface(@NonNull final String iface, 287 @Nullable final INetworkInterfaceOutcomeReceiver cb) { 288 Log.i(TAG, "enableInterface called with: iface=" + iface + ", cb=" + cb); 289 Objects.requireNonNull(iface); 290 throwIfEthernetNotStarted(); 291 292 enforceAdminPermission(iface, false, "enableInterface()"); 293 294 mTracker.setInterfaceEnabled(iface, true /* enabled */, new EthernetCallback(cb)); 295 } 296 297 @Override disableInterface(@onNull final String iface, @Nullable final INetworkInterfaceOutcomeReceiver cb)298 public void disableInterface(@NonNull final String iface, 299 @Nullable final INetworkInterfaceOutcomeReceiver cb) { 300 Log.i(TAG, "disableInterface called with: iface=" + iface + ", cb=" + cb); 301 Objects.requireNonNull(iface); 302 throwIfEthernetNotStarted(); 303 304 enforceAdminPermission(iface, false, "disableInterface()"); 305 306 mTracker.setInterfaceEnabled(iface, false /* enabled */, new EthernetCallback(cb)); 307 } 308 309 @Override setEthernetEnabled(boolean enabled)310 public void setEthernetEnabled(boolean enabled) { 311 PermissionUtils.enforceNetworkStackPermissionOr(mContext, 312 android.Manifest.permission.NETWORK_SETTINGS); 313 314 mTracker.setEthernetEnabled(enabled); 315 } 316 317 @Override getInterfaceList()318 public List<String> getInterfaceList() { 319 PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); 320 return mTracker.getInterfaceList(); 321 } 322 } 323