本博客从以太网的服务注册开始,着急的看官直接Step 3 (。・∀・)ノ゙.
system_server进程中的服务启动方式有两种:
1.一种是通过SystemServiceManager的startService()。该方法用于启动继承于SystemService的服务。主要功能:创建serviceClass类的对象,将刚创建对象添加到SystemServiceManager的成员变量mServices,再调用刚创建对象的onStart()方法,方法中调用publishBinderService将service注册到ServiceManager。当SystemService到一定阶段,进入相应的Phase时,会调用SystemServiceManager的startBootPhase()回调方法,该方法会循环遍历所有向SystemServiceManager注册过的service的onBootPhase()方法,service针对各个阶段需要做怎样的处理或者是不做任何处理。
2.另一种是通过ServiceManager的addService(String name, IBinder service),该方法用于初始化继承于IBinder的服务。主要功能将该服务向Native层的service Manager注册服务。
以太网的Service启动属于第一种. 虽然文字描述相对抽象,但是由于以太网服务的草鸡简单,所以以太网Service的注册和启动完全不是事儿,OK,开启以太网Service服务(EthernetService)注册之旅.先上代码:
先来看看系统的进程的入口SystemServer ,main方法里通过SystemServiceManage启动EthernetService
//frameworks/base/services/Java/com/Android/server/SystemServer.java
public final class SystemServer {
private static final String ETHERNET_SERVICE_CLASS =
"com.android.server.ethernet.EthernetService";
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
startOtherServices();
}
private void startOtherServices() {
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)) {
mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
}
}
EthernetService 被启动之后就干了三件事儿:
1.构造函数中创建EthernetServiceImpl 对象
2.在onStart()方法 中将EthernetServiceImpl对象注册进了ServiceManager。
3.当系统进入到 PHASE_SYSTEM_SERVICES_READY时状态时,EthernetService的onBootPhase()方法被触发,调用EthernetServiceImpl .Start();
//frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetService.java
public final class EthernetService extends SystemService {
private static final String TAG = "EthernetService";
final EthernetServiceImpl mImpl;
public EthernetService(Context context) {
super(context);
mImpl = new EthernetServiceImpl(context);
}
@Override
public void onStart() {
// 将ServiceImpl注册到ServiceManager
Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE);
publishBinderService(Context.ETHERNET_SERVICE, mImpl);
}
@Override
public void onBootPhase(int phase) {
//当系统运行到PHASE_SYSTEM_SERVICES_READY状态是时,Service启动EthernetServiceImpl
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mImpl.start();
}
}
}
上面说到,EthernetService创建EthernetServiceImpl 对象.调用EthernetServiceImpl start方法.继续跟踪代码…
//frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java
public class EthernetServiceImpl extends IEthernetManager.Stub {
private final EthernetConfigStore mEthernetConfigStore;
//以太网配置信息类
private IpConfiguration mIpConfiguration;
private final EthernetNetworkFactory mTracker;
private final RemoteCallbackList mListeners =
new RemoteCallbackList();
public EthernetServiceImpl(Context context) {
mContext = context;
Log.i(TAG, "Creating EthernetConfigStore");
mEthernetConfigStore = new EthernetConfigStore();
//读取以太网信息
mIpConfiguration = mEthernetConfigStore.readIpAndProxyConfigurations();
Log.i(TAG, "Read stored IP configuration: " + mIpConfiguration);
mTracker = new EthernetNetworkFactory(mListeners);
}
public void start() {
Log.i(TAG, "Starting Ethernet service");
HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
mTracker.start(mContext, mHandler);
mStarted.set(true);
/* int ethernet_on = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ETHERNET_ON, 0);
if(ethernet_on == 0 ) {
setEthernetEnabled(false);
} */
}
//frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetConfigStore.java
public class EthernetConfigStore extends IpConfigStore {
private static final String ipConfigFile = Environment.getDataDirectory() +
"/misc/ethernet/ipconfig.txt";
public EthernetConfigStore() {
}
public IpConfiguration readIpAndProxyConfigurations() {
SparseArray networks = readIpAndProxyConfigurations(ipConfigFile);
if (networks.size() == 0) {
Log.w(TAG, "No Ethernet configuration found. Using default.");
return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null);
}
if (networks.size() > 1) {
// Currently we only support a single Ethernet interface.
Log.w(TAG, "Multiple Ethernet configurations detected. Only reading first one.");
}
return networks.valueAt(0);
}
1.手动配置好一份静态ip,这是ipconfig.txt中存储的就是静态ip了。
2.取出以太网配置文件: ipconfig.txt
进入命令行,输入
adb root
adb pull /data/misc/ethernet/ipconfig.txt
因为是在桌面输入的命令行,所以复制出的ipconfig.txt 的位置在桌面
3.device.mk文件中 将 ipconfig.txt 预设置到固定位置
1)将刚刚拷贝的ipconfig.txt 文件复制到与device.mk同目录下.
2)找到一份源码编译时一定会编译的device.mk 文件,在device.mk中添加
PRODUCT_COPY_FILES += $(LOCAL_PATH)/ipconfig.txt:system/etc/ipconfig.txt
3)将上面提到的EthernetConfigStore 类中的ipConfigFile 修改为
private static final String ipConfigFile = Environment.getRootDirectory() +
"/etc/ipconfig.txt";
完活
初步估计是关于网口连接时的广播注册,和 Binder 调用. 有个现象应该和他有关,在没有接网线之前,以太网显示状态位static ,但是没有ip ,网关 , 掩码等信息.调查ing