blob: cf96a493d82acfa24f9570033eeb61e399829981 [file] [log] [blame]
/*
* Copyright (C) 2016 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.apptransition.tests;
import static android.system.helpers.OverviewHelper.isRecentsInLauncher;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.launcherhelper.ILauncherStrategy;
import android.support.test.launcherhelper.LauncherStrategyFactory;
import android.support.test.rule.logging.AtraceLogger;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.Direction;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.util.Log;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class AppTransitionTests {
private static final String TAG = AppTransitionTests.class.getSimpleName();
private static final int JOIN_TIMEOUT = 10000;
private static final int DEFAULT_DROP_CACHE_DELAY = 2000;
private static final String DEFAULT_POST_LAUNCH_TIMEOUT = "5000";
private static final String DEFAULT_LAUNCH_COUNT = "10";
private static final String SUCCESS_MESSAGE = "Status: ok";
private static final String HOT_LAUNCH_MESSAGE = "Warning: Activity not started, its current"
+ " task has been brought to the front";
private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
private static final String APP_LAUNCH_CMD = "am start -W -n";
private static final String FORCE_STOP = "am force-stop ";
private static final String PRE_LAUNCH_APPS = "pre_launch_apps";
private static final String LAUNCH_APPS = "launch_apps";
private static final String KEY_LAUNCH_ITERATIONS = "launch_iteration";
private static final String KEY_POST_LAUNCH_TIMEOUT = "postlaunch_timeout";
private static final String COLD_LAUNCH = "cold_launch";
private static final String HOT_LAUNCH = "hot_launch";
private static final String NOT_SURE = "not_sure";
private static final String ACTIVITY = "Activity";
private static final String KEY_TRACE_DIRECTORY = "trace_directory";
private static final String KEY_TRACE_CATEGORY = "trace_categories";
private static final String KEY_TRACE_BUFFERSIZE = "trace_bufferSize";
private static final String KEY_TRACE_DUMPINTERVAL = "tracedump_interval";
private static final String DEFAULT_TRACE_CATEGORIES = "sched,freq,gfx,view,dalvik,webview,"
+ "input,wm,disk,am,wm";
private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
private static final String DELIMITER = ",";
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private static final BySelector RECENTS = By.res(SYSTEMUI_PACKAGE, "recents_view");
private static final int TASK_SWITCH_SWIPE_SPEED = 500;
private Context mContext;
private UiDevice mDevice;
private PackageManager mPackageManager;
private IActivityManager mActivityManager;
private ILauncherStrategy mLauncherStrategy = null;
private Map<String, Intent> mAppLaunchIntentsMapping = null;
private String mTraceDirectoryStr = null;
private Bundle mResult = new Bundle();
private Bundle mArgs;
private String mPreAppsList;
private int mLaunchIterations;
private int mPostLaunchTimeout;
private String[] mAppListArray;
private String[] mPreAppsListArray;
private File mRootTrace = null;
private File mRootTraceSubDir = null;
private int mTraceBufferSize = 0;
private int mTraceDumpInterval = 0;
private Set<String> mTraceCategoriesSet = null;
private AtraceLogger mAtraceLogger = null;
private String mComponentName = null;
private Map<String,String> mPreAppsComponentName = new HashMap<String, String>();
private float mDisplayDensity;
private boolean mHasLeanback = false;
@Before
public void setUp() throws Exception {
mPackageManager = getInstrumentation().getContext().getPackageManager();
mContext = getInstrumentation().getContext();
mArgs = InstrumentationRegistry.getArguments();
mActivityManager = ActivityManager.getService();
mDevice = UiDevice.getInstance(getInstrumentation());
LauncherStrategyFactory factory = LauncherStrategyFactory.getInstance(mDevice);
mLauncherStrategy = factory.getLauncherStrategy();
mHasLeanback = hasLeanback(getInstrumentation().getTargetContext());
// Inject an instance of instrumentation only if leanback. This enables to launch any app
// in the Apps and Games row on leanback launcher.
if (mHasLeanback) {
factory.getLeanbackLauncherStrategy().setInstrumentation(getInstrumentation());
}
createLaunchIntentMappings();
String mAppsList = mArgs.getString(LAUNCH_APPS);
mPreAppsList = mArgs.getString(PRE_LAUNCH_APPS);
mLaunchIterations = Integer.parseInt(mArgs.getString(KEY_LAUNCH_ITERATIONS,
DEFAULT_LAUNCH_COUNT));
mPostLaunchTimeout = Integer.parseInt(mArgs.getString(KEY_POST_LAUNCH_TIMEOUT,
DEFAULT_POST_LAUNCH_TIMEOUT));
if (null == mAppsList && mAppsList.isEmpty()) {
throw new IllegalArgumentException("Need atleast one app to do the"
+ " app transition from launcher");
}
mAppsList = mAppsList.replaceAll("%"," ");
mAppListArray = mAppsList.split(DELIMITER);
mDisplayDensity = mContext.getResources().getDisplayMetrics().density;
// Parse the trace parameters
mTraceDirectoryStr = mArgs.getString(KEY_TRACE_DIRECTORY);
if (isTracesEnabled()) {
String traceCategoriesStr = mArgs
.getString(KEY_TRACE_CATEGORY, DEFAULT_TRACE_CATEGORIES);
mTraceBufferSize = Integer.parseInt(mArgs.getString(KEY_TRACE_BUFFERSIZE,
DEFAULT_TRACE_BUFFER_SIZE));
mTraceDumpInterval = Integer.parseInt(mArgs.getString(KEY_TRACE_DUMPINTERVAL,
DEFAULT_TRACE_DUMP_INTERVAL));
mTraceCategoriesSet = new HashSet<String>();
if (!traceCategoriesStr.isEmpty()) {
String[] traceCategoriesSplit = traceCategoriesStr.split(DELIMITER);
for (int i = 0; i < traceCategoriesSplit.length; i++) {
mTraceCategoriesSet.add(traceCategoriesSplit[i]);
}
}
}
mDevice.setOrientationNatural();
sleep(mPostLaunchTimeout);
cleanTestApps();
}
@After
public void tearDown() throws Exception{
cleanTestApps();
getInstrumentation().sendStatus(0, mResult);
}
/**
* Cold launch given list of apps for given launch count from the launcher screen.
* @throws IOException if there are issues in writing atrace file
* @throws InterruptedException if there are interrupt during the sleep
* @throws RemoteException if press home is not successful
*/
@Test
public void testColdLaunchFromLauncher() throws IOException, InterruptedException,
RemoteException {
if (isTracesEnabled()) {
createTraceDirectory("testColdLaunchFromLauncher");
}
// Perform cold app launch from launcher screen
for (int appCount = 0; appCount < mAppListArray.length; appCount++) {
String appName = mAppListArray[appCount];
// Additional launch to account for cold launch
if (setupAppLaunch(appName) == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) {
continue;
}
closeApps(new String[] {
appName
});
getInstrumentation().getUiAutomation()
.executeShellCommand(DROP_CACHE_SCRIPT);
sleep(DEFAULT_DROP_CACHE_DELAY);
for (int launchCount = 0; launchCount <= mLaunchIterations; launchCount++) {
if (null != mAtraceLogger) {
mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize,
mTraceDumpInterval, mRootTraceSubDir,
String.format("%s-%d", appName, launchCount));
}
mLauncherStrategy.launch(appName, mComponentName.split("\\/")[0]);
if (null != mAtraceLogger) {
mAtraceLogger.atraceStop();
}
sleep(mPostLaunchTimeout);
mDevice.pressHome();
mDevice.waitForIdle();
closeApps(new String[] {
appName
});
sleep(mPostLaunchTimeout);
getInstrumentation().getUiAutomation()
.executeShellCommand(DROP_CACHE_SCRIPT);
sleep(DEFAULT_DROP_CACHE_DELAY);
}
mComponentName = null;
// Update the result with the component name
updateResult(appName);
}
}
/**
* Hot launch given list of apps for given launch count from the launcher screen. Same method can be
* used to test app to home transition delay information as well.
* @throws IOException if there are issues in writing atrace file
* @throws InterruptedException if there are interrupt during the sleep
* @throws RemoteException if press home is not successful
*/
@Test
public void testHotLaunchFromLauncher() throws IOException, InterruptedException,
RemoteException {
if (isTracesEnabled()) {
createTraceDirectory("testHotLaunchFromLauncher");
}
for (int appCount = 0; appCount < mAppListArray.length; appCount++) {
String appName = mAppListArray[appCount];
// Additional launch to account for cold launch
if (setupAppLaunch(appName) == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) {
continue;
}
// Hot app launch for given (launch iterations + 1) times.
for (int launchCount = 0; launchCount <= (mLaunchIterations); launchCount++) {
if (null != mAtraceLogger) {
mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize,
mTraceDumpInterval, mRootTraceSubDir,
String.format("%s-%d", appName, (launchCount)));
}
mLauncherStrategy.launch(appName, mComponentName.split("\\/")[0]);
if (null != mAtraceLogger) {
mAtraceLogger.atraceStop();
}
sleep(mPostLaunchTimeout);
mDevice.pressHome();
sleep(mPostLaunchTimeout);
}
mComponentName = null;
// Update the result with the component name
updateResult(appName);
}
}
/**
* Launch an app and press recents for given list of apps for given launch counts.
* @throws IOException if there are issues in writing atrace file
* @throws InterruptedException if there are interrupt during the sleep
* @throws RemoteException if press recent apps is not successful
*/
@Test
public void testAppToRecents() throws IOException, InterruptedException, RemoteException {
Assume.assumeFalse(mHasLeanback);
if (isTracesEnabled()) {
createTraceDirectory("testAppToRecents");
}
if (null == mPreAppsList && mPreAppsList.isEmpty()) {
throw new IllegalArgumentException("Need atleast few apps in the "
+ "recents before starting the test");
}
mPreAppsList = mPreAppsList.replaceAll("%"," ");
mPreAppsListArray = mPreAppsList.split(DELIMITER);
mPreAppsComponentName.clear();
populateRecentsList();
for (int appCount = 0; appCount < mAppListArray.length; appCount++) {
String appName = mAppListArray[appCount];
long appLaunchTime = -1L;
for (int launchCount = 0; launchCount <= mLaunchIterations; launchCount++) {
mLauncherStrategy.launch(appName, mPreAppsComponentName.get(appName).split(
"\\/")[0]);
sleep(mPostLaunchTimeout);
if (null != mAtraceLogger && launchCount > 0) {
mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize,
mTraceDumpInterval, mRootTraceSubDir,
String.format("%s-%d", appName, launchCount - 1));
}
pressUiRecentApps();
sleep(mPostLaunchTimeout);
if (null != mAtraceLogger && launchCount > 0) {
mAtraceLogger.atraceStop();
}
mDevice.pressHome();
sleep(mPostLaunchTimeout);
}
updateResult(appName);
}
}
/**
* Hot launch an app from recents for given list of apps for given launch counts.
* @throws IOException if there are issues in writing atrace file
* @throws InterruptedException if there are interrupt during the sleep
* @throws RemoteException if press recent apps is not successful
*/
@Test
public void testHotLaunchFromRecents() throws IOException, InterruptedException,
RemoteException {
Assume.assumeFalse(mHasLeanback);
if (isTracesEnabled()) {
createTraceDirectory("testHotLaunchFromRecents");
}
if (null == mPreAppsList && mPreAppsList.isEmpty()) {
throw new IllegalArgumentException("Need atleast few apps in the"
+ " recents before starting the test");
}
mPreAppsList = mPreAppsList.replaceAll("%", " ");
mPreAppsListArray = mPreAppsList.split(DELIMITER);
mPreAppsComponentName.clear();
populateRecentsList();
for (int appCount = 0; appCount < mAppListArray.length; appCount++) {
String appName = mAppListArray[appCount];
// To bring the app to launch as first item from recents task.
mLauncherStrategy.launch(appName, mPreAppsComponentName.get(appName).split(
"\\/")[0]);
sleep(mPostLaunchTimeout);
for (int launchCount = 0; launchCount <= mLaunchIterations; launchCount++) {
if (null != mAtraceLogger) {
mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize,
mTraceDumpInterval, mRootTraceSubDir,
String.format("%s-%d", appName, (launchCount)));
}
openMostRecentTask();
sleep(mPostLaunchTimeout);
if (null != mAtraceLogger) {
mAtraceLogger.atraceStop();
}
mDevice.pressHome();
sleep(mPostLaunchTimeout);
}
updateResult(appName);
}
}
/**
* Launch given app to account for the cold launch and track
* component name associated with the app.
* @throws RemoteException if press home is not successful
* @param appName
* @return
*/
public long setupAppLaunch(String appName) throws RemoteException {
long appLaunchTime = startApp(appName, NOT_SURE);
if (appLaunchTime == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) {
return appLaunchTime;
}
sleep(mPostLaunchTimeout);
mDevice.pressHome();
sleep(mPostLaunchTimeout);
return appLaunchTime;
}
private BySelector getLauncherOverviewSelector() {
return By.res(mDevice.getLauncherPackageName(), "overview_panel");
}
/**
* Shows and returns the recents view.
*
* @throws RemoteException if press recents is not successful
*/
private UiObject2 pressUiRecentApps() throws RemoteException {
final UiObject2 recentsButton = mDevice.findObject(By.res(SYSTEMUI_PACKAGE, "recent_apps"));
if (recentsButton == null) {
int height = mDevice.getDisplayHeight();
UiObject2 navBar = mDevice.findObject(By.res(SYSTEMUI_PACKAGE, "navigation_bar_frame"));
// Swipe from nav bar to 2/3rd down the screen.
mDevice.swipe(
navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
navBar.getVisibleBounds().centerX(), height * 2 / 3,
(navBar.getVisibleBounds().centerY() - height * 2 / 3) / 100); // 100 px/step
} else {
recentsButton.click();
}
final UiObject2 recentsView = mDevice.wait(
Until.findObject(isRecentsInLauncher() ? getLauncherOverviewSelector() : RECENTS),
5000);
if (recentsView == null) {
throw new RuntimeException("Recents didn't appear");
}
mDevice.waitForIdle();
return recentsView;
}
/**
* To open the home screen.
* @throws RemoteException if press home is not successful
*/
private void pressUiHome() throws RemoteException {
mDevice.findObject(By.res(SYSTEMUI_PACKAGE, "home")).click();
}
/**
* Open recents view and click on the most recent task.
* @throws RemoteException if press recents is not successful
*/
public void openMostRecentTask() throws RemoteException {
final UiObject2 recentsView = pressUiRecentApps();
if (isRecentsInLauncher()) {
final List<UiObject2> taskViews = mDevice.findObjects(
By.res(mDevice.getLauncherPackageName(), "snapshot"));
if (taskViews.size() != 2) {
// We expect to see in the overview: the active task in the middle (#0), the next
// task on the right (#1).
throw new RuntimeException(
"Unexpected number of visible tasks: " + taskViews.size());
}
// Click at the first task.
taskViews.get(0).click();
} else {
List<UiObject2> recentsTasks = recentsView.getChildren().get(0)
.getChildren();
UiObject2 mostRecentTask = recentsTasks.get(recentsTasks.size() - 1);
mostRecentTask.click();
}
}
/**
* Create sub directory under the trace root directory to store the trace files captured during
* the app transition.
* @param subDirectoryName
*/
private void createTraceDirectory(String subDirectoryName) throws IOException {
mRootTrace = new File(mTraceDirectoryStr);
if (!mRootTrace.exists() && !mRootTrace.mkdirs()) {
throw new IOException("Unable to create the trace directory");
}
mRootTraceSubDir = new File(mRootTrace, subDirectoryName);
if (!mRootTraceSubDir.exists() && !mRootTraceSubDir.mkdirs()) {
throw new IOException("Unable to create the trace sub directory");
}
mAtraceLogger = AtraceLogger.getAtraceLoggerInstance(getInstrumentation());
}
/**
* Force stop the given list of apps, clear the cache and return to home screen.
* @throws RemoteException if press home is not successful
*/
private void cleanTestApps() throws RemoteException {
if (null != mPreAppsListArray && mPreAppsListArray.length > 0) {
closeApps(mPreAppsListArray);
}
closeApps(mAppListArray);
getInstrumentation().getUiAutomation()
.executeShellCommand(DROP_CACHE_SCRIPT);
sleep(DEFAULT_DROP_CACHE_DELAY);
mDevice.pressHome();
sleep(mPostLaunchTimeout);
}
/**
* Populate the recents list with given list of apps.
* @throws RemoteException if press home is not successful
*/
private void populateRecentsList() throws RemoteException {
for (int preAppCount = 0; preAppCount < mPreAppsListArray.length; preAppCount++) {
startApp(mPreAppsListArray[preAppCount], NOT_SURE);
mPreAppsComponentName.put(mPreAppsListArray[preAppCount], mComponentName);
sleep(mPostLaunchTimeout);
mDevice.pressHome();
sleep(mPostLaunchTimeout);
}
mComponentName = null;
}
/**
* To obtain the app name and corresponding intent to launch the app.
*/
private void createLaunchIntentMappings() {
mAppLaunchIntentsMapping = new LinkedHashMap<String, Intent>();
PackageManager pm = getInstrumentation().getContext()
.getPackageManager();
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
intentToResolve.addCategory(mHasLeanback ?
Intent.CATEGORY_LEANBACK_LAUNCHER :
Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
resolveLoop(ris, intentToResolve, pm);
}
private void resolveLoop(List<ResolveInfo> ris, Intent intentToResolve, PackageManager pm) {
if (ris == null || ris.isEmpty()) {
Log.i(TAG, "Could not find any apps");
} else {
for (ResolveInfo ri : ris) {
Intent startIntent = new Intent(intentToResolve);
startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startIntent.setClassName(ri.activityInfo.packageName,
ri.activityInfo.name);
String appName = ri.loadLabel(pm).toString();
if (appName != null) {
mAppLaunchIntentsMapping.put(appName, startIntent);
}
}
}
}
/**
* Launch an app using the app name and return the app launch time. If app launch time is -1
* then app launch is not successful.
* @param appName Name of an app as listed in the launcher
* @param launchMode Cold or Hot launch
* @return
*/
private long startApp(String appName, String launchMode) {
Log.i(TAG, "Starting " + appName);
Intent startIntent = mAppLaunchIntentsMapping.get(appName);
if (startIntent == null) {
return -1L;
}
AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, launchMode);
Thread t = new Thread(runnable);
t.start();
try {
t.join(JOIN_TIMEOUT);
} catch (InterruptedException e) {
// ignore
}
mComponentName = runnable.getCmpName();
return runnable.getResult();
}
private class AppLaunchRunnable implements Runnable {
private Intent mLaunchIntent;
private String mLaunchMode;
private Long mResult = -1L;
private String mCmpName;
public AppLaunchRunnable(Intent intent, String launchMode) {
mLaunchIntent = intent;
mLaunchMode = launchMode;
}
public Long getResult() {
return mResult;
}
public String getCmpName() {
return mCmpName;
}
@Override
public void run() {
String packageName = mLaunchIntent.getComponent().getPackageName();
String componentName = mLaunchIntent.getComponent().flattenToString();
String launchCmd = String.format("%s %s", APP_LAUNCH_CMD, componentName);
ParcelFileDescriptor parcelDesc = getInstrumentation().getUiAutomation()
.executeShellCommand(launchCmd);
mResult = Long.parseLong(parseLaunchTime(parcelDesc));
}
/**
* Returns launch time if app launch is successful otherwise "-1"
* @param parcelDesc
* @return
*/
private String parseLaunchTime(ParcelFileDescriptor parcelDesc) {
String launchTime = "-1";
boolean launchSuccess = false;
mCmpName = null;
try {
InputStream inputStream = new FileInputStream(parcelDesc.getFileDescriptor());
StringBuilder appLaunchOuput = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
inputStream));
String line = null;
int lineCount = 1;
while ((line = bufferedReader.readLine()) != null) {
if (lineCount == 2) {
if ((mLaunchMode.contains(COLD_LAUNCH) || mLaunchMode.contains(NOT_SURE))
&& line.contains(SUCCESS_MESSAGE)) {
launchSuccess = true;
} else if ((mLaunchMode.contains(HOT_LAUNCH) || mLaunchMode
.contains(NOT_SURE)) && line.contains(HOT_LAUNCH_MESSAGE)) {
launchSuccess = true;
}
}
if ((launchSuccess && (mLaunchMode.contains(COLD_LAUNCH)
|| mLaunchMode.contains(NOT_SURE)) && lineCount == 4) ||
(launchSuccess && (mLaunchMode.contains(HOT_LAUNCH) ||
mLaunchMode.contains(NOT_SURE)) && lineCount == 5)) {
String launchSplit[] = line.split(":");
launchTime = launchSplit[1].trim();
}
// Needed to update the component name if the very first launch activity
// is different from hot launch activity (i.e YouTube)
if ((launchSuccess && (mLaunchMode.contains(HOT_LAUNCH) ||
mLaunchMode.contains(NOT_SURE)) && lineCount == 3)) {
String activitySplit[] = line.split(":");
if (activitySplit[0].contains(ACTIVITY)) {
mCmpName = activitySplit[1].trim();
}
}
lineCount++;
}
inputStream.close();
} catch (IOException e) {
Log.w(TAG, "Error writing the launch file", e);
}
return launchTime;
}
}
/**
* To force stop the given list of apps based on the app name.
* @param appNames
*/
private void closeApps(String[] appNames) {
for (int i = 0; i < appNames.length; i++) {
Intent startIntent = mAppLaunchIntentsMapping.get(appNames[i]);
if (startIntent != null) {
String packageName = startIntent.getComponent().getPackageName();
getInstrumentation().getUiAutomation().executeShellCommand(
FORCE_STOP + packageName);
}
sleep(1000);
}
sleep(mPostLaunchTimeout);
}
/**
* @return
*/
private boolean isTracesEnabled(){
return (null != mTraceDirectoryStr && !mTraceDirectoryStr.isEmpty());
}
/**
* Update the result status
* @param appName
*/
private void updateResult(String appName) {
// Component name needed for parsing the events log
if (null != mComponentName) {
mResult.putString(appName, mComponentName);
} else {
// Component name needed for parsing the events log
mResult.putString(appName, mAppLaunchIntentsMapping.get(appName).
getComponent().flattenToString());
}
}
/**
* To sleep for given millisecs.
* @param time
*/
private void sleep(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
// ignore
}
}
/**
* Return the instrumentation from the registry.
* @return
*/
private Instrumentation getInstrumentation() {
return InstrumentationRegistry.getInstrumentation();
}
/**
* @return True if we're running on Android TV.
*/
private boolean hasLeanback(Context context) {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
}
}