--- /dev/null
+ /*
+ * Dynamic Analyzer
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * WooJin Jung <woojin2.jung@samsung.com>
+ * Jooyoul Lee <jy.exe.lee@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+ package org.tizen.dynamicanalyzer.swap.logparser;
+
++import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.MSG_APP_STARTUP_STAGE;
+ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.MSG_CONTEXT_SWITCH_ENTRY;
+ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.MSG_CONTEXT_SWITCH_EXIT;
+ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.MSG_DATA_RECORD;
+ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.MSG_DATA_SAMPLE;
+ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.MSG_DATA_SYSTEM;
+ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.MSG_FUNCTION_ENTRY;
+ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.MSG_FUNCTION_EXIT;
+ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.MSG_PROBE_SCREENSHOT;
+
+ import java.util.ArrayDeque;
+ import java.util.ArrayList;
+ import java.util.Deque;
+ import java.util.HashMap;
+ import java.util.List;
+ import java.util.Map;
+
+ import org.tizen.dynamicanalyzer.common.AnalyzerConstants;
+ import org.tizen.dynamicanalyzer.common.AnalyzerManager;
+ import org.tizen.dynamicanalyzer.common.Global;
+ import org.tizen.dynamicanalyzer.common.SymbolManager;
+ import org.tizen.dynamicanalyzer.communicator.DACommunicator;
+ import org.tizen.dynamicanalyzer.control.DataThread;
+ import org.tizen.dynamicanalyzer.nl.InformationViewLabels;
+ import org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants;
+ import org.tizen.dynamicanalyzer.swap.model.data.LogData;
+ import org.tizen.dynamicanalyzer.swap.model.data.ProfileData;
+ import org.tizen.dynamicanalyzer.swap.model.data.ScreenShotData;
+ import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackInserter;
+ import org.tizen.dynamicanalyzer.ui.info.screenshot.SocketClient;
+ import org.tizen.dynamicanalyzer.ui.summary.profiling.FunctionUsageProfiler;
+ import org.tizen.dynamicanalyzer.util.Logger;
+
+ public class LogParser extends DataThread<List<LogData>> {
+ private static LogParser instance = new LogParser();
+
+ public static List<LogData> END_OF_QUEUE = new ArrayList<LogData>();
+
+ // map for matching exit log with entry log
+ private Map<Integer, Deque<Long>> functionEntryStackByTidMap = new HashMap<Integer, Deque<Long>>();
+
+ // list of image thread
+ private List<Thread> imageThreads = new ArrayList<Thread>();
+
+ public static LogParser getInstance() {
+ return instance;
+ }
+
+ @Override
+ protected String getThreadName() {
+ return AnalyzerConstants.LOG_QUEUE_OBSERVING_THREAD;
+ }
+
+ @Override
+ protected boolean workAfterStart() {
+ return true;
+ }
+
+ @Override
+ protected boolean workAfterStopNormal() {
+ // wait for all image thread is finished
+ synchronized (imageThreads) {
+ while (!imageThreads.isEmpty()) {
+ try {
+ imageThreads.wait();
+ } catch (InterruptedException e) {
+ Logger.exception(e);
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ protected boolean workAfterStopForced() {
+ // force to stop image thread and
+ // wait for all image thread is finished
+ synchronized (imageThreads) {
+ for (Thread entry : imageThreads) {
+ entry.interrupt();
+ }
+
+ while (!imageThreads.isEmpty()) {
+ try {
+ imageThreads.wait();
+ } catch (InterruptedException e) {
+ Logger.exception(e);
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ protected void resetBeforeStart() {
+ functionEntryStackByTidMap.clear();
+ imageThreads.clear();
+ }
+
+ @Override
+ protected void clearAfterStop() {
+ functionEntryStackByTidMap.clear();
+ }
+
+ public Deque<Long> getFunctionEntryStack(int tid) {
+ Deque<Long> functionEntryStack = functionEntryStackByTidMap.get(tid);
+ if (null == functionEntryStack) {
+ functionEntryStack = new ArrayDeque<Long>();
+ functionEntryStackByTidMap.put(tid, functionEntryStack);
+ }
+ return functionEntryStack;
+ }
+
+ /*** log parsing thread ***/
+ @Override
+ public void run() {
+ Thread curThread = Thread.currentThread();
+
+ try {
+ List<LogData> loglist;
+ while (testThread(curThread)) {
+ loglist = pollData();
+ if (loglist == null || loglist == LogParser.END_OF_QUEUE) {
+ break;
+ }
+
+ logParsing(loglist);
+ }
+ } finally {
+ DataManagerRegistry.updateLog(LogPackage.END_OF_QUEUE);
+ CallStackInserter.getInstance().pushData(CallStackInserter.END_OF_QUEUE);
+ }
+
+ Logger.debug("log parsing thread end!!"); //$NON-NLS-1$
+ }
+
+ private void logParsing(List<LogData> loglist) {
+ int size = loglist.size();
+ LogPackage logPack = new LogPackage();
+ for (int i = 0; i < size; i++) {
+ LogData log = loglist.get(i);
+ if (null == log) {
+ continue;
+ }
+
+ int id = log.getMsgID();
+ boolean ret;
+ switch (id) {
+ case MSG_DATA_SAMPLE:
+ if (!AnalyzerManager.isProcessInfoArrived()) {
+ break;
+ }
+ packLog(log, logPack);
+ break;
+ case MSG_FUNCTION_ENTRY:
+ case MSG_FUNCTION_EXIT:
+ if (!AnalyzerManager.isProcessInfoArrived()) {
+ break;
+ }
+ ret = processFunctionData((ProfileData) log);
+ if (ret) {
+ packLog(log, logPack);
+ }
+ break;
+ case MSG_DATA_SYSTEM:
+ case MSG_DATA_RECORD:
+ case MSG_CONTEXT_SWITCH_ENTRY:
+ case MSG_CONTEXT_SWITCH_EXIT:
++ case MSG_APP_STARTUP_STAGE:
+ packLog(log, logPack);
+ break;
+ case MSG_PROBE_SCREENSHOT:
+ processScreenshotData((ScreenShotData) log);
+ packLog(log, logPack);
+ Global.getRuntimeCallstackManager().makeCallstackWithoutBacktrace(log);
+ break;
+ default:
+ packLog(log, logPack);
+ Global.getRuntimeCallstackManager().makeCallstackWithoutBacktrace(log);
+ break;
+ }
+ }
+
+ updateLog(logPack);
+ }
+
+ private boolean processFunctionData(ProfileData pData) {
+ int msgID = pData.getMsgID();
+ Deque<Long> functionStack = getFunctionEntryStack(pData.getTid());
+
+ // entry / exit pair matching
+ if (msgID == DataChannelConstants.MSG_FUNCTION_ENTRY) {
+ functionStack.addLast(pData.getSeq());
+ } else { // msg_function_exit
+ if (!functionStack.isEmpty()) {
+ pData.setEntrySeq(functionStack.removeLast());
+ } else { // size <= 0 : bug (exit without entry)
+ Logger.error("function exit log without entry log");
+ }
+ }
+
+ if (pData.getProbeType() != AnalyzerConstants.FUNCTION_TYPE_FILE) {
+ int apiID = SymbolManager.getFuncId(pData, pData.getPcAddr(), pData.getPid(),
+ pData.getTime());
+ if (apiID < 0) {
+ return false;
+ } else {
+ String apiName = Global.getFunctionName(apiID);
+ if (apiName.equals(InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION)) {
+ return false;
+ } else {
+ pData.setApiId(apiID);
+ }
+ }
+
+ Global.getRuntimeCallstackManager().makeUserCallstack(pData,
+ FunctionUsageProfiler.getInstance().getProfileDataMakerByPid(pData.getPid()));
+ }
+
+ return true;
+ }
+
+ private void processScreenshotData(ScreenShotData log) {
+ // get image file from target or ecs
+ if (DACommunicator.isTargetEmulator() && SocketClient.getInstance().isConnected()) {
+ Global.getCurrentDeviceInfo().emulatorScreenshot.send();
+ String remoteImgPath = Global.getCurrentDeviceInfo().emulatorScreenshot.getFilePath();
+ processImagefromECS(remoteImgPath, log.getOrientation());
+ } else {
+ processImage(log.getImageFilePath(), log.getOrientation());
+ }
+ }
+
+ private void processImage(String from, int angle) {
+ if (angle != 0) {
+ Logger.debug("[ image rotate : " + angle + " ]");
+ }
+
+ Thread thread = new Thread(null, new ImageProcessingThread(this, from, angle, false),
+ AnalyzerConstants.MESSAGE_INTERNAL_IMAGE_THREAD);
+ synchronized (imageThreads) {
+ imageThreads.add(thread);
+ }
+
+ // The thread must be started after it is queued
+ thread.start();
+ }
+
+ private void processImagefromECS(String path, int angle) {
+ if (angle != 0) {
+ Logger.debug("[ image rotate : " + angle + " ]");
+ }
+
+ Thread thread = new Thread(null, new ImageProcessingThread(this, path, angle, true),
+ AnalyzerConstants.MESSAGE_INTERNAL_IMAGE_THREAD);
+ synchronized (imageThreads) {
+ imageThreads.add(thread);
+ }
+
+ // The thread must be started after it is queued
+ thread.start();
+ }
+
+ // notified from image thread that the thread is finished
+ public void setImageThreadFinished(Thread finishedThread) {
+ synchronized (imageThreads) {
+ imageThreads.remove(finishedThread);
+ imageThreads.notifyAll();
+ }
+ }
+
+ private void updateLog(LogPackage logPack) {
+ if (logPack != null && !logPack.isEmpty()) {
+ DataManagerRegistry.updateLog(logPack);
+ }
+ }
+
+ private void packLog(LogData logData, LogPackage logPack) {
+ // a special case for file analysis
+ if (logData.getMsgID() == DataChannelConstants.MSG_FUNCTION_ENTRY
+ || logData.getMsgID() == DataChannelConstants.MSG_FUNCTION_EXIT) {
+ ProfileData data = (ProfileData) logData;
+ if (data.getProbeType() == AnalyzerConstants.FUNCTION_TYPE_FILE) {
+ logPack.setLogs(DataChannelConstants.MSG_FUCNTION_ENTRY_EXIT, logData);
+ return;
+ }
+ }
+ logPack.setLogs(logData.getMsgID(), logData);
+ }
+ }
--- /dev/null
- import org.tizen.dynamicanalyzer.constant.CommonConstants;
- import org.tizen.dynamicanalyzer.swap.logparser.MessageParser;
+/*
+ * Dynamic Analyzer
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Heeyoung Hwang <heeyoung1008.hwang@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+package org.tizen.dynamicanalyzer.swap.model.data;
+
+import org.tizen.dynamicanalyzer.common.Global;
- import org.tizen.dynamicanalyzer.util.ByteUtil;
+import org.tizen.dynamicanalyzer.swap.model.DATime;
- public boolean makeData(byte[] data) {
- super.makeData(data);
- index = MessageParser.MSG_HEADER_SIZE;
-
- pid = ByteUtil.toInt(data, index);
- index += CommonConstants.INT_SIZE;
-
- stageid = ByteUtil.toInt(data, index);
- index += CommonConstants.INT_SIZE;
+import org.tizen.dynamicanalyzer.util.Logger;
+
+public class AppStartupData extends LogData {
+
+ int pid = 0;
+ int stageid = 0;
+ long startTime = 0;
+ long endTime = 0;
+
- int startSec = ByteUtil.toInt(data, index);
- index += CommonConstants.INT_SIZE;
- int startNano = ByteUtil.toInt(data, index);
- index += CommonConstants.INT_SIZE;
- startTime = calculateTimeData(startSec, startNano);
++ public AppStartupData() {
++ }
++
++ @Override
++ public AppStartupData clone() throws CloneNotSupportedException {
++ throw new CloneNotSupportedException();
++ }
++
++ @Override
++ protected boolean makeData(DATime startTime) {
++ super.makeData(startTime);
++
++ pid = getInt();
++ stageid = getInt();
+
+ // start time
- int endSec = ByteUtil.toInt(data, index);
- index += CommonConstants.INT_SIZE;
- int endNano = ByteUtil.toInt(data, index);
- index += CommonConstants.INT_SIZE;
- endTime = calculateTimeData(endSec, endNano);
++ int startSec = getInt();
++ int startNano =getInt();
++ this.startTime = calculateTimeData(startSec, startNano);
+
+ // end time
++ int endSec = getInt();
++ int endNano =getInt();
++ this.endTime = calculateTimeData(endSec, endNano);
+
+ Logger.debug("Application startup :" + pid + "," + stageid + "," + startSec + "." + startNano
+ + ","+ endSec + "." + endNano);
+ return true;
+ }
+
+ public int getPid() {
+ return pid;
+ }
+
+ public void setPid(int pid) {
+ this.pid = pid;
+ }
+
+ public int getStageid() {
+ return stageid;
+ }
+
+ public void setStageid(int stageid) {
+ this.stageid = stageid;
+ }
+
+ public long getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(long startTime) {
+ this.startTime = startTime;
+ }
+
+ public long getEndTime() {
+ return endTime;
+ }
+
+ public void setEndTime(long endTime) {
+ this.endTime = endTime;
+ }
+
+ private long calculateTimeData(int sec, int nano) {
+ DATime time = new DATime(sec, nano);
+ DATime resultTime = time.subtract(Global.getProject().getProfilingStartTime());
+ return resultTime.getLongTime();
+ }
+}
--- /dev/null
- import org.tizen.dynamicanalyzer.database.DBInsertManager;
+/*
+ * Dynamic Analyzer
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Heeyoung Hwang <heeyoung1008.hwang@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.dynamicanalyzer.ui.info.appStartup;
+
+import java.util.ArrayList;
+import java.util.List;
+
- appStartupDBInserter = DBInsertManager.makeInserter(appStartupDBTable);
+import org.tizen.dynamicanalyzer.database.DBInserter;
+import org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants;
+import org.tizen.dynamicanalyzer.swap.logparser.LogPackage;
+import org.tizen.dynamicanalyzer.swap.logparser.Logs;
+import org.tizen.dynamicanalyzer.swap.logparser.PageDataManager;
+import org.tizen.dynamicanalyzer.swap.model.data.LogData;
+import org.tizen.dynamicanalyzer.swap.model.data.AppStartupData;
+
+public class AppStartupDataManager extends PageDataManager {
+
+ private static AppStartupDataManager instance = null;
+
+ private AppStartupDBTable appStartupDBTable = null;
+ private DBInserter appStartupDBInserter = null;
+
+ private AppStartupDataManager() {
+ appStartupDBTable = new AppStartupDBTable();
++ appStartupDBInserter = makeInserter(appStartupDBTable);
+ }
+
+ public AppStartupDBTable getAppStartupDBTable() {
+ return appStartupDBTable;
+ }
+
+ public synchronized static AppStartupDataManager getInstance() {
+ if (null == instance) {
+ instance = new AppStartupDataManager();
+ }
+ return instance;
+ }
+
+ @Override
+ protected void makeData(LogPackage pack) {
+ Logs entryLogs = pack.getLogs(DataChannelConstants.MSG_APP_STARTUP_STAGE);
+ if (null != entryLogs && entryLogs.getRawLogs().size() != 0) {
+ List<LogData> logList = entryLogs.getLogs();
+ List<List<Object>> insertDataList = new ArrayList<List<Object>>();
+ int size = logList.size();
+ for (int i = 0; i < size; i++) {
+ AppStartupData data = (AppStartupData) logList.get(i);
+ List<Object> insertRowData = new ArrayList<Object>();
+
+ try {
+ insertRowData.add(new Integer(data.getPid()));
+ insertRowData.add(new Integer(data.getStageid()));
+ insertRowData.add(new Long(data.getStartTime()));
+ insertRowData.add(new Long(data.getEndTime()));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ e.printStackTrace();
+ }
+ insertDataList.add(insertRowData);
+ }
+
+ // insert table
+ if (insertDataList.size() > 0) {
+ appStartupDBInserter.pushData(insertDataList);
+ }
+ }
+ }
+}