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