diff -r f65f740e69f9 -r 8e12a575a9b5 sysperfana/memspyext/com.nokia.s60tools.memspy/src/com/nokia/s60tools/memspy/model/TraceCoreEngine.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/memspyext/com.nokia.s60tools.memspy/src/com/nokia/s60tools/memspy/model/TraceCoreEngine.java Wed Apr 21 20:01:08 2010 +0300
@@ -0,0 +1,1093 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+
+package com.nokia.s60tools.memspy.model;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Date;
+
+import javax.swing.Timer;
+
+import com.nokia.s60tools.memspy.common.ProductInfoRegistry;
+import com.nokia.s60tools.memspy.containers.SWMTLogInfo;
+import com.nokia.s60tools.memspy.containers.ThreadInfo;
+import com.nokia.s60tools.memspy.containers.SWMTLogInfo.SWMTLogType;
+import com.nokia.s60tools.memspy.export.ITraceClientNotificationsIf;
+import com.nokia.s60tools.memspy.interfaces.IMemSpyTraceListener;
+import com.nokia.s60tools.memspy.interfaces.IMemSpyTraceListener.LauncherAction;
+import com.nokia.s60tools.memspy.interfaces.IMemSpyTraceListener.LauncherErrorType;
+import com.nokia.s60tools.memspy.plugin.MemSpyPlugin;
+import com.nokia.s60tools.memspy.preferences.MemSpyPreferences;
+import com.nokia.s60tools.memspy.ui.wizards.DeviceOrFileSelectionPage;
+import com.nokia.s60tools.memspy.util.MemSpyConsole;
+import com.nokia.s60tools.util.console.IConsolePrintUtility;
+import com.nokia.s60tools.util.debug.DbgUtility;
+
+
+/**
+ * TraceCoreEngine
class offers public services for starting operations for
+ * getting heap dump and SWMT log data. It creates and manages list of sub tasks
+ * are requested sequentially until main operation chain is over (either successfully
+ * or with error).
+ *
+ * This class is tightly coupled with TraceCoreDataHandler
class
+ * that parses trace data and passes flow control back to TraceCoreEngine
+ * between individual sub tasks.
+ *
+ * @see com.nokia.s60tools.memspy.model.TraceCoreDataHandler.java
+ */
+public class TraceCoreEngine implements ActionListener, ITraceClientNotificationsIf {
+
+ /**
+ * Enumerator for upper level operation progress status. Ordinal order of the operations should not be changed.
+ * Once operation status is advanced to EProgressMemSpyOperationDone
+ * the progress status is not initialized until wizard re-start, connection setting are changed, or an error occurs.
+ *
+ * The enumerator is used in order being able to give user best possible guidance on time-out error when we know
+ * the context in which the error has occurred.
+ */
+ public enum ProgressStatus{
+ EPROGRESS_INITIAL, // Initial status with no progress so far during current session
+ EPROGRESS_MEMSPY_LAUNCHED, // MemSpy has been launched successfully
+ EPROGRESS_FIRST_TASK_LAUNCHED, // First actual task for MemSpy is triggered (i.e. non-MemSpy launch task)
+ EPROGRESS_FIRST_TASK_DONE // First actual task for MemSpy completed successfully (i.e. non-MemSpy launch task)
+ }
+
+ // GroupIDs that are used
+ public final static String MEMSPY_LAUNCH = "10";
+ public final static String MEMSPY_THREAD_LIST = "11";
+ public final static String MEMSPY_THREAD_INFO = "12";
+ public final static String MEMSPY_GET_HEAP_DUMP = "13";
+ public final static String MEMSPY_SWMT_UPDATE = "14";
+ public final static String MEMSPY_SWMT_RESET = "16";
+ public final static String MEMSPY_STOP = "17";
+ public final static String MEMSPY_SET_CATEGORIES_LOW = "19";
+ public final static String MEMSPY_SET_CATEGORIES_HIGH = "20";
+ public final static String MEMSPY_SET_SWMT_HEAP_DUMP = "21";
+ public final static String MEMSPY_SET_HEAP_NAME_FILTER = "SUBSCRIBE_COMM_EVENT_SET_HEAP_NAME_FILTER";
+
+ // Time that device waits for line.
+ private final int SECOND = 1000;
+ private final int DEFAULT_WAIT_TIME = 20 * SECOND; // seconds
+ private final int MAX_WAIT_TIME = 60 * SECOND; // seconds
+ private int currentWaitTime;
+
+ /**
+ * Indicate that MemSpy Launcher data version is not received.
+ */
+ private static final int MEMSPY_LAUNCHER_VERSION_NOT_DEFINED = -1;
+
+ /* timer that is used in error correction */
+ private Timer errorTimer;
+
+ /* boolean value that is true when MemSpy is running */
+ private boolean MemSpyRunning;
+
+ /* Cycle number of swmt logs that is received next time */
+ private int cycleNumber;
+
+ /* interval between swmt logs */
+ private int interval;
+
+ /* timer that is used when receiving SWMT-logs via timer */
+ private Timer intervalTimer;
+
+ /* info of swmt-log that is currently received */
+ private SWMTLogInfo swmtLogInfo;
+
+ // Trace data handler
+ private TraceCoreDataHandler handler;
+
+ // Id of threads that is currently received
+ int threadID;
+
+ // Task list
+ private ArrayList taskList;
+
+ // WizardPage, that is notified when operations are done.
+ private IMemSpyTraceListener wizardPage;
+
+ // Name of the file where heap dumps and SWMT-logs are written.
+ private String currentFile;
+
+ /**
+ * If S60 MemSpy is to be closed between cycles
+ */
+ private boolean resetBetweenCycles = false;
+
+ /**
+ * Stores MemSpy launcher communication version.
+ */
+ private int receivedMemSpyLauncherDataVersion = MEMSPY_LAUNCHER_VERSION_NOT_DEFINED;
+
+ /**
+ * Upper level operation progress status. Ordinal order of the operations should not be changed.
+ * Once operation status is advanced to EProgressMemSpyOperationDone
+ * the progress status is not initialized until wizard re-start, connection setting are changed, or an error occurs.
+ */
+ private ProgressStatus progressStatus = ProgressStatus.EPROGRESS_INITIAL;
+
+ /**
+ * Provides possibly additional error information about the occurred error.
+ */
+ private String additionalErrorInformation;
+
+ /**
+ * Constructor.
+ */
+ public TraceCoreEngine(){
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine() Construct START"); //$NON-NLS-1$
+ this.MemSpyRunning = false;
+ this.handler = new TraceCoreDataHandler(this);
+ this.taskList = new ArrayList();
+ this.errorTimer = null;
+ this.cycleNumber = 1;
+ this.interval = 0;
+ this.swmtLogInfo = null;
+ this.currentWaitTime = DEFAULT_WAIT_TIME;
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine() Construct END"); //$NON-NLS-1$
+ }
+
+ /**
+ * Request thread list from MemSpyLauncher.
+ * @param threadArray array where thread names and id's are written
+ * @param wizard page which is notified when request is finished
+ * @return true, if connection to TraceCore established successfully, else false
+ */
+
+ public boolean requestThreadList( ArrayList threadArray, DeviceOrFileSelectionPage wizard ){
+ this.wizardPage = wizard;
+
+ // Set handler values correct
+ handler.setLastWasName( false );
+ handler.setThreadArray( threadArray );
+
+ // if connection established successfully, return true
+ if( this.connect() ){
+
+ // Set handler values correct
+ handler.setLastWasName( false );
+ handler.setThreadArray( threadArray );
+
+ if( !this.MemSpyRunning ){
+ taskList.add( MEMSPY_LAUNCH );
+ }
+ taskList.add( MEMSPY_THREAD_LIST );
+ return this.runNextTask();
+ }
+ else{
+ return false;
+ }
+
+
+ }
+
+ /**
+ * Request Heap Dump from device and write it into text file
+ * @param threadID ID of thread which is requested from device
+ * @param wizardPage page which is notified when request is finished
+ * @param currentFile path of the file where Heap Dump is written
+ * @return true, if connection to TraceCore established successfully, else false
+ */
+ public boolean requestHeapDump( int threadID, IMemSpyTraceListener wizardPage, String currentFile ){
+
+ this.currentFile = currentFile;
+ this.wizardPage = wizardPage;
+ this.threadID = threadID;
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.requestHeapDump/threadID=" + threadID); //$NON-NLS-1$
+
+ if( this.connect() ){
+
+ // Reset heap type value
+ handler.setHeapTypeCorrect( false );
+
+ // Send id to trace,
+ if( !this.sendIntegerDataToLauncher(threadID) ){
+ launcherError(LauncherErrorType.ACTIVATION);
+ return false;
+ }
+ else{
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.requestHeapDump/activateId => OK"); //$NON-NLS-1$
+ }
+
+ if( !this.MemSpyRunning ){
+ taskList.add( MEMSPY_LAUNCH );
+ }
+
+ // Add tasks into task list
+ taskList.add( MEMSPY_THREAD_INFO );
+ taskList.add( MEMSPY_GET_HEAP_DUMP );
+
+ // start running tasks
+ return this.runNextTask();
+ }
+ else{
+ return false;
+ }
+ }
+
+ /**
+ * Request Heap Dump from device and write it into text file
+ * @param threadID ID of thread which is requested from device
+ * @param wizardPage page which is notified when request is finished
+ * @param currentFile path of the file where Heap Dump is written
+ * @return true, if connection to TraceCore established successfully, else false
+ */
+ public boolean requestHeapDump( String threadID, IMemSpyTraceListener wizardPage, String currentFile ){
+
+ return requestHeapDump( Integer.parseInt(threadID), wizardPage, currentFile );
+
+ }
+
+ /**
+ * Request SWMT-log from device and write it into file
+ * @param wizardPage page which is notified when request is finished
+ * @param currentFile path of the file where Heap Dump is written
+ * @param resetCycles should cycles be reseted
+ * @return true, if connection to TraceCore established successfully, else false
+ */
+ public boolean requestSWMTLog( IMemSpyTraceListener wizardPage, String currentFile, boolean resetCycles){
+ this.currentFile = currentFile;
+ this.wizardPage = wizardPage;
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.requestSWMTLog(resetCycles=" + resetCycles + ")/currentFile: " + currentFile); //$NON-NLS-1$ //$NON-NLS-2$
+
+ // if connection established successfully, return true
+ if( this.connect() ){
+
+ // stop and start MemSpy so that logging is reseted.
+ if( resetCycles == true ){
+ taskList.add( MEMSPY_STOP );
+ taskList.add( MEMSPY_LAUNCH );
+ }
+
+ // If MemSpy is not running launch it
+ if( !this.MemSpyRunning ){
+ taskList.add( MEMSPY_LAUNCH );
+ }
+
+ //Adding category settings requests, if the feature is supported
+ if(MemSpyPlugin.getDefault().isSWMTCategorySettingFeatureEnabled()){
+ taskList.add( MEMSPY_SET_CATEGORIES_LOW ); //LOW bytes has to be written always before high bytes
+ taskList.add( MEMSPY_SET_CATEGORIES_HIGH ); //HIGH bytes has to be written always after low bytes
+ }
+
+
+ // Set the name filter for User Heap SWMT category
+ if(MemSpyPreferences.isSWMTHeapDumpSelected() && !MemSpyPreferences.isProfileTrackedCategoriesSelected()) {
+ taskList.add( MEMSPY_SET_SWMT_HEAP_DUMP );
+ taskList.add( MEMSPY_SET_HEAP_NAME_FILTER );
+ }
+
+ taskList.add( MEMSPY_SWMT_UPDATE );
+
+ // start running tasks
+ return this.runNextTask();
+ }
+ else{
+ return false;
+ }
+ }
+
+ /**
+ * Starts timer based SWMT logging.
+ * @param wizardPage page which is notified when request is finished
+ * @param currentFile path of the file where Heap Dump is written
+ * @param resetInStart should cycles be reseted
+ * @param resetBetweenCycles if MemSpy S60 application is to be reseted between every cycle
+ * @param interval poll interval
+ * @return true, if connection to TraceCore established successfully, else false
+ */
+ public boolean startSWMTTimer( IMemSpyTraceListener wizardPage, int cycleNumber,
+ boolean resetInStart, boolean resetBetweenCycles, int interval ){
+ this.wizardPage = wizardPage;
+ this.resetBetweenCycles = resetBetweenCycles;
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.startSWMTTimer"); //$NON-NLS-1$
+
+ // if connection established successfully, return true
+ if( this.connect() ){
+ this.cycleNumber = cycleNumber - 1;
+ this.interval = interval;
+
+
+ if( resetInStart == true ){
+ taskList.add( MEMSPY_STOP );
+ taskList.add( MEMSPY_LAUNCH );
+
+ }
+
+ this.runNextTimedTask();
+
+ return true;
+ }
+ else{
+ return false;
+ }
+
+
+ }
+
+
+ /**
+ * Stops SWMT timer
+ * @return true if timer was stopped immediately, false if MemSpy operation was on-going and timer is stopped after after operations are done.
+ */
+ public boolean stopSWMTTimer(){
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.stopSWMTTimer"); //$NON-NLS-1$
+
+ // other variables to zero.
+ this.interval = 0;
+ this.cycleNumber = 1;
+
+ // if timer is, running stop it
+ if( intervalTimer != null && intervalTimer.isRunning() ){
+ intervalTimer.stop();
+ this.swmtLogInfo = null;
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+
+ /**
+ * addNextTimedTask.
+ * Adds next timed tasks into taskList if needed
+ */
+ private void runNextTimedTask(){
+
+ cycleNumber++;
+
+ // get new SWMT-object and set filename correct
+ swmtLogInfo = this.getNewSWMTInfo();
+ this.currentFile = swmtLogInfo.getPath();
+
+ // If MemSpy is not running launch it
+ if( !this.MemSpyRunning ){
+ taskList.add( MEMSPY_LAUNCH );
+ }
+ //If memSpy is running and we want to reset it between cycles
+ else if(this.MemSpyRunning && resetBetweenCycles == true ){
+ taskList.add( MEMSPY_STOP );
+ taskList.add( MEMSPY_LAUNCH );
+
+ }
+
+ //Adding category settings requests, if the feature is supported
+ if(MemSpyPlugin.getDefault().isSWMTCategorySettingFeatureEnabled()){
+ taskList.add( MEMSPY_SET_CATEGORIES_LOW ); //LOW bytes has to be written always before high bytes
+ taskList.add( MEMSPY_SET_CATEGORIES_HIGH ); //HIGH bytes has to be written always after low bytes
+ }
+
+ // Set the name filter for User Heap SWMT category
+ if(MemSpyPreferences.isSWMTHeapDumpSelected() && !MemSpyPreferences.isProfileTrackedCategoriesSelected()) {
+ taskList.add( MEMSPY_SET_SWMT_HEAP_DUMP );
+ taskList.add( MEMSPY_SET_HEAP_NAME_FILTER );
+ }
+
+
+ // Requesting SWMT update
+ taskList.add( MEMSPY_SWMT_UPDATE );
+
+ // start runnings tasks
+ this.runNextTask();
+ }
+
+ /**
+ * Function that handles calls when MemSpys operation is finished successfully
+ * This method is called from DataHandler every time tag -tag received.
+ */
+ public void memSpyReady(){
+
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady"); //$NON-NLS-1$
+
+ //Check Launcher data version
+ checkMemSpyLauncherDataVersion();
+ //MemSpy launcher data version is received always before -tag is received
+ //When version number is checked, returning -1 to received value
+ receivedMemSpyLauncherDataVersion = MEMSPY_LAUNCHER_VERSION_NOT_DEFINED;
+
+ // Stop logging trace data
+ handler.stopLogging();
+ // Stop listening trace data
+ MemSpyPlugin.getTraceProvider().stopListenTraceData();
+ // Stop timer
+ errorTimer.stop();
+
+ // Checking an updating progress status based on the completed task type
+ checkTaskForCurrentProgressStatus(this.taskList.get(0));
+
+ if( this.taskList.get(0) == MEMSPY_LAUNCH ){
+ //Setting timer value to MAX here when known that MemSpy Launcher in S60 target is OK
+ //(last successfully run command is MemSpy launch).
+ this.currentWaitTime = MAX_WAIT_TIME;
+
+ // MemSpy started successfully, update status
+ this.MemSpyRunning = true;
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady/MEMSPY_LAUNCH/MemSpyRunning=true"); //$NON-NLS-1$
+ if( this.taskList.size() >= 2 && this.taskList.get(1) == MEMSPY_THREAD_INFO ){
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady/MEMSPY_LAUNCH/activateId( threadID: "+ threadID); //$NON-NLS-1$
+ if( !this.sendIntegerDataToLauncher(threadID) ){
+ launcherError(LauncherErrorType.ACTIVATION);
+ }
+ else{
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "T raceCoreEngine.memSpyReady/MEMSPY_LAUNCH/activateId => OK"); //$NON-NLS-1$
+ }
+ }
+ }
+ else if( this.taskList.get(0) == MEMSPY_THREAD_LIST ){
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady/MEMSPY_THREAD_LIST"); //$NON-NLS-1$
+ this.wizardPage.operationFinished( LauncherAction.GET_THREAD_LIST );
+ }
+ else if( this.taskList.get(0) == MEMSPY_THREAD_INFO ){
+ // Heap info received
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady/MEMSPY_THREAD_INFO"); //$NON-NLS-1$
+
+ // If heap type is not correct, reset tasklist and return error
+ if( !handler.isHeapTypeCorrect() ){
+ this.taskList.clear();
+ this.wizardPage.deviceError( LauncherErrorType.HEAP_TYPE_WRONG );
+ }
+
+ // ignore dumped traces-messages.
+ if( handler.isDumpedTraces() ){
+ handler.setDumpedTraces( false );
+ }
+ }
+ else if( this.taskList.get(0) == MEMSPY_GET_HEAP_DUMP ){
+ // Heap Dump received
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady/MEMSPY_GET_HEAP_DUMP"); //$NON-NLS-1$
+
+ if( handler.isDumpedTraces() == false ){
+ // Tell wizard that request is finished
+ this.wizardPage.operationFinished( LauncherAction.GET_HEAP_DUMP );
+ }
+ else{
+ handler.setDumpedTraces( false );
+ this.launcherError(LauncherErrorType.HEAP_NOT_FOUND);
+ }
+ }
+ else if( this.taskList.get(0) == MEMSPY_SWMT_UPDATE || this.taskList.get(0) == MEMSPY_SWMT_RESET ){
+ // if SWMT log received
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady/MEMSPY_SWMT_UPDATE || MEMSPY_SWMT_RESET"); //$NON-NLS-1$
+
+ if( handler.isDumpedTraces() == false ){
+ // Tell wizard that request is finished
+
+ // if timed swmt-logging is on request notification after interval
+ if( swmtLogInfo != null ){
+
+ boolean timerRunning = false;
+
+ // if interval is more that zero, start counter and set timerRunning variable correct.
+ if( interval > 0 ){
+ intervalTimer = new Timer( interval * SECOND, this );
+ intervalTimer.start();
+ timerRunning = true;
+ }
+
+ // tell wizard that one log file has been received.
+ this.wizardPage.operationFinished( LauncherAction.TIMED_SWMT_UPDATE, swmtLogInfo, timerRunning);
+ swmtLogInfo = null;
+
+ }
+ else{
+ this.wizardPage.operationFinished( LauncherAction.SWMT_UPDATE );
+ }
+ }
+ else{
+ //Reset SWMT timer values.
+ this.stopSWMTTimer();
+
+ handler.setDumpedTraces( false );
+ this.launcherError(LauncherErrorType.HEAP_NOT_FOUND);
+ }
+ }
+ else if( this.taskList.get(0) == MEMSPY_STOP ){
+ MemSpyRunning = false;
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady/MEMSPY_STOP"); //$NON-NLS-1$
+ }
+
+ // Remove first task from list.
+ if(taskList.size() > 0){
+ this.taskList.remove(0);
+ // Updating progress status to next task launched status
+ // (only updated in case this is progress to previous situation).
+ setProgressStatus(ProgressStatus.EPROGRESS_FIRST_TASK_LAUNCHED);
+ }
+ // run next task
+ this.runNextTask();
+
+
+ }
+
+ /**
+ * Updates progress status based on given task id.
+ * Used setter method takes care that update is done only
+ * if there has been progress compared to previous situation.
+ * @param taskId task event for the task that was just completed
+ */
+ private void checkTaskForCurrentProgressStatus(String taskId) {
+ if( taskId == MEMSPY_LAUNCH ){
+ setProgressStatus(ProgressStatus.EPROGRESS_MEMSPY_LAUNCHED);
+ }
+ else{
+ // In case of other than launch task first task has been executed properly
+ setProgressStatus(ProgressStatus.EPROGRESS_FIRST_TASK_DONE);
+ }
+ }
+
+ /**
+ * Handles calls when launcher prints error message into trace.
+ * @param error error code
+ * @param clientContextErrorString provides optionally additional information about the error occurred
+ */
+ public void launcherError( LauncherErrorType error, String clientContextErrorString ){
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.launcherError/error: " + error); //$NON-NLS-1$
+
+ additionalErrorInformation = clientContextErrorString;;
+
+ handler.stopLogging();
+ // Stop listening trace data
+ MemSpyPlugin.getTraceProvider().stopListenTraceData();
+
+ // Stop timer
+ if( errorTimer != null ){
+ errorTimer.stop();
+ //Setting timer value to default when error occurred
+ this.currentWaitTime = DEFAULT_WAIT_TIME;
+ }
+
+ // if wizard has been shut down, don't send error message.
+ if( taskList.size() == 1 && taskList.get(0) == MEMSPY_STOP ){
+ return;
+ }
+ this.taskList.clear();
+ // Stop logging trace data
+
+ //
+ //When there are special handling about error, founding error codes and then call the wizard.
+ //But in default case, we just pass the error code to wizard to show the error.
+ //
+
+ // MemSpy not running.
+ if( error == LauncherErrorType.MEMSPY_NOT_RUNNING ){
+ wizardPage.deviceError( LauncherErrorType.MEMSPY_NOT_RUNNING );
+ this.MemSpyRunning = false;
+ }
+ else if( error == LauncherErrorType.NO_ANSWER_FROM_DEVICE ){
+ // No answer from device can happen because
+ if( handler.isDumpedTraces() ){
+ // Input data is corrupted and traces are dumped...
+ handler.setDumpedTraces( false );
+ wizardPage.deviceError( LauncherErrorType.DUMPED_TRACES );
+ }
+ else{
+ //..or connection is broken and we really has'nt got any response from device
+ wizardPage.deviceError( LauncherErrorType.NO_ANSWER_FROM_DEVICE );
+ }
+ }
+ else {
+ wizardPage.deviceError( error);
+ }
+
+ }
+
+
+ /**
+ * Function that is called when response from launcher is not received within reasonable time.
+ * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+ */
+ public void actionPerformed(ActionEvent e) {
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.actionPerformed/e.getSource(): " + e.getSource().toString()); //$NON-NLS-1$
+
+ if( e.getSource() == errorTimer ){
+ // This function is called if MemSpy operation does not respond in time stored in currentWaitTime member variable.
+ // I.e. no answer has been received from the device in expected maximum time.
+ this.launcherError(LauncherErrorType.NO_ANSWER_FROM_DEVICE);
+ }
+ else if( e.getSource() == intervalTimer ){
+ this.runNextTimedTask();
+ // Notify wizard that SWMT receiving is started
+ wizardPage.startedReceivingSWMTLog();
+ intervalTimer.stop();
+ }
+
+ }
+
+
+ /**
+ * Shuts down MemSpy application. If some MemSpy operation is on-going schedule shutdown after that.
+ */
+ public void shutDownMemSpy(){
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.shutDownMemSpy"); //$NON-NLS-1$
+
+ // if MemSpy is running, send stop request
+ if( this.MemSpyRunning ) {
+ this.taskList.add( MEMSPY_STOP );
+ }
+
+ // If timer is not running( MemSpy is not currently operating ), run next task
+ if( errorTimer != null && !errorTimer.isRunning() ){
+ this.runNextTask();
+ }
+ disconnectTrace();
+ }
+
+ /**
+ * Check if MemSpy is running
+ * @return true
if MemSpy is Running false
otherwise.
+ */
+ public boolean isMemSpyRunning() {
+ return MemSpyRunning;
+ }
+
+ /**
+ * Establishes connection between plugin and device.
+ * @return true, is connection established successfully
+ */
+ private boolean connect(){
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.connect"); //$NON-NLS-1$
+ return MemSpyPlugin.getTraceProvider().connectTraceSource(this);
+ }
+
+ /**
+ * Disconnects connection between plugin and device if connection was started
+ * for this MemSpy run. Leaving connection up, if TraceViewer was already connected.
+ */
+ public void disconnectTrace() {
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.disconnectTrace"); //$NON-NLS-1$
+ MemSpyPlugin.getTraceProvider().disconnectTraceSource();
+ }
+
+ /**
+ * Sends current usage context-specific integer data to launcher.
+ * Integer data can contain values that can be expressed with 10 bytes
+ * i.e. only 10 lower bytes are taken into account when setting data.
+ * @param integerData integer data to be sent
+ * @return false
if failed to send integer data, otherwise true
+ */
+ private boolean sendIntegerDataToLauncher(int integerData)
+ {
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "sendIntegerDataToLauncher: id=" + integerData); //$NON-NLS-1$
+ return MemSpyPlugin.getTraceProvider().sendIntData(integerData);
+ }
+
+ /**
+ * Sends current usage context-specific string message to launcher.
+ * @param stringData string data to send
+ * @param writesFile set to true
if set trace handler needs to write some data into file
+ * @return true
on success, otherwise false
+ */
+ private boolean sendStringDataToLauncher(String stringData, boolean writesFile){
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.sendMessage/message=" + stringData); //$NON-NLS-1$
+
+ if(! addDataProcessorAndSetupLogging(writesFile)){
+ return false;
+ }
+
+ if(! MemSpyPlugin.getTraceProvider().sendStringData(stringData)){
+ return false;
+ }
+
+ startErrorTimer();
+ return true;
+ }
+
+ /**
+ * activateTrace
+ * Sends activation/deactivation message via TraceCore
+ * @param group GroupID
+ * @param writesFile true, if set trace handler needs to write some data into file.
+ * return false if trace activation was not successful.
+ */
+ private boolean activateTrace( String group, boolean writesFile ){
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.activateTrace/group=" + group + ", writesFile=" + writesFile); //$NON-NLS-1$ //$NON-NLS-2$
+
+ if(! addDataProcessorAndSetupLogging(writesFile)){
+ return false;
+ }
+
+ if(! MemSpyPlugin.getTraceProvider().activateTrace(group)){
+ return false;
+ }
+
+ startErrorTimer();
+ return true;
+
+ }
+
+ /**
+ * Starts error time after request.
+ */
+ private void startErrorTimer() {
+ // Start Timer
+ errorTimer = new Timer( currentWaitTime, this );
+ errorTimer.start();
+ }
+
+ /**
+ * Adds dataprocessor and sets-up logging.
+ * @param writesFile true, if set trace handler needs to write some data into file.
+ * @return true
in case of success, and false
in case of some failure.
+ */
+ private boolean addDataProcessorAndSetupLogging(boolean writesFile) {
+
+ //Add DataProcessor to TraceViewer
+ if(! MemSpyPlugin.getTraceProvider().startListenTraceData(handler)){
+ return false;
+ }
+
+ // Start logging
+ if( !handler.startLogging(currentFile, writesFile ) ){
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * runNextTask
+ * Gets next task from list and sends it to TraceCore.
+ * @return false if operation fails.
+ */
+ private boolean runNextTask(){
+
+ try {
+ if( taskList.size() > 0 ){
+ String nextTask = taskList.get(0);
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.runNextTask/taskList.get(0)=" + nextTask); //$NON-NLS-1$
+
+ // Confirming that all necessary preparations for running the next task has been done.
+ prepareRunNextTask();
+
+ // Set writeFile value as false when task needs to write some data into file
+ if( nextTask == MEMSPY_GET_HEAP_DUMP || nextTask == MEMSPY_SWMT_UPDATE || nextTask == MEMSPY_SWMT_RESET ){
+ if( !activateTrace( nextTask, true ) ){
+ this.launcherError(LauncherErrorType.ACTIVATION);
+ return false;
+ }
+ }
+ else if(nextTask == MEMSPY_SET_HEAP_NAME_FILTER){
+ // This task used subscribe communication, instead of group IDs
+ // Send SWMT heap filter before activating command group
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady/MEMSPY_SET_HEAP_NAME_FILTER/sendMessage"); //$NON-NLS-1$
+ if( !this.sendStringDataToLauncher(getHeapNameFilterForSWMT(), false)){
+ launcherError(LauncherErrorType.ACTIVATION);
+ }
+ else{
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.memSpyReady/MEMSPY_SET_HEAP_NAME_FILTER/sendMessage => OK"); //$NON-NLS-1$
+ }
+ }
+ else{
+ if( !activateTrace( nextTask, false) ){
+ this.launcherError(LauncherErrorType.ACTIVATION);
+ return false;
+ };
+
+ }
+ }
+ else{
+ DbgUtility.println(DbgUtility.PRIORITY_LOOP, "TraceCoreEngine.runNextTask/empty taskList"); //$NON-NLS-1$
+ //Setting timer value to default when there are no tasks to run
+ this.currentWaitTime = DEFAULT_WAIT_TIME;
+ }
+ return true;
+
+ } catch (Exception e) {
+ String errMsg = "Unexpected exception in encountered in TraceCoreEngine.runNextTask: " + e;
+ MemSpyConsole.getInstance().println(errMsg , IConsolePrintUtility.MSG_ERROR);
+ return false;
+ }
+
+ }
+
+
+ /**
+ * Confirms that all necessary preparations for running the next task has been done.
+ */
+ private void prepareRunNextTask() {
+ if(this.taskList.get(0) == MEMSPY_SET_CATEGORIES_LOW ){
+ // Setting SWMT low bits data before activating command group
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.prepareRunNextTask/activateId( getCategoriesForSWMTLowBits(): "+ getCategoriesForSWMTLowBits()); //$NON-NLS-1$
+ if( !this.sendIntegerDataToLauncher( getCategoriesForSWMTLowBits()) ){
+ launcherError(LauncherErrorType.ACTIVATION );
+ }
+ else{
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.prepareRunNextTask/MEMSPY_SET_CATEGORIES_HIGH/activateId => OK"); //$NON-NLS-1$
+ }
+ }
+ else if( this.taskList.get(0) == MEMSPY_SET_CATEGORIES_HIGH ){
+ // Setting SWMT high bits data before activating command group
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.prepareRunNextTask/MEMSPY_SET_CATEGORIES_HIGH/activateId( getCategoriesForSWMTHighBits(): "+ getCategoriesForSWMTHighBits()); //$NON-NLS-1$
+ if( !this.sendIntegerDataToLauncher( getCategoriesForSWMTHighBits()) ){
+ launcherError(LauncherErrorType.ACTIVATION );
+ }
+ else{
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.prepareRunNextTask/MEMSPY_SET_CATEGORIES_HIGH/activateId => OK"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * getNewSWMTInfo.
+ * Creates a new SWMTLogInfo object and sets correct filename and time into it.
+ * @return SWMTLogInfo-object
+ */
+ private SWMTLogInfo getNewSWMTInfo(){
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "TraceCoreEngine.getNewSWMTInfo"); //$NON-NLS-1$
+
+ // Create new SWMTLogInfo item.
+ SWMTLogInfo newItem = new SWMTLogInfo();
+
+ // set date correct
+ Date date = new Date();
+ newItem.setDate(date);
+
+
+ // set filename correct
+ newItem.setPath( MemSpyFileOperations.getTempFileNameForSWMTLog(cycleNumber, date) );
+
+ // set type
+ newItem.setType( SWMTLogType.DEVICE );
+
+ return newItem;
+ }
+
+ /**
+ * Get first task.
+ * @return first task from taskList.
+ */
+ public String getFirstTask(){
+ if( taskList.size() > 0 ){
+ return taskList.get(0);
+ }
+ else{
+ return null;
+ }
+ }
+
+ /**
+ * Gets lower 10 bits for SWMT categories that user wants to include into SWMT log.
+ * @return lower 10 bits for SWMT categories that user wants to include into SWMT log.
+ */
+ public int getCategoriesForSWMTLowBits() {
+ int lowBits = getCategoriesForSWMTWithKernelHandles() & 0x3ff; // ANDs away all the other that lower 10 bits
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "getCategoriesForSWMTLowBits(): " + String.format("0x%x", lowBits)); //$NON-NLS-1$
+ return lowBits;
+ }
+
+ /**
+ * Gets higher bits for SWMT categories that user wants to include into SWMT log.
+ * @return higher bits for SWMT categories that user wants to include into SWMT log.
+ */
+ public int getCategoriesForSWMTHighBits() {
+ int highBits = getCategoriesForSWMTWithKernelHandles()>>10;
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "getCategoriesForSWMTHighBits(): " + String.format("0x%x", highBits)); //$NON-NLS-1$
+ return highBits;
+ }
+
+ /**
+ * Gets SWMT categories that user wants to include into SWMT log.
+ * Includes always {@link SWMTCategoryConstants#CATEGORY_KERNELHANDLES} with it because SWMT Analyser
+ * needs it to be functional
+ * @return SWMT categories that user wants to include into SWMT log.
+ */
+ private int getCategoriesForSWMTWithKernelHandles() {
+ // CATEGORY_KERNELHANDLES is always included into fetched categories because data is required by SWMT analyser plug-in
+ //If SWMT Analyzer is modified so that Kernel Handles is not always needed then SWMTCategoryConstants.CATEGORY_KERNELHANDLES can be removed.
+ return getCategoriesForSWMT() | SWMTCategoryConstants.CATEGORY_KERNELHANDLES;
+ }
+
+
+ /**
+ * Gets SWMT categories that user wants to include into SWMT log.
+ * @return SWMT categories that user wants to include into SWMT log.
+ */
+ public int getCategoriesForSWMT() {
+ int sessionSpecificSWMTCategorySetting = MemSpyPreferences.getSWMTCategorySetting();
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "getCategoriesForSWMT(): " + String.format("0x%x", sessionSpecificSWMTCategorySetting)); //$NON-NLS-1$
+ SWMTCategoryConstants.debugPrintSWMTCategorySetting(sessionSpecificSWMTCategorySetting);
+ return sessionSpecificSWMTCategorySetting;
+ }
+
+ /**
+ * Sets SWMT categories that user wants to include into SWMT log.
+ * @param categoriesForSWMT SWMT categories that user wants to include into SWMT log.
+ * @param isProfileSettings true
if these settings are profile settings
+ * false
if these are custom settings
+ */
+ public void setCategoriesForSWMT(int categoriesForSWMT, boolean isProfileSettings) {
+ MemSpyPreferences.setSWMTCategorySetting(categoriesForSWMT, isProfileSettings);
+ }
+
+ /**
+ * Sets if User has select a Profile or not
+ * @param isProfileCategoriesSelected
+ */
+ public void setProfileTrackedCategoriesSelected(boolean isProfileCategoriesSelected) {
+ MemSpyPreferences.setProfileTrackedCategoriesSelected(isProfileCategoriesSelected);
+ }
+
+ /**
+ * Gets if User has select a Profile or not
+ * @return true
if one of the profiles has been selected
+ */
+ public boolean isProfileTrackedCategoriesSelected() {
+ return MemSpyPreferences.isProfileTrackedCategoriesSelected();
+ }
+
+ /**
+ * Gets SWMT HeapNameFilter to filter User Heaps in SWMT log.
+ * @return SWMT HeapNameFilter that user wants to include into SWMT log.
+ */
+ public String getHeapNameFilterForSWMT() {
+ String filter = MemSpyPreferences.getSWMTHeapNameFilter();
+
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "getHeapNameFilterForSWMT(): " + filter); //$NON-NLS-1$
+ return filter;
+ }
+
+ /**
+ * Sets SWMT HeapNameFilter to filter User Heaps in SWMT log.
+ * @param HeapNameFilter SWMT HeapNameFilter that user wants to include into SWMT log.
+ */
+ public void setHeapNameFilterForSWMT(String heapNameFilterForSWMT) {
+ MemSpyPreferences.setSWMTHeapNameFilter(heapNameFilterForSWMT);
+ }
+
+ /**
+ * Restarts error timer
+ */
+ public void restartErrorTimer() {
+ if( errorTimer != null && errorTimer.isRunning() ){
+ errorTimer.restart();
+ }
+ }
+
+ /**
+ * Notify about MemSpy Launcher S60 application version
+ * @param version in format "x", e.g "1".
+ */
+ public void setMemSpyLauncherVersion(String version) {
+ String msg = "MemSpy Launcher data version: '" +version +"' detected in S60 target.";
+ DbgUtility.println(DbgUtility.PRIORITY_LOOP, msg);
+ MemSpyConsole.getInstance().println(msg);
+
+ receivedMemSpyLauncherDataVersion = Integer.parseInt(version);
+ }
+
+ /**
+ * Check if received MemSpy Launcher data version is at least required version
+ */
+ private void checkMemSpyLauncherDataVersion() {
+ int requiredVersion = ProductInfoRegistry.getRequiredMemSpyLauncherDataVersion();
+ DbgUtility.println(DbgUtility.PRIORITY_LOOP, "Required MemSpy Launcher data version: " +requiredVersion);
+ if(requiredVersion > receivedMemSpyLauncherDataVersion){
+ this.launcherError(LauncherErrorType.TOO_OLD_MEMSPY_LAUNCHER_DATAVERSION);
+ }
+ }
+
+ /**
+ * Get Heap Dump files that has been imported during SWMT logging.
+ * @return list about imported Heap Dumps.
+ */
+ public ArrayList getImportedSWMTHeaps() {
+ return handler.getImportedSWMTHeaps();
+ }
+
+ /**
+ * Gets progress status for current wizard session with current connection settings.
+ * @return Progress status for current wizard session with current connection settings.
+ */
+ public ProgressStatus getProgressStatus() {
+ return progressStatus;
+ }
+
+ /**
+ * Sets progress status if there has been further progress after recent progress status update.
+ * @param progressStatus the progressStatus to set
+ */
+ private void setProgressStatus(ProgressStatus progressStatus) {
+ if(progressStatus.ordinal() > this.progressStatus.ordinal()){
+ this.progressStatus = progressStatus;
+ DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "setProgressStatus: " + this.progressStatus.name()); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Resets progress status back into initial value.
+ */
+ public void resetProgressStatus() {
+ this.progressStatus = ProgressStatus.EPROGRESS_INITIAL;
+ }
+
+ /**
+ * Delegates launcher error info further without any additional information
+ * @param generalLauncherError launcher error occurred
+ */
+ public void launcherError(LauncherErrorType launcherError) {
+ launcherError(launcherError, "");
+ }
+
+ /**
+ * Gets possible additional information related to occurred error.
+ * @return string containing additional information related to occurred error
+ */
+ public String getAdditionalErrorInformation() {
+ return additionalErrorInformation;
+ }
+
+ /* (non-Javadoc)
+ * @see com.nokia.s60tools.memspy.export.ITraceClientNotificationsIf#notifyError(java.lang.String)
+ */
+ public void notifyError(String message) {
+ // Currently only showing trace errors on console
+ MemSpyConsole.getInstance().println(message, MemSpyConsole.MSG_ERROR);
+ }
+
+ /* (non-Javadoc)
+ * @see com.nokia.s60tools.memspy.export.ITraceClientNotificationsIf#notifyInformation(java.lang.String)
+ */
+ public void notifyInformation(String message) {
+ // Currently only showing trace informative messages on console
+ MemSpyConsole.getInstance().println(message, MemSpyConsole.MSG_NORMAL);
+ }
+
+ /* (non-Javadoc)
+ * @see com.nokia.s60tools.memspy.export.ITraceClientNotificationsIf#notifyWarning(java.lang.String)
+ */
+ public void notifyWarning(String message) {
+ // Currently only showing trace warnings on console
+ MemSpyConsole.getInstance().println(message, MemSpyConsole.MSG_WARNING);
+ }
+
+}