/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ddmlib;
import com.android.ddmlib.Client;
import com.android.ddmlib.log.LogReceiver;
import java.io.IOException;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A Device. It can be a physical device or an emulator.
*
* TODO: make this class package-protected, and shift all callers to use IDevice
*/
public final class Device implements IDevice {
/**
* The state of a device.
*/
public static enum DeviceState {
BOOTLOADER("bootloader"), //$NON-NLS-1$
OFFLINE("offline"), //$NON-NLS-1$
ONLINE("device"); //$NON-NLS-1$
private String mState;
DeviceState(String state) {
mState = state;
}
/**
* Returns a {@link DeviceState} from the string returned by <code>adb devices</code>.
* @param state the device state.
* @return a {@link DeviceState} object or <code>null</code> if the state is unknown.
*/
public static DeviceState getState(String state) {
for (DeviceState deviceState : values()) {
if (deviceState.mState.equals(state)) {
return deviceState;
}
}
return null;
}
}
/** Emulator Serial Number regexp. */
final static String RE_EMULATOR_SN = "emulator-(\\d+)"; //$NON-NLS-1$
/** Serial number of the device */
String serialNumber = null;
/** Name of the AVD */
String mAvdName = null;
/** State of the device. */
DeviceState state = null;
/** Device properties. */
private final Map<String, String> mProperties = new HashMap<String, String>();
private final ArrayList<Client> mClients = new ArrayList<Client>();
private DeviceMonitor mMonitor;
/**
* Socket for the connection monitoring client connection/disconnection.
*/
private SocketChannel mSocketChannel;
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getSerialNumber()
*/
public String getSerialNumber() {
return serialNumber;
}
public String getAvdName() {
return mAvdName;
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getState()
*/
public DeviceState getState() {
return state;
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getProperties()
*/
public Map<String, String> getProperties() {
return Collections.unmodifiableMap(mProperties);
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getPropertyCount()
*/
public int getPropertyCount() {
return mProperties.size();
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getProperty(java.lang.String)
*/
public String getProperty(String name) {
return mProperties.get(name);
}
@Override
public String toString() {
return serialNumber;
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#isOnline()
*/
public boolean isOnline() {
return state == DeviceState.ONLINE;
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#isEmulator()
*/
public boolean isEmulator() {
return serialNumber.matches(RE_EMULATOR_SN);
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#isOffline()
*/
public boolean isOffline() {
return state == DeviceState.OFFLINE;
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#isBootLoader()
*/
public boolean isBootLoader() {
return state == DeviceState.BOOTLOADER;
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#hasClients()
*/
public boolean hasClients() {
return mClients.size() > 0;
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getClients()
*/
public Client[] getClients() {
synchronized (mClients) {
return mClients.toArray(new Client[mClients.size()]);
}
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getClient(java.lang.String)
*/
public Client getClient(String applicationName) {
synchronized (mClients) {
for (Client c : mClients) {
if (applicationName.equals(c.getClientData().getClientDescription())) {
return c;
}
}
}
return null;
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getSyncService()
*/
public SyncService getSyncService() {
SyncService syncService = new SyncService(AndroidDebugBridge.sSocketAddr, this);
if (syncService.openSync()) {
return syncService;
}
return null;
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getFileListingService()
*/
public FileListingService getFileListingService() {
return new FileListingService(this);
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getScreenshot()
*/
public RawImage getScreenshot() throws IOException {
return AdbHelper.getFrameBuffer(AndroidDebugBridge.sSocketAddr, this);
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#executeShellCommand(java.lang.String, com.android.ddmlib.IShellOutputReceiver)
*/
public void executeShellCommand(String command, IShellOutputReceiver receiver)
throws IOException {
AdbHelper.executeRemoteCommand(AndroidDebugBridge.sSocketAddr, command, this,
receiver);
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#runEventLogService(com.android.ddmlib.log.LogReceiver)
*/
public void runEventLogService(LogReceiver receiver) throws IOException {
AdbHelper.runEventLogService(AndroidDebugBridge.sSocketAddr, this, receiver);
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#runLogService(com.android.ddmlib.log.LogReceiver)
*/
public void runLogService(String logname,
LogReceiver receiver) throws IOException {
AdbHelper.runLogService(AndroidDebugBridge.sSocketAddr, this, logname, receiver);
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#createForward(int, int)
*/
public boolean createForward(int localPort, int remotePort) {
try {
return AdbHelper.createForward(AndroidDebugBridge.sSocketAddr, this,
localPort, remotePort);
} catch (IOException e) {
Log.e("adb-forward", e); //$NON-NLS-1$
return false;
}
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#removeForward(int, int)
*/
public boolean removeForward(int localPort, int remotePort) {
try {
return AdbHelper.removeForward(AndroidDebugBridge.sSocketAddr, this,
localPort, remotePort);
} catch (IOException e) {
Log.e("adb-remove-forward", e); //$NON-NLS-1$
return false;
}
}
/*
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getClientName(int)
*/
public String getClientName(int pid) {
synchronized (mClients) {
for (Client c : mClients) {
if (c.getClientData().getPid() == pid) {
return c.getClientData().getClientDescription();
}
}
}
return null;
}
Device(DeviceMonitor monitor) {
mMonitor = monitor;
}
DeviceMonitor getMonitor() {
return mMonitor;
}
void addClient(Client client) {
synchronized (mClients) {
mClients.add(client);
}
}
List<Client> getClientList() {
return mClients;
}
boolean hasClient(int pid) {
synchronized (mClients) {
for (Client client : mClients) {
if (client.getClientData().getPid() == pid) {
return true;
}
}
}
return false;
}
void clearClientList() {
synchronized (mClients) {
mClients.clear();
}
}
/**
* Sets the client monitoring socket.
* @param socketChannel the sockets
*/
void setClientMonitoringSocket(SocketChannel socketChannel) {
mSocketChannel = socketChannel;
}
/**
* Returns the client monitoring socket.
*/
SocketChannel getClientMonitoringSocket() {
return mSocketChannel;
}
/**
* Removes a {@link Client} from the list.
* @param client the client to remove.
* @param notify Whether or not to notify the listeners of a change.
*/
void removeClient(Client client, boolean notify) {
mMonitor.addPortToAvailableList(client.getDebuggerListenPort());
synchronized (mClients) {
mClients.remove(client);
}
if (notify) {
mMonitor.getServer().deviceChanged(this, CHANGE_CLIENT_LIST);
}
}
void update(int changeMask) {
mMonitor.getServer().deviceChanged(this, changeMask);
}
void update(Client client, int changeMask) {
mMonitor.getServer().clientChanged(client, changeMask);
}
void addProperty(String label, String value) {
mProperties.put(label, value);
}
}
|