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