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