1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief TesterCore remote interface.
22 *//*--------------------------------------------------------------------*/
23
24package com.drawelements.deqp.testercore;
25
26import android.app.ActivityManager;
27import android.content.Context;
28import android.content.ComponentName;
29import android.content.Intent;
30import android.os.Process;
31
32import java.util.List;
33
34public class RemoteAPI {
35
36	private static final String			LOG_TAG				= "dEQP";
37
38	private Context						m_context;
39	private String						m_processName;
40	private String						m_logFileName;
41	private boolean						m_canBeRunning;
42
43	public RemoteAPI (Context context, String logFileName) {
44		m_context			= context;
45		m_processName		= m_context.getPackageName() + ":testercore";
46		m_logFileName		= logFileName;
47		m_canBeRunning		= false;
48	}
49
50	private ComponentName getDefaultTesterComponent () {
51		return new ComponentName(m_context.getPackageName(), "android.app.NativeActivity");
52	}
53
54	private ComponentName getTesterComponent (String testerName) {
55		if (testerName != null && !testerName.equals("")) {
56			ComponentName component = ComponentName.unflattenFromString(testerName);
57			if (component == null) {
58				Log.e(LOG_TAG, "Invalid component name supplied (" + testerName + "), using default");
59				component = getDefaultTesterComponent();
60			}
61			return component;
62		} else {
63			return getDefaultTesterComponent();
64		}
65	}
66
67	public boolean start (String testerName, String cmdLine, String caseList) {
68
69		// Choose component
70		ComponentName component = getTesterComponent(testerName);
71
72		Intent testIntent = new Intent();
73		testIntent.setComponent(component);
74		testIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
75
76		// Add all data to cmdLine
77		cmdLine = testerName + " " + cmdLine + " --deqp-log-filename=" + m_logFileName;
78
79		if (caseList != null)
80			cmdLine = cmdLine + " --deqp-caselist=" + caseList;
81
82		cmdLine = cmdLine.replaceAll("  ", " ");
83		testIntent.putExtra("cmdLine", cmdLine);
84
85		// Try to resolve intent.
86		boolean	isActivity	= m_context.getPackageManager().resolveActivity(testIntent, 0) != null;
87		boolean isService	= m_context.getPackageManager().resolveService(testIntent, 0) != null;
88
89		if (!isActivity && !isService) {
90			Log.e(LOG_TAG, "Can't resolve component as activity or service (" + component.flattenToString() + "), using default");
91			component = getDefaultTesterComponent();
92		}
93
94		Log.d(LOG_TAG, "Starting activity " + component.flattenToString());
95
96		try {
97			if (isService)
98				m_context.startService(testIntent);
99			else
100				m_context.startActivity(testIntent);
101		} catch (Exception e) {
102			Log.e(LOG_TAG, "Failed to start tester", e);
103			return false;
104		}
105
106		m_canBeRunning = true;
107		return true;
108	}
109
110	public boolean kill () {
111		ActivityManager.RunningAppProcessInfo processInfo = findProcess(m_processName);
112
113		// \note not mutating m_canBeRunning yet since process does not die immediately
114
115		if (processInfo != null) {
116			Log.d(LOG_TAG, "Killing " + m_processName);
117			Process.killProcess(processInfo.pid);
118			return true;
119		} else {
120			return false;
121		}
122
123		// \todo [2010-11-01 pyry] Block until tester process is not running?
124	}
125
126	public boolean isRunning () {
127		if (!m_canBeRunning) {
128			return false;
129		} else if (isProcessRunning(m_processName)) {
130			return true;
131		} else {
132			// Cache result. Safe, because only start() can spawn the process
133			m_canBeRunning = false;
134			return false;
135		}
136	}
137
138	public String getLogFileName () {
139		return m_logFileName;
140	}
141
142	private ActivityManager.RunningAppProcessInfo findProcess (String name) {
143		ActivityManager activityMgr = (ActivityManager)m_context.getSystemService(Context.ACTIVITY_SERVICE);
144		List<ActivityManager.RunningAppProcessInfo> processes = activityMgr.getRunningAppProcesses();
145
146		for (ActivityManager.RunningAppProcessInfo info : processes) {
147			// Log.v(LOG_TAG, "Found proc : " + info.processName + " " + info.pid);
148			if (info.processName.equals(name))
149				return info;
150		}
151
152		return null;
153	}
154
155	private boolean isProcessRunning (String processName) {
156		// Log.d(LOG_TAG, "isProcessRunning(): " + processName);
157		return (findProcess(processName) != null);
158	}
159}
160