这个类是ddmlib库的一个类,上面类图列出了DeviceMonitor关键的成员变量和方法,我们先对它们做初步的介绍,这样有利于大家更好的跟随我在下面对这个类的源代码进行分析:
mServer: DebugBridgeServer对象,因为需要向ADB服务器发送相应的设备监控命令,所以在DeviceMonitor初始化的时候会把一个DebugBridgeServer实例传进来保存到mServer中
mMainAdbConnection: 一个SocketChannel实例,DeviceMonitor在对每个设备进行监控之前需要先和ADB服务器建立链接
mDevices: 代表一个安卓设备的Device实例组成的一个列表。注意这个Device在整个MonkeyRunner框架中非常的重要,如前面所述,它基本上可以被看成是真实安卓设备在PC端的一个代理,很多发送给ADB服务器的命令最终都是通过它发送出去的。DeviceMonitor监控线程一旦发现新设备就会建立一个Device实例并放到mDevices列表里面,反之,如果一个设备被移除,就会从mDevices列表中移除
start: 一个默认权限的方法,所以可以被同一个ddmlib包里面的AndroidDebugBridge调用。它的作用是启动设备列表监控线程,线程循环主体在下面描述的deviceMonitorLoop方法里面
getDevices: 返回上面的mDevices设备。MonkeyRunner类的waitForConnection方法在建立与设备的连接时,最终会调用到这个方法来获得所有设备并根据设备序列号找到目标设备去连接
deviceMonitorLoop: 向ADB服务器发送”host:track-devices”设备监控命令来循环获取最新的字串类型的设备列表,这个命令类似于在命令行发送”adb devices”来获得当前连接的设备列表,但是不同的地方是该监控命令发送给ADB服务器后,ADB服务器会周期性的更新设备列表然后主动发送回来。每个循环完成后,如果发现ADB服务器有数据过来,都会调用下面的processIncomingDeviceData方法来作更新mDevices设备列表等事宜
sendDeviceListMonitoringRequest:上面的deviceMonitorLoop方法调用来往ADB服务器发送”host:track-devices”设备列表监控命令的方法
processIncomingDeviceData:上面的deviceMonitorLoop方法在发现ADB服务器有数据过来的时候会调用这个方法来从与ADB服务器连接的mMainAdbConnection这个SocketChannel中把最新的字串类型设备列表读出来,然后为每个设备实例化一个Device实例并将这些实例放到一个列表中,传送给下面的updateDevices方法来处理
updateDevices: 在收到上面processIncomingDeviceData发送过来的最新的Device类型的设备列表后,updateDevices会根据当前持有的mDevices设备列表来检查究竟哪些设备是新增加进来的,哪些是被移除掉的,哪些是状态改变了的来作相应的处理:
新设备: 将该设备加入到DeviceMonitor维护的mDevices设备列表里面,并调用下面的startMonitoringDevice来为该设备的每个可调试应用进程建立一个监控线程来监控该VM进程
设备变成ONLINE状态: 将mDevices设备列表里面对应的设备设置成ONLINE状态,并调用下面的startMonitoringDevice来为该设备的每个可调试应用进程建立一个监控线程来监控该VM进程
设备从ONLINE变成其他状态:将mDevices设备列表里面对应的设备设置成对应状态
移除设备: 将该设备从当前设备列表mDevices中移除掉
startMonitoringDevice: 获得对应设备中的所有可调试VM进程的PID列表(可调试进程指的是DalvikVM中每个启动了JDWP线程让DDMS等调试工具连接的进程),连接上每个VM的调试端口并建立对应的客户端监控线程来监控该进程。因为客户端机器下层的JDWP相关的代码主要是给DDMS等监控调试工具使用的,所以本书不会往下作深入分析
sendDeviceMonitoringRequest: startMonitoringDevice方法调用本方法来获得指定设备可调试的所有进程的PID,其实发送的就是”track-jdwp“命令
有了以上的基本认识后,我们继续往下分析其代码实现。AndroidDebugBridge启动起来后,下一步就是把这个ADB实例传到DeviceMonitor来去监测所有连接到adb服务器也就是pc主机端的android设备的状态:
70 DeviceMonitor(AndroidDebugBridge server)
71 {
72 this.mServer = server;
73
74 this.mDebuggerPorts.add(Integer.valueOf(DdmPreferences.getDebugPortBase()));
75 }
代码8-4-1 DeviceMonitor构造函数
保存好AndroidDebugBridge实例后,下一步就是继续AndroidDebugBridge启动函数start()启动DeviceMonitor设备监控线程:
79 void start()
80 {
81 new Thread("Device List Monitor")
82 {
83 public void run() {
84 DeviceMonitor.this.deviceMonitorLoop();
85 }
86 }.start();
87 }
代码8-4-2 DeviceMonitor - start
第81-86行,整个方法的主体就是创建一个”Device List Monitor”的线程。线程运行方法run直接调用DeviceMonitor的deviceMonitorLoop方法来进行无限循环监控设备状态了。
155 private void deviceMonitorLoop()
156 {
157 do
158 {
159 try
160 {
161 if (this.mMainAdbConnection == null) {
162 Log.d("DeviceMonitor", "Opening adb connection");
163 this.mMainAdbConnection =
openAdbConnection();
164 if (this.mMainAdbConnection == null) {
165 this.mConnectionAttempt += 1;
166 Log.e("DeviceMonitor", "Connection attempts: " + this.mConnectionAttempt);
167 if (this.mConnectionAttempt > 10) {
168 if (!this.mServer.startAdb()) {
169 this.mRestartAttemptCount += 1;
170 Log.e("DeviceMonitor", "adb restart attempts: " + this.mRestartAttemptCount);
171 }
172 else {
173 this.mRestartAttemptCount = 0;
174 }
175 }
176 waitABit();
177 } else {
178 Log.d("DeviceMonitor", "Connected to adb for device monitoring");
179 this.mConnectionAttempt = 0;
180 }
181 }
182
183 if ((this.mMainAdbConnection != null) &&
(!this.mMonitoring)) {
184 this.mMonitoring = sendDeviceListMonitoringRequest();
185 }
186
187 if (this.mMonitoring)
188 {
189 int length = readLength(this.mMainAdbConnection, this.mLengthBuffer);
190
191 if (length >= 0)
192 {
193 processIncomingDeviceData(length);
194
195
196 this.mInitialDeviceListDone = true;
197 }
198 }
199 }
200 catch (AsynchronousCloseException ace) {}catch (TimeoutException ioe)
201 {
202 handleExpectionInMonitorLoop(ioe);
203 } catch (IOException ioe) {
204 handleExpectionInMonitorLoop(ioe);
205 }
206 } while (!this.mQuit);
207 }
代码8-4-3 DeviceMonitor - deviceMonitorLoop