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