import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.tizen.emulator.skin.EmulatorSkin;
import org.tizen.emulator.skin.comm.ICommunicator;
+import org.tizen.emulator.skin.comm.ICommunicator.SendCommand;
import org.tizen.emulator.skin.comm.sock.data.ISendData;
import org.tizen.emulator.skin.comm.sock.data.StartData;
import org.tizen.emulator.skin.config.EmulatorConfig;
private boolean isTransferState;
private byte[] receivedData;
+ private long sleep;
+ private long maxWaitTime;
+ private Timer timer;
+
private DataTranfer() {
}
- private void reset() {
- receivedData = null;
- isTransferState = true;
- }
-
private void setData( byte[] data ) {
this.receivedData = data;
isTransferState = false;
}
- public synchronized boolean isTransferState() {
- return isTransferState;
- }
-
- public synchronized byte[] getReceivedData() {
- return receivedData;
- }
-
}
public static final int HEART_BEAT_INTERVAL = 1; //second
public static final int HEART_BEAT_EXPIRE = 5;
+
+ public final static int SCREENSHOT_WAIT_INTERVAL = 3; // milli-seconds
+ public final static int SCREENSHOT_WAIT_LIMIT = 3000; // milli-seconds
+ public final static int DETAIL_INFO_WAIT_INTERVAL = 1; // milli-seconds
+ public final static int DETAIL_INFO_WAIT_LIMIT = 3000; // milli-seconds
private static int reqId;
private DataInputStream dis;
private DataOutputStream dos;
- private DataTranfer dataTransfer;
-
private AtomicInteger heartbeatCount;
-
private boolean isTerminated;
+ private boolean isSensorDaemonStarted;
private ScheduledExecutorService heartbeatExecutor;
- private boolean isSensorDaemonStarted;
+ private DataTranfer screenShotDataTransfer;
+ private DataTranfer detailInfoTransfer;
+ private Thread sendThread;
+ private ConcurrentLinkedQueue<SkinSendData> sendQueue;
+
public SocketCommunicator( EmulatorConfig config, int uId, int windowHandleId, EmulatorSkin skin ) {
this.config = config;
this.windowHandleId = windowHandleId;
this.skin = skin;
- this.dataTransfer = new DataTranfer();
+ this.screenShotDataTransfer = new DataTranfer();
+ this.screenShotDataTransfer.sleep = SCREENSHOT_WAIT_INTERVAL;
+ this.screenShotDataTransfer.maxWaitTime = SCREENSHOT_WAIT_LIMIT;
+
+ this.detailInfoTransfer = new DataTranfer();
+ this.detailInfoTransfer.sleep = DETAIL_INFO_WAIT_INTERVAL;
+ this.detailInfoTransfer.maxWaitTime = DETAIL_INFO_WAIT_LIMIT;
this.heartbeatCount = new AtomicInteger( 0 );
this.heartbeatExecutor = Executors.newSingleThreadScheduledExecutor();
try {
+ sendQueue = new ConcurrentLinkedQueue<SkinSendData>();
+
+ sendThread = new Thread() {
+ @Override
+ public void run() {
+
+ while ( true ) {
+
+ synchronized ( sendThread ) {
+ try {
+ sendThread.wait();
+ } catch ( InterruptedException e ) {
+ logger.log( Level.SEVERE, e.getMessage(), e );
+ }
+ }
+
+ SkinSendData sendData = null;
+ while ( true ) {
+ sendData = sendQueue.poll();
+ if ( null != sendData ) {
+ sendToQEMUInternal( sendData );
+ } else {
+ break;
+ }
+ }
+
+ if ( isTerminated ) {
+ break;
+ }
+
+ }
+
+ }
+ };
+
+ sendThread.start();
+
dis = new DataInputStream( socket.getInputStream() );
dos = new DataOutputStream( socket.getOutputStream() );
}
case SCREEN_SHOT_DATA: {
logger.info( "received SCREEN_SHOT_DATA from QEMU." );
-
- synchronized ( dataTransfer ) {
- byte[] imageData = readData( dis, length );
- dataTransfer.setData( imageData );
- dataTransfer.notifyAll();
- }
-
- logger.info( "finish receiving image data from QEMU." );
+ receiveData( screenShotDataTransfer, length );
break;
}
case DETAIL_INFO_DATA: {
logger.info( "received DETAIL_INFO_DATA from QEMU." );
-
- synchronized ( dataTransfer ) {
- byte[] infoData = readData( dis, length );
- dataTransfer.setData( infoData );
- dataTransfer.notifyAll();
- }
-
- logger.info( "finish receiving info data from QEMU." );
+ receiveData( detailInfoTransfer, length );
break;
}
case SHUTDOWN: {
logger.info( "received RESPONSE_SHUTDOWN from QEMU." );
sendToQEMU( SendCommand.RESPONSE_SHUTDOWN, null );
- isTerminated = true;
terminate();
break;
}
}
+ private void receiveData( DataTranfer dataTransfer, int length ) throws IOException {
+
+ synchronized ( dataTransfer ) {
+
+ if( null != dataTransfer.timer ) {
+ dataTransfer.timer.cancel();
+ }
+
+ byte[] data = readData( dis, length );
+
+ if( null != data ) {
+ logger.info( "finished receiving data from QEMU." );
+ }else {
+ logger.severe( "Fail to receiving data from QEMU." );
+ }
+
+ dataTransfer.isTransferState = false;
+ dataTransfer.timer = null;
+
+ dataTransfer.setData( data );
+ dataTransfer.notifyAll();
+
+ }
+
+ }
+
private byte[] readData( DataInputStream is, int length ) throws IOException {
if ( 0 >= length ) {
}
- public synchronized void sendToQEMU( SendCommand command, ISendData data, boolean useDataTransfer ) {
+ public synchronized DataTranfer sendToQEMU( SendCommand command, ISendData data, boolean useDataTransfer ) {
+
+ DataTranfer dataTranfer = null;
+
if ( useDataTransfer ) {
- this.dataTransfer.reset();
+
+ if ( SendCommand.SCREEN_SHOT.equals( command ) ) {
+ dataTranfer = resetDataTransfer( screenShotDataTransfer );
+ } else if ( SendCommand.DETAIL_INFO.equals( command ) ) {
+ dataTranfer = resetDataTransfer( detailInfoTransfer );
+ }
}
+
sendToQEMU( command, data );
+
+ return dataTranfer;
+
}
+
+ private DataTranfer resetDataTransfer( final DataTranfer dataTransfer ) {
+
+ synchronized ( dataTransfer ) {
+
+ if ( dataTransfer.isTransferState ) {
+ logger.severe( "Already transter state for getting data." );
+ return null;
+ }
+
+ dataTransfer.isTransferState = true;
+
+ Timer timer = new Timer();
+ dataTransfer.timer = timer;
+ TimerTask timerTask = new TimerTask() {
+ @Override
+ public void run() {
+ synchronized ( dataTransfer ) {
+ dataTransfer.isTransferState = false;
+ dataTransfer.timer = null;
+ dataTransfer.receivedData = null;
+ }
+ }
+ };
+ timer.schedule( timerTask, dataTransfer.maxWaitTime );
+
+ return dataTransfer;
+
+ }
+
+ }
+
@Override
- public synchronized void sendToQEMU( SendCommand command, ISendData data ) {
+ public void sendToQEMU( SendCommand command, ISendData data ) {
+
+ sendQueue.add( new SkinSendData( command, data ) );
+
+ synchronized ( sendThread ) {
+ sendThread.notifyAll();
+ }
+
+ }
+
+ private void sendToQEMUInternal( SkinSendData sendData ) {
try {
+ if( null == sendData ) {
+ return;
+ }
+
+ SendCommand command = sendData.getCommand();
+ ISendData data = sendData.getSendData();
+
reqId = ( Integer.MAX_VALUE == reqId ) ? 0 : ++reqId;
ByteArrayOutputStream bao = new ByteArrayOutputStream();
}
+ public byte[] getReceivedData( DataTranfer dataTranfer ) {
+
+ if( null == dataTranfer ) {
+ return null;
+ }
+
+ synchronized ( dataTranfer ) {
+
+ int count = 0;
+ byte[] receivedData = null;
+ long sleep = dataTranfer.sleep;
+ long maxWaitTime = dataTranfer.maxWaitTime;
+ int limitCount = (int) ( maxWaitTime / sleep );
+
+ while ( dataTranfer.isTransferState ) {
+
+ if ( limitCount < count ) {
+ logger.severe( "time out for receiving data from skin server." );
+ dataTranfer.receivedData = null;
+ break;
+ }
+
+ try {
+ dataTranfer.wait( sleep );
+ } catch ( InterruptedException e ) {
+ logger.log( Level.SEVERE, e.getMessage(), e );
+ }
+
+ count++;
+ logger.info( "wait data... count:" + count );
+
+ }
+
+ receivedData = dataTranfer.receivedData;
+ dataTranfer.receivedData = null;
+
+ return receivedData;
+
+ }
+
+ }
+
public Socket getSocket() {
return socket;
}
heartbeatCount.set( 0 );
}
- public DataTranfer getDataTranfer() {
- return dataTransfer;
- }
-
@Override
public void terminate() {
+
+ isTerminated = true;
+
if ( null != heartbeatExecutor ) {
heartbeatExecutor.shutdownNow();
}
+
+ if( null != sendThread ) {
+ synchronized ( sendThread ) {
+ sendThread.notifyAll();
+ }
+ }
+
IOUtil.closeSocket( socket );
+
synchronized ( this ) {
skin.shutdown();
}
+
}
public void resetSkin( EmulatorSkin skin ) {
}
}
+
+class SkinSendData {
+
+ private SendCommand command;
+ private ISendData data;
+
+ public SkinSendData( SendCommand command, ISendData data ) {
+ this.command = command;
+ this.data = data;
+ }
+
+ public SendCommand getCommand() {
+ return command;
+ }
+
+ public ISendData getSendData() {
+ return data;
+ }
+
+}
\ No newline at end of file
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
-import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.swt.SWT;
*/
public class DetailInfoDialog extends SkinDialog {
- public final static int DETAIL_INFO_WAIT_INTERVAL = 1; // milli-seconds
- public final static int DETAIL_INFO_WAIT_LIMIT = 3000; // milli-seconds
public final static String DATA_DELIMITER = "#";
private Logger logger = SkinLogger.getSkinLogger( DetailInfoDialog.class ).getLogger();
String infoData = null;
- communicator.sendToQEMU( SendCommand.DETAIL_INFO, null, true );
- DataTranfer dataTranfer = communicator.getDataTranfer();
-
- int count = 0;
- boolean isFail = false;
- byte[] receivedData = null;
- int limitCount = DETAIL_INFO_WAIT_LIMIT / DETAIL_INFO_WAIT_INTERVAL;
-
- synchronized ( dataTranfer ) {
-
- while ( dataTranfer.isTransferState() ) {
-
- if ( limitCount < count ) {
- isFail = true;
- break;
- }
-
- try {
- dataTranfer.wait( DETAIL_INFO_WAIT_INTERVAL );
- } catch ( InterruptedException e ) {
- logger.log( Level.SEVERE, e.getMessage(), e );
- }
-
- count++;
- logger.info( "wait detail info data... count:" + count );
-
- }
-
- receivedData = dataTranfer.getReceivedData();
-
- }
-
- if ( isFail ) {
-
- logger.severe( "Fail to get detail info from server." );
- SkinUtil.openMessage( shell, null, "Internal error.", SWT.ICON_ERROR, config );
+ DataTranfer dataTranfer = communicator.sendToQEMU( SendCommand.DETAIL_INFO, null, true );
+ byte[] receivedData = communicator.getReceivedData( dataTranfer );
+ if ( null != receivedData ) {
+ infoData = new String( receivedData );
} else {
-
- if ( null != receivedData ) {
- infoData = new String( receivedData );
- } else {
- logger.severe( "Received detail info is null" );
- SkinUtil.openMessage( shell, null, "Internal error.", SWT.ICON_ERROR, config );
- }
-
+ logger.severe( "Fail to get detail info." );
+ SkinUtil.openMessage( shell, null, "Fail to get detail info.", SWT.ICON_ERROR, config );
}
return infoData;
public final static String DEFAULT_FILE_EXTENSION = "png";
- public final static int SCREENSHOT_WAIT_INTERVAL = 3; // milli-seconds
- public final static int SCREENSHOT_WAIT_LIMIT = 3000; // milli-seconds
-
public final static int RED_MASK = 0x0000FF00;
public final static int GREEN_MASK = 0x00FF0000;
public final static int BLUE_MASK = 0xFF000000;
private void capture() throws ScreenShotException {
- communicator.sendToQEMU( SendCommand.SCREEN_SHOT, null, true );
- DataTranfer dataTranfer = communicator.getDataTranfer();
-
- int count = 0;
- boolean isFail = false;
- byte[] receivedData = null;
- int limitCount = SCREENSHOT_WAIT_LIMIT / SCREENSHOT_WAIT_INTERVAL;
-
- synchronized ( dataTranfer ) {
-
- while ( dataTranfer.isTransferState() ) {
-
- if ( limitCount < count ) {
- isFail = true;
- break;
- }
-
- try {
- dataTranfer.wait( SCREENSHOT_WAIT_INTERVAL );
- } catch ( InterruptedException e ) {
- logger.log( Level.SEVERE, e.getMessage(), e );
- }
+ DataTranfer dataTranfer = communicator.sendToQEMU( SendCommand.SCREEN_SHOT, null, true );
+ byte[] receivedData = communicator.getReceivedData( dataTranfer );
- count++;
- logger.info( "wait image data... count:" + count );
+ if ( null != receivedData ) {
+ if ( null != this.image ) {
+ this.image.dispose();
}
- receivedData = dataTranfer.getReceivedData();
+ int width = config.getArgInt( ArgsConstants.RESOLUTION_WIDTH );
+ int height = config.getArgInt( ArgsConstants.RESOLUTION_HEIGHT );
+ ImageData imageData = new ImageData( width, height, COLOR_DEPTH, paletteData, 1, receivedData );
- }
-
- if ( !isFail ) {
-
- if ( null != receivedData ) {
-
- if ( null != this.image ) {
- this.image.dispose();
- }
+ RotationInfo rotation = getCurrentRotation();
+ imageData = rotateImageData( imageData, rotation );
- int width = config.getArgInt( ArgsConstants.RESOLUTION_WIDTH );
- int height = config.getArgInt( ArgsConstants.RESOLUTION_HEIGHT );
- ImageData imageData = new ImageData( width, height, COLOR_DEPTH, paletteData, 1, receivedData );
-
- RotationInfo rotation = getCurrentRotation();
- imageData = rotateImageData( imageData, rotation );
-
- this.image = new Image( Display.getDefault(), imageData );
- imageCanvas.redraw();
-
- } else {
- throw new ScreenShotException( "Received image data is null." );
- }
+ this.image = new Image( Display.getDefault(), imageData );
+ imageCanvas.redraw();
} else {
- throw new ScreenShotException( "Fail to received image data." );
+ throw new ScreenShotException( "Fail to get image data." );
}
}