/*
 * Copyright (C) 2010 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.tradefed.device;

import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.InstallException;
import com.android.ddmlib.InstallReceiver;
import com.android.ddmlib.RawImage;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.SyncException;
import com.android.ddmlib.TimeoutException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ByteArrayInputStreamSource;
import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.util.AaptParser;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.KeyguardControllerState;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.StreamUtil;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nullable;
import javax.imageio.ImageIO;

/**
 * Implementation of a {@link ITestDevice} for a full stack android device
 */
public class TestDevice extends NativeDevice {

    /** number of attempts made to clear dialogs */
    private static final int NUM_CLEAR_ATTEMPTS = 5;
    /** the command used to dismiss a error dialog. Currently sends a DPAD_CENTER key event */
    static final String DISMISS_DIALOG_CMD = "input keyevent 23";
    /** Commands that can be used to dismiss the keyguard. */
    public static final String DISMISS_KEYGUARD_CMD = "input keyevent 82";

    /**
     * Alternative command to dismiss the keyguard by requesting the Window Manager service to do
     * it. Api 23 and after.
     */
    static final String DISMISS_KEYGUARD_WM_CMD = "wm dismiss-keyguard";

    /** Timeout to wait for input dispatch to become ready **/
    private static final long INPUT_DISPATCH_READY_TIMEOUT = 5 * 1000;
    /** command to test input dispatch readiness **/
    private static final String TEST_INPUT_CMD = "dumpsys input";

    private static final long AM_COMMAND_TIMEOUT = 10 * 1000;
    private static final long CHECK_NEW_USER = 1000;

    static final String LIST_PACKAGES_CMD = "pm list packages -f";
    private static final Pattern PACKAGE_REGEX = Pattern.compile("package:(.*)=(.*)");

    static final String LIST_APEXES_CMD = "pm list packages --apex-only --show-versioncode -f";
    private static final Pattern APEXES_WITH_PATH_REGEX =
            Pattern.compile("package:(.*)=(.*) versionCode:(.*)");
    /**
     * Regexp to match on old versions of platform (before R), where {@code -f} flag for the {@code
     * pm list packages apex-only} command wasn't supported.
     */
    private static final Pattern APEXES_WITHOUT_PATH_REGEX =
            Pattern.compile("package:(.*) versionCode:(.*)");

    private static final int FLAG_PRIMARY = 1; // From the UserInfo class

    private static final String[] SETTINGS_NAMESPACE = {"system", "secure", "global"};

    /** user pattern in the output of "pm list users" = TEXT{<id>:<name>:<flags>} TEXT * */
    private static final String USER_PATTERN = "(.*?\\{)(\\d+)(:)(.*)(:)(\\w+)(\\}.*)";
    /** Pattern to find the display ids of "dumpsys SurfaceFlinger" */
    private static final String DISPLAY_ID_PATTERN = "(Display )(?<id>\\d+)( color modes:)";

    private static final int API_LEVEL_GET_CURRENT_USER = 24;
    /** Timeout to wait for a screenshot before giving up to avoid hanging forever */
    private static final long MAX_SCREENSHOT_TIMEOUT = 5 * 60 * 1000; // 5 min

    /** adb shell am dumpheap <service pid> <dump file path> */
    private static final String DUMPHEAP_CMD = "am dumpheap %s %s";
    /** Time given to a file to be dumped on device side */
    private static final long DUMPHEAP_TIME = 5000l;

    /** Timeout in minutes for the package installation */
    static final long INSTALL_TIMEOUT_MINUTES = 4;
    /** Max timeout to output for package installation */
    static final long INSTALL_TIMEOUT_TO_OUTPUT_MINUTES = 3;

    private boolean mWasWifiHelperInstalled = false;

    private static final String APEX_SUFFIX = ".apex";
    private static final String APEX_ARG = "--apex";

    /**
     * @param device
     * @param stateMonitor
     * @param allocationMonitor
     */
    public TestDevice(IDevice device, IDeviceStateMonitor stateMonitor,
            IDeviceMonitor allocationMonitor) {
        super(device, stateMonitor, allocationMonitor);
    }

    @Override
    public boolean isAppEnumerationSupported() throws DeviceNotAvailableException {
        if (!checkApiLevelAgainstNextRelease(30)) {
            return false;
        }
        return hasFeature("android.software.app_enumeration");
    }

    /**
     * Core implementation of package installation, with retries around
     * {@link IDevice#installPackage(String, boolean, String...)}
     * @param packageFile
     * @param reinstall
     * @param extraArgs
     * @return the response from the installation
     * @throws DeviceNotAvailableException
     */
    private String internalInstallPackage(
            final File packageFile, final boolean reinstall, final List<String> extraArgs)
                    throws DeviceNotAvailableException {
        List<String> args = new ArrayList<>(extraArgs);
        if (packageFile.getName().endsWith(APEX_SUFFIX)) {
            args.add(APEX_ARG);
        }
        // use array to store response, so it can be returned to caller
        final String[] response = new String[1];
        DeviceAction installAction =
                new DeviceAction() {
                    @Override
                    public boolean run() throws InstallException {
                        try {
                            InstallReceiver receiver = createInstallReceiver();
                            getIDevice()
                                    .installPackage(
                                            packageFile.getAbsolutePath(),
                                            reinstall,
                                            receiver,
                                            INSTALL_TIMEOUT_MINUTES,
                                            INSTALL_TIMEOUT_TO_OUTPUT_MINUTES,
                                            TimeUnit.MINUTES,
                                            args.toArray(new String[] {}));
                            if (receiver.isSuccessfullyCompleted()) {
                                response[0] = null;
                            } else if (receiver.getErrorMessage() == null) {
                                response[0] =
                                        String.format(
                                                "Installation of %s timed out",
                                                packageFile.getAbsolutePath());
                            } else {
                                response[0] = receiver.getErrorMessage();
                            }
                        } catch (InstallException e) {
                            String message = e.getMessage();
                            if (message == null) {
                                message =
                                        String.format(
                                                "InstallException during package installation. "
                                                        + "cause: %s",
                                                StreamUtil.getStackTrace(e));
                            }
                            response[0] = message;
                        }
                        return response[0] == null;
                    }
                };
        CLog.v(
                "Installing package file %s with args %s on %s",
                packageFile.getAbsolutePath(), extraArgs.toString(), getSerialNumber());
        performDeviceAction(String.format("install %s", packageFile.getAbsolutePath()),
                installAction, MAX_RETRY_ATTEMPTS);
        List<File> packageFiles = new ArrayList();
        packageFiles.add(packageFile);
        allowLegacyStorageForApps(packageFiles);
        return response[0];
    }

    /**
     * Creates and return an {@link InstallReceiver} for {@link #internalInstallPackage(File,
     * boolean, List)} and {@link #installPackage(File, File, boolean, String...)} testing.
     */
    @VisibleForTesting
    InstallReceiver createInstallReceiver() {
        return new InstallReceiver();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String installPackage(final File packageFile, final boolean reinstall,
            final String... extraArgs) throws DeviceNotAvailableException {
        boolean runtimePermissionSupported = isRuntimePermissionSupported();
        List<String> args = new ArrayList<>(Arrays.asList(extraArgs));
        // grant all permissions by default if feature is supported
        if (runtimePermissionSupported) {
            args.add("-g");
        }
        return internalInstallPackage(packageFile, reinstall, args);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String installPackage(File packageFile, boolean reinstall, boolean grantPermissions,
            String... extraArgs) throws DeviceNotAvailableException {
        ensureRuntimePermissionSupported();
        List<String> args = new ArrayList<>(Arrays.asList(extraArgs));
        if (grantPermissions) {
            args.add("-g");
        }
        return internalInstallPackage(packageFile, reinstall, args);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String installPackageForUser(File packageFile, boolean reinstall, int userId,
            String... extraArgs) throws DeviceNotAvailableException {
        boolean runtimePermissionSupported = isRuntimePermissionSupported();
        List<String> args = new ArrayList<>(Arrays.asList(extraArgs));
        // grant all permissions by default if feature is supported
        if (runtimePermissionSupported) {
            args.add("-g");
        }
        args.add("--user");
        args.add(Integer.toString(userId));
        return internalInstallPackage(packageFile, reinstall, args);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String installPackageForUser(File packageFile, boolean reinstall,
            boolean grantPermissions, int userId, String... extraArgs)
                    throws DeviceNotAvailableException {
        ensureRuntimePermissionSupported();
        List<String> args = new ArrayList<>(Arrays.asList(extraArgs));
        if (grantPermissions) {
            args.add("-g");
        }
        args.add("--user");
        args.add(Integer.toString(userId));
        return internalInstallPackage(packageFile, reinstall, args);
    }

    public String installPackage(final File packageFile, final File certFile,
            final boolean reinstall, final String... extraArgs) throws DeviceNotAvailableException {
        // use array to store response, so it can be returned to caller
        final String[] response = new String[1];
        DeviceAction installAction =
                new DeviceAction() {
                    @Override
                    public boolean run()
                            throws InstallException, SyncException, IOException, TimeoutException,
                                    AdbCommandRejectedException {
                        // TODO: create a getIDevice().installPackage(File, File...) method when the
                        // dist cert functionality is ready to be open sourced
                        String remotePackagePath =
                                getIDevice().syncPackageToDevice(packageFile.getAbsolutePath());
                        String remoteCertPath =
                                getIDevice().syncPackageToDevice(certFile.getAbsolutePath());
                        // trick installRemotePackage into issuing a 'pm install <apk> <cert>'
                        // command, by adding apk path to extraArgs, and using cert as the
                        // 'apk file'.
                        String[] newExtraArgs = new String[extraArgs.length + 1];
                        System.arraycopy(extraArgs, 0, newExtraArgs, 0, extraArgs.length);
                        newExtraArgs[newExtraArgs.length - 1] =
                                String.format("\"%s\"", remotePackagePath);
                        try {
                            InstallReceiver receiver = createInstallReceiver();
                            getIDevice()
                                    .installRemotePackage(
                                            remoteCertPath,
                                            reinstall,
                                            receiver,
                                            INSTALL_TIMEOUT_MINUTES,
                                            INSTALL_TIMEOUT_TO_OUTPUT_MINUTES,
                                            TimeUnit.MINUTES,
                                            newExtraArgs);
                            if (receiver.isSuccessfullyCompleted()) {
                                response[0] = null;
                            } else if (receiver.getErrorMessage() == null) {
                                response[0] =
                                        String.format(
                                                "Installation of %s timed out.",
                                                packageFile.getAbsolutePath());
                            } else {
                                response[0] = receiver.getErrorMessage();
                            }
                        } catch (InstallException e) {
                            String message = e.getMessage();
                            if (message == null) {
                                message =
                                        String.format(
                                                "InstallException during package installation. "
                                                        + "cause: %s",
                                                StreamUtil.getStackTrace(e));
                            }
                            response[0] = message;
                        } finally {
                            getIDevice().removeRemotePackage(remotePackagePath);
                            getIDevice().removeRemotePackage(remoteCertPath);
                        }
                        return true;
                    }
                };
        performDeviceAction(String.format("install %s", packageFile.getAbsolutePath()),
                installAction, MAX_RETRY_ATTEMPTS);
        List<File> packageFiles = new ArrayList();
        packageFiles.add(packageFile);
        allowLegacyStorageForApps(packageFiles);
        return response[0];
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String uninstallPackage(final String packageName) throws DeviceNotAvailableException {
        // use array to store response, so it can be returned to caller
        final String[] response = new String[1];
        DeviceAction uninstallAction = new DeviceAction() {
            @Override
            public boolean run() throws InstallException {
                CLog.d("Uninstalling %s", packageName);
                String result = getIDevice().uninstallPackage(packageName);
                response[0] = result;
                return result == null;
            }
        };
        performDeviceAction(String.format("uninstall %s", packageName), uninstallAction,
                MAX_RETRY_ATTEMPTS);
        return response[0];
    }

    /**
     * Core implementation for installing application with split apk files {@link
     * IDevice#installPackages(List, boolean, List)} See
     * "https://developer.android.com/studio/build/configure-apk-splits" on how to split apk to
     * several files.
     *
     * @param packageFiles the local apk files
     * @param reinstall <code>true</code> if a reinstall should be performed
     * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
     *     options.
     * @return the response from the installation <code>null</code> if installation succeeds.
     * @throws DeviceNotAvailableException
     */
    private String internalInstallPackages(
            final List<File> packageFiles, final boolean reinstall, final List<String> extraArgs)
            throws DeviceNotAvailableException {
        // use array to store response, so it can be returned to caller
        final String[] response = new String[1];
        DeviceAction installAction =
                new DeviceAction() {
                    @Override
                    public boolean run() throws InstallException {
                        try {
                            getIDevice()
                                    .installPackages(
                                            packageFiles,
                                            reinstall,
                                            extraArgs,
                                            INSTALL_TIMEOUT_MINUTES,
                                            TimeUnit.MINUTES);
                            response[0] = null;
                            return true;
                        } catch (InstallException e) {
                            response[0] = e.getMessage();
                            if (response[0] == null) {
                                response[0] =
                                        String.format(
                                                "InstallException: %s",
                                                StreamUtil.getStackTrace(e));
                            }
                            return false;
                        }
                    }
                };
        performDeviceAction(
                String.format("install %s", packageFiles.toString()),
                installAction,
                MAX_RETRY_ATTEMPTS);
        allowLegacyStorageForApps(packageFiles);
        return response[0];
    }

    /**
     * Allows Legacy External Storage access for apps that request for it.
     *
     * <p>Apps that request for legacy external storage access are granted the access by setting
     * MANAGE_EXTERNAL_STORAGE App Op. This gives the app File manager privileges, File managers
     * have legacy external storage access.
     *
     * @param appFiles List of Files. Apk Files of the apps that are installed.
     */
    private void allowLegacyStorageForApps(List<File> appFiles) throws DeviceNotAvailableException {
        for (File appFile : appFiles) {
            AaptParser aaptParser = AaptParser.parse(appFile);
            if (aaptParser != null
                    && aaptParser.getTargetSdkVersion() > 29
                    && aaptParser.isRequestingLegacyStorage()) {
                if (!aaptParser.isUsingPermissionManageExternalStorage()) {
                    CLog.w(
                            "App is requesting legacy storage and targets R or above, but didn't"
                                    + " request the MANAGE_EXTERNAL_STORAGE permission so the"
                                    + " associated app op cannot be automatically granted and the"
                                    + " app won't have legacy external storage access: "
                                    + aaptParser.getPackageName());
                    continue;
                }
                // Set the MANAGE_EXTERNAL_STORAGE App Op to MODE_ALLOWED (Code = 0)
                // for all users.
                ArrayList<Integer> userIds = listUsers();
                for (int userId : userIds) {
                    CommandResult setFileManagerAppOpResult =
                            executeShellV2Command(
                                    "appops set --user "
                                            + userId
                                            + " --uid "
                                            + aaptParser.getPackageName()
                                            + " MANAGE_EXTERNAL_STORAGE 0");
                    if (!CommandStatus.SUCCESS.equals(setFileManagerAppOpResult.getStatus())) {
                        CLog.e(
                                "Failed to set MANAGE_EXTERNAL_STORAGE App Op to"
                                        + " allow legacy external storage for: %s ; stderr: %s",
                                aaptParser.getPackageName(), setFileManagerAppOpResult.getStderr());
                    }
                }
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public String installPackages(
            final List<File> packageFiles, final boolean reinstall, final String... extraArgs)
            throws DeviceNotAvailableException {
        // Grant all permissions by default if feature is supported
        return installPackages(packageFiles, reinstall, isRuntimePermissionSupported(), extraArgs);
    }

    /** {@inheritDoc} */
    @Override
    public String installPackages(
            List<File> packageFiles,
            boolean reinstall,
            boolean grantPermissions,
            String... extraArgs)
            throws DeviceNotAvailableException {
        List<String> args = new ArrayList<>(Arrays.asList(extraArgs));
        if (grantPermissions) {
            ensureRuntimePermissionSupported();
            args.add("-g");
        }
        return internalInstallPackages(packageFiles, reinstall, args);
    }

    /** {@inheritDoc} */
    @Override
    public String installPackagesForUser(
            List<File> packageFiles, boolean reinstall, int userId, String... extraArgs)
            throws DeviceNotAvailableException {
        // Grant all permissions by default if feature is supported
        return installPackagesForUser(
                packageFiles, reinstall, isRuntimePermissionSupported(), userId, extraArgs);
    }

    /** {@inheritDoc} */
    @Override
    public String installPackagesForUser(
            List<File> packageFiles,
            boolean reinstall,
            boolean grantPermissions,
            int userId,
            String... extraArgs)
            throws DeviceNotAvailableException {
        List<String> args = new ArrayList<>(Arrays.asList(extraArgs));
        if (grantPermissions) {
            ensureRuntimePermissionSupported();
            args.add("-g");
        }
        args.add("--user");
        args.add(Integer.toString(userId));
        return internalInstallPackages(packageFiles, reinstall, args);
    }

    /**
     * Core implementation for split apk remote installation {@link IDevice#installPackage(String,
     * boolean, String...)} See "https://developer.android.com/studio/build/configure-apk-splits" on
     * how to split apk to several files.
     *
     * @param remoteApkPaths the remote apk file paths
     * @param reinstall <code>true</code> if a reinstall should be performed
     * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
     *     options.
     * @return the response from the installation <code>null</code> if installation succeeds.
     * @throws DeviceNotAvailableException
     */
    private String internalInstallRemotePackages(
            final List<String> remoteApkPaths,
            final boolean reinstall,
            final List<String> extraArgs)
            throws DeviceNotAvailableException {
        // use array to store response, so it can be returned to caller
        final String[] response = new String[1];
        DeviceAction installAction =
                new DeviceAction() {
                    @Override
                    public boolean run() throws InstallException {
                        try {
                            getIDevice()
                                    .installRemotePackages(
                                            remoteApkPaths,
                                            reinstall,
                                            extraArgs,
                                            INSTALL_TIMEOUT_MINUTES,
                                            TimeUnit.MINUTES);
                            response[0] = null;
                            return true;
                        } catch (InstallException e) {
                            response[0] = e.getMessage();
                            if (response[0] == null) {
                                response[0] = String.format(
                                    "InstallException during package installation. cause: %s",
                                    StreamUtil.getStackTrace(e));
                            }
                            return false;
                        }
                    }
                };
        performDeviceAction(
                String.format("install %s", remoteApkPaths.toString()),
                installAction,
                MAX_RETRY_ATTEMPTS);
        return response[0];
    }

    /** {@inheritDoc} */
    @Override
    public String installRemotePackages(
            final List<String> remoteApkPaths, final boolean reinstall, final String... extraArgs)
            throws DeviceNotAvailableException {
        // Grant all permissions by default if feature is supported
        return installRemotePackages(
                remoteApkPaths, reinstall, isRuntimePermissionSupported(), extraArgs);
    }

    /** {@inheritDoc} */
    @Override
    public String installRemotePackages(
            List<String> remoteApkPaths,
            boolean reinstall,
            boolean grantPermissions,
            String... extraArgs)
            throws DeviceNotAvailableException {
        List<String> args = new ArrayList<>(Arrays.asList(extraArgs));
        if (grantPermissions) {
            ensureRuntimePermissionSupported();
            args.add("-g");
        }
        return internalInstallRemotePackages(remoteApkPaths, reinstall, args);
    }

    /** {@inheritDoc} */
    @Override
    public InputStreamSource getScreenshot() throws DeviceNotAvailableException {
        return getScreenshot("PNG");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputStreamSource getScreenshot(String format) throws DeviceNotAvailableException {
        return getScreenshot(format, true);
    }

    /** {@inheritDoc} */
    @Override
    public InputStreamSource getScreenshot(String format, boolean rescale)
            throws DeviceNotAvailableException {
        if (!format.equalsIgnoreCase("PNG") && !format.equalsIgnoreCase("JPEG")){
            CLog.e("Screenshot: Format %s is not supported, defaulting to PNG.", format);
            format = "PNG";
        }
        ScreenshotAction action = new ScreenshotAction();
        if (performDeviceAction("screenshot", action, MAX_RETRY_ATTEMPTS)) {
            byte[] imageData =
                    compressRawImage(action.mRawScreenshot, format.toUpperCase(), rescale);
            if (imageData != null) {
                return new ByteArrayInputStreamSource(imageData);
            }
        }
        // Return an error in the buffer
        return new ByteArrayInputStreamSource(
                "Error: device reported null for screenshot.".getBytes());
    }

    /** {@inheritDoc} */
    @Override
    public InputStreamSource getScreenshot(long displayId) throws DeviceNotAvailableException {
        final String tmpDevicePath = String.format("/data/local/tmp/display_%s.png", displayId);
        CommandResult result =
                executeShellV2Command(
                        String.format("screencap -p -d %s %s", displayId, tmpDevicePath));
        if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
            // Return an error in the buffer
            CLog.e("Error: device reported error for screenshot: %s", result.getStderr());
            return null;
        }
        try {
            File tmpScreenshot = pullFile(tmpDevicePath);
            if (tmpScreenshot == null) {
                return null;
            }
            return new FileInputStreamSource(tmpScreenshot, true);
        } finally {
            deleteFile(tmpDevicePath);
        }
    }

    private class ScreenshotAction implements DeviceAction {

        RawImage mRawScreenshot;

        /**
         * {@inheritDoc}
         */
        @Override
        public boolean run() throws IOException, TimeoutException, AdbCommandRejectedException,
                ShellCommandUnresponsiveException, InstallException, SyncException {
            mRawScreenshot =
                    getIDevice().getScreenshot(MAX_SCREENSHOT_TIMEOUT, TimeUnit.MILLISECONDS);
            return mRawScreenshot != null;
        }
    }

    /**
     * Helper to compress a rawImage obtained from the screen.
     *
     * @param rawImage {@link RawImage} to compress.
     * @param format resulting format of compressed image. PNG and JPEG are supported.
     * @param rescale if rescaling should be done to further reduce size of compressed image.
     * @return compressed image.
     */
    @VisibleForTesting
    byte[] compressRawImage(RawImage rawImage, String format, boolean rescale) {
        BufferedImage image = rawImageToBufferedImage(rawImage, format);

        // Rescale to reduce size if needed
        // Screenshot default format is 1080 x 1920, 8-bit/color RGBA
        // By cutting in half we can easily keep good quality and smaller size
        if (rescale) {
            image = rescaleImage(image);
        }

        return getImageData(image, format);
    }

    /**
     * Converts {@link RawImage} to {@link BufferedImage} in specified format.
     *
     * @param rawImage {@link RawImage} to convert.
     * @param format resulting format of image. PNG and JPEG are supported.
     * @return converted image.
     */
    @VisibleForTesting
    BufferedImage rawImageToBufferedImage(RawImage rawImage, String format) {
        BufferedImage image = null;

        if ("JPEG".equalsIgnoreCase(format)) {
            //JPEG does not support ARGB without a special encoder
            image =
                    new BufferedImage(
                            rawImage.width, rawImage.height, BufferedImage.TYPE_3BYTE_BGR);
        }
        else {
            image = new BufferedImage(rawImage.width, rawImage.height, BufferedImage.TYPE_INT_ARGB);
        }

        // borrowed conversion logic from platform/sdk/screenshot/.../Screenshot.java
        int index = 0;
        int IndexInc = rawImage.bpp >> 3;
        for (int y = 0 ; y < rawImage.height ; y++) {
            for (int x = 0 ; x < rawImage.width ; x++) {
                int value = rawImage.getARGB(index);
                index += IndexInc;
                image.setRGB(x, y, value);
            }
        }

        return image;
    }

    /**
     * Rescales image cutting it in half.
     *
     * @param image source {@link BufferedImage}.
     * @return resulting scaled image.
     */
    @VisibleForTesting
    BufferedImage rescaleImage(BufferedImage image) {
        int shortEdge = Math.min(image.getHeight(), image.getWidth());
        if (shortEdge > 720) {
            Image resized =
                    image.getScaledInstance(
                            image.getWidth() / 2, image.getHeight() / 2, Image.SCALE_SMOOTH);
            image =
                    new BufferedImage(
                            image.getWidth() / 2, image.getHeight() / 2, Image.SCALE_REPLICATE);
            image.getGraphics().drawImage(resized, 0, 0, null);
        }
        return image;
    }

    /**
     * Gets byte array representation of {@link BufferedImage}.
     *
     * @param image source {@link BufferedImage}.
     * @param format resulting format of image. PNG and JPEG are supported.
     * @return byte array representation of the image.
     */
    @VisibleForTesting
    byte[] getImageData(BufferedImage image, String format) {
        // store compressed image in memory, and let callers write to persistent storage
        // use initial buffer size of 128K
        byte[] imageData = null;
        ByteArrayOutputStream imageOut = new ByteArrayOutputStream(128*1024);
        try {
            if (ImageIO.write(image, format, imageOut)) {
                imageData = imageOut.toByteArray();
            } else {
                CLog.e("Failed to compress screenshot to png");
            }
        } catch (IOException e) {
            CLog.e("Failed to compress screenshot to png");
            CLog.e(e);
        }
        StreamUtil.close(imageOut);
        return imageData;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean clearErrorDialogs() throws DeviceNotAvailableException {
        // attempt to clear error dialogs multiple times
        for (int i = 0; i < NUM_CLEAR_ATTEMPTS; i++) {
            int numErrorDialogs = getErrorDialogCount();
            if (numErrorDialogs == 0) {
                return true;
            }
            doClearDialogs(numErrorDialogs);
        }
        if (getErrorDialogCount() > 0) {
            // at this point, all attempts to clear error dialogs completely have failed
            // it might be the case that the process keeps showing new dialogs immediately after
            // clearing. There's really no workaround, but to dump an error
            CLog.e("error dialogs still exist on %s.", getSerialNumber());
            return false;
        }
        return true;
    }

    /**
     * Detects the number of crash or ANR dialogs currently displayed.
     * <p/>
     * Parses output of 'dump activity processes'
     *
     * @return count of dialogs displayed
     * @throws DeviceNotAvailableException
     */
    private int getErrorDialogCount() throws DeviceNotAvailableException {
        int errorDialogCount = 0;
        Pattern crashPattern = Pattern.compile(".*crashing=true.*AppErrorDialog.*");
        Pattern anrPattern = Pattern.compile(".*notResponding=true.*AppNotRespondingDialog.*");
        String systemStatusOutput =
                executeShellCommand(
                        "dumpsys activity processes | grep -e .*crashing=true.*AppErrorDialog.* -e .*notResponding=true.*AppNotRespondingDialog.*");
        Matcher crashMatcher = crashPattern.matcher(systemStatusOutput);
        while (crashMatcher.find()) {
            errorDialogCount++;
        }
        Matcher anrMatcher = anrPattern.matcher(systemStatusOutput);
        while (anrMatcher.find()) {
            errorDialogCount++;
        }

        return errorDialogCount;
    }

    private void doClearDialogs(int numDialogs) throws DeviceNotAvailableException {
        CLog.i("Attempted to clear %d dialogs on %s", numDialogs, getSerialNumber());
        for (int i=0; i < numDialogs; i++) {
            // send DPAD_CENTER
            executeShellCommand(DISMISS_DIALOG_CMD);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void disableKeyguard() throws DeviceNotAvailableException {
        long start = System.currentTimeMillis();
        while (true) {
            Boolean ready = isDeviceInputReady();
            if (ready == null) {
                // unsupported API level, bail
                break;
            }
            if (ready) {
                // input dispatch is ready, bail
                break;
            }
            long timeSpent = System.currentTimeMillis() - start;
            if (timeSpent > INPUT_DISPATCH_READY_TIMEOUT) {
                CLog.w("Timeout after waiting %dms on enabling of input dispatch", timeSpent);
                // break & proceed anyway
                break;
            } else {
                getRunUtil().sleep(1000);
            }
        }
        if (getApiLevel() >= 23) {
            CLog.i(
                    "Attempting to disable keyguard on %s using %s",
                    getSerialNumber(), DISMISS_KEYGUARD_WM_CMD);
            String output = executeShellCommand(DISMISS_KEYGUARD_WM_CMD);
            CLog.i("output of %s: %s", DISMISS_KEYGUARD_WM_CMD, output);
        } else {
            CLog.i("Command: %s, is not supported, falling back to %s", DISMISS_KEYGUARD_WM_CMD,
                    DISMISS_KEYGUARD_CMD);
            executeShellCommand(DISMISS_KEYGUARD_CMD);
        }
        // TODO: check that keyguard was actually dismissed.
    }

    /** {@inheritDoc} */
    @Override
    public KeyguardControllerState getKeyguardState() throws DeviceNotAvailableException {
        String output =
                executeShellCommand("dumpsys activity activities | grep -A3 KeyguardController:");
        CLog.d("Output from KeyguardController: %s", output);
        KeyguardControllerState state =
                KeyguardControllerState.create(Arrays.asList(output.trim().split("\n")));
        return state;
    }

    /**
     * Tests the device to see if input dispatcher is ready
     *
     * @return <code>null</code> if not supported by platform, or the actual readiness state
     * @throws DeviceNotAvailableException
     */
    Boolean isDeviceInputReady() throws DeviceNotAvailableException {
        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
        executeShellCommand(TEST_INPUT_CMD, receiver);
        String output = receiver.getOutput();
        Matcher m = INPUT_DISPATCH_STATE_REGEX.matcher(output);
        if (!m.find()) {
            // output does not contain the line at all, implying unsupported API level, bail
            return null;
        }
        return "1".equals(m.group(1));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void prePostBootSetup() throws DeviceNotAvailableException {
        if (mOptions.isDisableKeyguard()) {
            disableKeyguard();
        }
    }

    /**
     * Performs an reboot via framework power manager
     *
     * <p>Must have root access, device must be API Level 18 or above
     *
     * @param rebootMode a mode of this reboot.
     * @param reason for this reboot.
     * @return <code>true</code> if the device rebooted, <code>false</code> if not successful or
     *     unsupported
     * @throws DeviceNotAvailableException
     */
    private boolean doAdbFrameworkReboot(RebootMode rebootMode, @Nullable final String reason)
            throws DeviceNotAvailableException {
        // use framework reboot when:
        // 1. device API level >= 18
        // 2. has adb root
        // 3. framework is running
        if (!isEnableAdbRoot()) {
            CLog.i("framework reboot is not supported; when enable root is disabled");
            return false;
        }
        enableAdbRoot();
        if (getApiLevel() >= 18 && isAdbRoot()) {
            try {
                // check framework running
                String output = executeShellCommand("pm path android");
                if (output == null || !output.contains("package:")) {
                    CLog.v("framework reboot: can't detect framework running");
                    return false;
                }
                String command = "svc power reboot " + rebootMode.formatRebootCommand(reason);
                executeShellCommand(command);
            } catch (DeviceUnresponsiveException due) {
                CLog.v("framework reboot: device unresponsive to shell command, using fallback");
                return false;
            }
            boolean notAvailable = waitForDeviceNotAvailable(30 * 1000);
            if (notAvailable) {
                postAdbReboot();
            }
            return notAvailable;
        } else {
            CLog.v("framework reboot: not supported");
            return false;
        }
    }

    /**
     * Perform a adb reboot.
     *
     * @param rebootMode a mode of this reboot.
     * @param reason for this reboot.
     * @throws DeviceNotAvailableException
     */
    @Override
    protected void doAdbReboot(RebootMode rebootMode, @Nullable final String reason)
            throws DeviceNotAvailableException {
        if (!TestDeviceState.ONLINE.equals(getDeviceState())
                || !doAdbFrameworkReboot(rebootMode, reason)) {
            super.doAdbReboot(rebootMode, reason);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set<String> getInstalledPackageNames() throws DeviceNotAvailableException {
        return getInstalledPackageNames(null, null);
    }

    /** {@inheritDoc} */
    @Override
    public boolean isPackageInstalled(String packageName) throws DeviceNotAvailableException {
        return getInstalledPackageNames(packageName, null).contains(packageName);
    }

    /** {@inheritDoc} */
    @Override
    public boolean isPackageInstalled(String packageName, String userId)
            throws DeviceNotAvailableException {
        return getInstalledPackageNames(packageName, userId).contains(packageName);
    }

    /** {@inheritDoc} */
    @Override
    public Set<ApexInfo> getActiveApexes() throws DeviceNotAvailableException {
        String output = executeShellCommand(LIST_APEXES_CMD);
        // Optimistically parse expecting platform to return paths. If it doesn't, empty set will
        // be returned.
        Set<ApexInfo> ret = parseApexesFromOutput(output, true /* withPath */);
        if (ret.isEmpty()) {
            ret = parseApexesFromOutput(output, false /* withPath */);
        }
        return ret;
    }

    private Set<ApexInfo> parseApexesFromOutput(final String output, boolean withPath) {
        Set<ApexInfo> ret = new HashSet<>();
        Matcher matcher =
                withPath
                        ? APEXES_WITH_PATH_REGEX.matcher(output)
                        : APEXES_WITHOUT_PATH_REGEX.matcher(output);
        while (matcher.find()) {
            if (withPath) {
                String sourceDir = matcher.group(1);
                String name = matcher.group(2);
                long version = Long.valueOf(matcher.group(3));
                ret.add(new ApexInfo(name, version, sourceDir));
            } else {
                String name = matcher.group(1);
                long version = Long.valueOf(matcher.group(2));
                ret.add(new ApexInfo(name, version));
            }
        }
        return ret;
    }

    /**
     * A {@link com.android.tradefed.device.NativeDevice.DeviceAction}
     * for retrieving package system service info, and do retries on
     * failures.
     */
    private class DumpPkgAction implements DeviceAction {

        Map<String, PackageInfo> mPkgInfoMap;

        DumpPkgAction() {
        }

        @Override
        public boolean run() throws IOException, TimeoutException, AdbCommandRejectedException,
                ShellCommandUnresponsiveException, InstallException, SyncException {
            DumpsysPackageReceiver receiver = new DumpsysPackageReceiver();
            getIDevice().executeShellCommand("dumpsys package p", receiver);
            mPkgInfoMap = receiver.getPackages();
            if (mPkgInfoMap.size() == 0) {
                // Package parsing can fail if package manager is currently down. throw exception
                // to retry
                CLog.w("no packages found from dumpsys package p.");
                throw new IOException();
            }
            return true;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set<String> getUninstallablePackageNames() throws DeviceNotAvailableException {
        DumpPkgAction action = new DumpPkgAction();
        performDeviceAction("dumpsys package p", action, MAX_RETRY_ATTEMPTS);

        Set<String> pkgs = new HashSet<String>();
        for (PackageInfo pkgInfo : action.mPkgInfoMap.values()) {
            if (!pkgInfo.isSystemApp() || pkgInfo.isUpdatedSystemApp()) {
                CLog.d("Found uninstallable package %s", pkgInfo.getPackageName());
                pkgs.add(pkgInfo.getPackageName());
            }
        }
        return pkgs;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PackageInfo getAppPackageInfo(String packageName) throws DeviceNotAvailableException {
        DumpPkgAction action = new DumpPkgAction();
        performDeviceAction("dumpsys package", action, MAX_RETRY_ATTEMPTS);
        return action.mPkgInfoMap.get(packageName);
    }

    /** {@inheritDoc} */
    @Override
    public List<PackageInfo> getAppPackageInfos() throws DeviceNotAvailableException {
        DumpPkgAction action = new DumpPkgAction();
        performDeviceAction("dumpsys package", action, MAX_RETRY_ATTEMPTS);
        return new ArrayList<>(action.mPkgInfoMap.values());
    }

    // TODO: convert this to use DumpPkgAction
    private Set<String> getInstalledPackageNames(String packageNameSearched, String userId)
            throws DeviceNotAvailableException {
        Set<String> packages= new HashSet<String>();
        String command = LIST_PACKAGES_CMD;
        if (userId != null) {
            command += String.format(" --user %s", userId);
        }
        if (packageNameSearched != null) {
            command += (" | grep " + packageNameSearched);
        }
        String output = executeShellCommand(command);
        if (output != null) {
            Matcher m = PACKAGE_REGEX.matcher(output);
            while (m.find()) {
                String packageName = m.group(2);
                if (packageNameSearched != null && packageName.equals(packageNameSearched)) {
                    packages.add(packageName);
                } else if (packageNameSearched == null) {
                    packages.add(packageName);
                }
            }
        }
        return packages;
    }

    /** {@inheritDoc} */
    @Override
    public boolean doesFileExist(String deviceFilePath) throws DeviceNotAvailableException {
        if (deviceFilePath.startsWith(SD_CARD)) {
            deviceFilePath =
                    deviceFilePath.replaceFirst(
                            SD_CARD, String.format("/storage/emulated/%s/", getCurrentUser()));
        }
        return super.doesFileExist(deviceFilePath);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ArrayList<Integer> listUsers() throws DeviceNotAvailableException {
        ArrayList<String[]> users = tokenizeListUsers();
        ArrayList<Integer> userIds = new ArrayList<Integer>(users.size());
        for (String[] user : users) {
            userIds.add(Integer.parseInt(user[1]));
        }
        return userIds;
    }

    /** {@inheritDoc} */
    @Override
    public Map<Integer, UserInfo> getUserInfos() throws DeviceNotAvailableException {
        ArrayList<String[]> lines = tokenizeListUsers();
        Map<Integer, UserInfo> result = new HashMap<Integer, UserInfo>(lines.size());
        for (String[] tokens : lines) {
            UserInfo userInfo =
                    new UserInfo(
                            /* userId= */ Integer.parseInt(tokens[1]),
                            /* userName= */ tokens[2],
                            /* flag= */ Integer.parseInt(tokens[3], 16),
                            /* isRunning= */ tokens.length >= 5
                                    ? tokens[4].contains("running")
                                    : false);
            result.put(userInfo.userId(), userInfo);
        }
        return result;
    }

    /**
     * Tokenizes the output of 'pm list users'.
     * The returned tokens for each user have the form: {"\tUserInfo", Integer.toString(id), name,
     * Integer.toHexString(flag), "[running]"}; (the last one being optional)
     * @return a list of arrays of strings, each element of the list representing the tokens
     * for a user, or {@code null} if there was an error while tokenizing the adb command output.
     */
    private ArrayList<String[]> tokenizeListUsers() throws DeviceNotAvailableException {
        String command = "pm list users";
        String commandOutput = executeShellCommand(command);
        // Extract the id of all existing users.
        String[] lines = commandOutput.split("\\r?\\n");
        if (!lines[0].equals("Users:")) {
            throw new DeviceRuntimeException(
                    String.format("'%s' in not a valid output for 'pm list users'", commandOutput));
        }
        ArrayList<String[]> users = new ArrayList<String[]>(lines.length - 1);
        for (int i = 1; i < lines.length; i++) {
            // Individual user is printed out like this:
            // \tUserInfo{$id$:$name$:$Integer.toHexString(flags)$} [running]
            String[] tokens = lines[i].split("\\{|\\}|:");
            if (tokens.length != 4 && tokens.length != 5) {
                throw new DeviceRuntimeException(
                        String.format(
                                "device output: '%s' \nline: '%s' was not in the expected "
                                        + "format for user info.",
                                commandOutput, lines[i]));
            }
            users.add(tokens);
        }
        return users;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getMaxNumberOfUsersSupported() throws DeviceNotAvailableException {
        String command = "pm get-max-users";
        String commandOutput = executeShellCommand(command);
        try {
            return Integer.parseInt(commandOutput.substring(commandOutput.lastIndexOf(" ")).trim());
        } catch (NumberFormatException e) {
            CLog.e("Failed to parse result: %s", commandOutput);
        }
        return 0;
    }

    /** {@inheritDoc} */
    @Override
    public int getMaxNumberOfRunningUsersSupported() throws DeviceNotAvailableException {
        checkApiLevelAgainstNextRelease("get-max-running-users", 28);
        String command = "pm get-max-running-users";
        String commandOutput = executeShellCommand(command);
        try {
            return Integer.parseInt(commandOutput.substring(commandOutput.lastIndexOf(" ")).trim());
        } catch (NumberFormatException e) {
            CLog.e("Failed to parse result: %s", commandOutput);
        }
        return 0;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isMultiUserSupported() throws DeviceNotAvailableException {
        return getMaxNumberOfUsersSupported() > 1;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int createUser(String name) throws DeviceNotAvailableException, IllegalStateException {
        return createUser(name, false, false);
    }

    /** {@inheritDoc} */
    @Override
    public int createUserNoThrow(String name) throws DeviceNotAvailableException {
        try {
            return createUser(name);
        } catch (IllegalStateException e) {
            CLog.e("Error creating user: " + e.toString());
            return -1;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int createUser(String name, boolean guest, boolean ephemeral)
            throws DeviceNotAvailableException, IllegalStateException {
        String command ="pm create-user " + (guest ? "--guest " : "")
                + (ephemeral ? "--ephemeral " : "") + name;
        final String output = executeShellCommand(command);
        if (output.startsWith("Success")) {
            try {
                resetContentProviderSetup();
                return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim());
            } catch (NumberFormatException e) {
                CLog.e("Failed to parse result: %s", output);
            }
        }
        throw new IllegalStateException(String.format("Failed to create user: %s", output));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean removeUser(int userId) throws DeviceNotAvailableException {
        final String output = executeShellCommand(String.format("pm remove-user %s", userId));
        if (output.startsWith("Error")) {
            CLog.e("Failed to remove user %d on device %s: %s", userId, getSerialNumber(), output);
            return false;
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean startUser(int userId) throws DeviceNotAvailableException {
        return startUser(userId, false);
    }

    /** {@inheritDoc} */
    @Override
    public boolean startUser(int userId, boolean waitFlag) throws DeviceNotAvailableException {
        if (waitFlag) {
            checkApiLevelAgainstNextRelease("start-user -w", 29);
        }
        String cmd = "am start-user " + (waitFlag ? "-w " : "") + userId;

        CLog.d("Starting user with command: %s", cmd);
        final String output = executeShellCommand(cmd);
        if (output.startsWith("Error")) {
            CLog.e("Failed to start user: %s", output);
            return false;
        }
        if (waitFlag) {
            String state = executeShellCommand("am get-started-user-state " + userId);
            if (!state.contains("RUNNING_UNLOCKED")) {
                CLog.w("User %s is not RUNNING_UNLOCKED after start-user -w. (%s).", userId, state);
                return false;
            }
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean stopUser(int userId) throws DeviceNotAvailableException {
        // No error or status code is returned.
        return stopUser(userId, false, false);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean stopUser(int userId, boolean waitFlag, boolean forceFlag)
            throws DeviceNotAvailableException {
        final int apiLevel = getApiLevel();
        if (waitFlag && apiLevel < 23) {
            throw new IllegalArgumentException("stop-user -w requires API level >= 23");
        }
        if (forceFlag && apiLevel < 24) {
            throw new IllegalArgumentException("stop-user -f requires API level >= 24");
        }
        StringBuilder cmd = new StringBuilder("am stop-user ");
        if (waitFlag) {
            cmd.append("-w ");
        }
        if (forceFlag) {
            cmd.append("-f ");
        }
        cmd.append(userId);

        CLog.d("stopping user with command: %s", cmd.toString());
        final String output = executeShellCommand(cmd.toString());
        if (output.contains("Error: Can't stop system user")) {
            CLog.e("Cannot stop System user.");
            return false;
        }
        if (output.contains("Can't stop current user")) {
            CLog.e("Cannot stop current user.");
            return false;
        }
        if (isUserRunning(userId)) {
            CLog.w("User Id: %s is still running after the stop-user command.", userId);
            return false;
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Integer getPrimaryUserId() throws DeviceNotAvailableException {
        ArrayList<String[]> users = tokenizeListUsers();
        for (String[] user : users) {
            int flag = Integer.parseInt(user[3], 16);
            if ((flag & FLAG_PRIMARY) != 0) {
                return Integer.parseInt(user[1]);
            }
        }
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public int getCurrentUser() throws DeviceNotAvailableException {
        checkApiLevelAgainstNextRelease("get-current-user", API_LEVEL_GET_CURRENT_USER);
        final String output = executeShellCommand("am get-current-user");
        try {
            int userId = Integer.parseInt(output.trim());
            if (userId >= 0) {
                return userId;
            }
            CLog.e("Invalid user id '%s' was returned for get-current-user", userId);
        } catch (NumberFormatException e) {
            CLog.e("Invalid string was returned for get-current-user: %s.", output);
            CLog.e(e);
        }
        return INVALID_USER_ID;
    }

    private Matcher findUserInfo(String pmListUsersOutput) {
        Pattern pattern = Pattern.compile(USER_PATTERN);
        Matcher matcher = pattern.matcher(pmListUsersOutput);
        return matcher;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getUserFlags(int userId) throws DeviceNotAvailableException {
        checkApiLevelAgainst("getUserFlags", 22);
        final String commandOutput = executeShellCommand("pm list users");
        Matcher matcher = findUserInfo(commandOutput);
        while(matcher.find()) {
            if (Integer.parseInt(matcher.group(2)) == userId) {
                return Integer.parseInt(matcher.group(6), 16);
            }
        }
        CLog.w("Could not find any flags for userId: %d in output: %s", userId, commandOutput);
        return INVALID_USER_ID;
    }

    /** {@inheritDoc} */
    @Override
    public boolean isUserSecondary(int userId) throws DeviceNotAvailableException {
        if (userId == UserInfo.USER_SYSTEM) {
            return false;
        }
        int flags = getUserFlags(userId);
        if (flags == INVALID_USER_ID) {
            return false;
        }
        return (flags & UserInfo.FLAGS_NOT_SECONDARY) == 0;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isUserRunning(int userId) throws DeviceNotAvailableException {
        checkApiLevelAgainst("isUserIdRunning", 22);
        final String commandOutput = executeShellCommand("pm list users");
        Matcher matcher = findUserInfo(commandOutput);
        while(matcher.find()) {
            if (Integer.parseInt(matcher.group(2)) == userId) {
                if (matcher.group(7).contains("running")) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getUserSerialNumber(int userId) throws DeviceNotAvailableException {
        checkApiLevelAgainst("getUserSerialNumber", 22);
        final String commandOutput = executeShellCommand("dumpsys user");
        // example: UserInfo{0:Test:13} serialNo=0
        String userSerialPatter = "(.*\\{)(\\d+)(.*\\})(.*=)(\\d+)";
        Pattern pattern = Pattern.compile(userSerialPatter);
        Matcher matcher = pattern.matcher(commandOutput);
        while(matcher.find()) {
            if (Integer.parseInt(matcher.group(2)) == userId) {
                return Integer.parseInt(matcher.group(5));
            }
        }
        CLog.w("Could not find user serial number for userId: %d, in output: %s",
                userId, commandOutput);
        return INVALID_USER_ID;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean switchUser(int userId) throws DeviceNotAvailableException {
        return switchUser(userId, AM_COMMAND_TIMEOUT);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean switchUser(int userId, long timeout) throws DeviceNotAvailableException {
        checkApiLevelAgainstNextRelease("switchUser", API_LEVEL_GET_CURRENT_USER);
        if (userId == getCurrentUser()) {
            CLog.w("Already running as user id: %s. Nothing to be done.", userId);
            return true;
        }

        String switchCommand =
                checkApiLevelAgainstNextRelease(30)
                        ? String.format("am switch-user -w %d", userId)
                        : String.format("am switch-user %d", userId);

        resetContentProviderSetup();
        long initialTime = getHostCurrentTime();
        String output = executeShellCommand(switchCommand);
        boolean success = userId == getCurrentUser();

        while (!success && (getHostCurrentTime() - initialTime <= timeout)) {
            // retry
            RunUtil.getDefault().sleep(getCheckNewUserSleep());
            output = executeShellCommand(String.format(switchCommand));
            success = userId == getCurrentUser();
        }

        CLog.d("switchUser took %d ms", getHostCurrentTime() - initialTime);
        if (success) {
            prePostBootSetup();
            return true;
        } else {
            CLog.e("User did not switch in the given %d timeout: %s", timeout, output);
            return false;
        }
    }

    /**
     * Exposed for testing.
     */
    protected long getCheckNewUserSleep() {
        return CHECK_NEW_USER;
    }

    /**
     * Exposed for testing
     */
    protected long getHostCurrentTime() {
        return System.currentTimeMillis();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasFeature(String feature) throws DeviceNotAvailableException {
        // Add support for directly checking a feature and match the pm output.
        if (!feature.startsWith("feature:")) {
            feature = "feature:" + feature;
        }
        String commandOutput = executeShellCommand("pm list features");
        for (String line: commandOutput.split("\\s+")) {
            // Each line in the output of the command has the format "feature:{FEATURE_VALUE}".
            if (feature.equals(line)) {
                return true;
            }
        }
        CLog.w("Feature: %s is not available on %s", feature, getSerialNumber());
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getSetting(String namespace, String key) throws DeviceNotAvailableException {
        return getSettingInternal("", namespace.trim(), key.trim());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getSetting(int userId, String namespace, String key)
            throws DeviceNotAvailableException {
        return getSettingInternal(String.format("--user %d", userId), namespace.trim(), key.trim());
    }

    /**
     * Internal Helper to get setting with or without a userId provided.
     */
    private String getSettingInternal(String userFlag, String namespace, String key)
            throws DeviceNotAvailableException {
        namespace = namespace.toLowerCase();
        if (Arrays.asList(SETTINGS_NAMESPACE).contains(namespace)) {
            String cmd = String.format("settings %s get %s %s", userFlag, namespace, key);
            String output = executeShellCommand(cmd);
            if ("null".equals(output)) {
                CLog.w("settings returned null for command: %s. "
                        + "please check if the namespace:key exists", cmd);
                return null;
            }
            return output.trim();
        }
        CLog.e("Namespace requested: '%s' is not part of {system, secure, global}", namespace);
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Map<String, String> getAllSettings(String namespace) throws DeviceNotAvailableException {
        return getAllSettingsInternal(namespace.trim());
    }

    /** Internal helper to get all settings */
    private Map<String, String> getAllSettingsInternal(String namespace)
            throws DeviceNotAvailableException {
        namespace = namespace.toLowerCase();
        if (Arrays.asList(SETTINGS_NAMESPACE).contains(namespace)) {
            Map<String, String> map = new HashMap<>();
            String cmd = String.format("settings list %s", namespace);
            String output = executeShellCommand(cmd);
            for (String line : output.split("\\n")) {
                // Setting's value could be empty
                String[] pair = line.trim().split("=", -1);
                if (pair.length > 1) {
                    map.putIfAbsent(pair[0], pair[1]);
                } else {
                    CLog.e("Unable to get setting from string: %s", line);
                }
            }
            return map;
        }
        CLog.e("Namespace requested: '%s' is not part of {system, secure, global}", namespace);
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setSetting(String namespace, String key, String value)
            throws DeviceNotAvailableException {
        setSettingInternal("", namespace.trim(), key.trim(), value.trim());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setSetting(int userId, String namespace, String key, String value)
            throws DeviceNotAvailableException {
        setSettingInternal(String.format("--user %d", userId), namespace.trim(), key.trim(),
                value.trim());
    }

    /**
     * Internal helper to set a setting with or without a userId provided.
     */
    private void setSettingInternal(String userFlag, String namespace, String key, String value)
            throws DeviceNotAvailableException {
        checkApiLevelAgainst("Changing settings", 22);
        if (Arrays.asList(SETTINGS_NAMESPACE).contains(namespace.toLowerCase())) {
            executeShellCommand(String.format("settings %s put %s %s %s",
                    userFlag, namespace, key, value));
        } else {
            throw new IllegalArgumentException("Namespace must be one of system, secure, global."
                    + " You provided: " + namespace);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getAndroidId(int userId) throws DeviceNotAvailableException {
        if (isAdbRoot()) {
            String cmd = String.format(
                    "sqlite3 /data/user/%d/com.google.android.gsf/databases/gservices.db "
                    + "'select value from main where name = \"android_id\"'", userId);
            String output = executeShellCommand(cmd).trim();
            if (!output.contains("unable to open database")) {
                return output;
            }
            CLog.w("Couldn't find android-id, output: %s", output);
        } else {
            CLog.w("adb root is required.");
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<Integer, String> getAndroidIds() throws DeviceNotAvailableException {
        ArrayList<Integer> userIds = listUsers();
        if (userIds == null) {
            return null;
        }
        Map<Integer, String> androidIds = new HashMap<Integer, String>();
        for (Integer id : userIds) {
            String androidId = getAndroidId(id);
            androidIds.put(id, androidId);
        }
        return androidIds;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    IWifiHelper createWifiHelper() throws DeviceNotAvailableException {
        mWasWifiHelperInstalled = true;
        return new WifiHelper(this, mOptions.getWifiUtilAPKPath());
    }

    /**
     * Alternative to {@link #createWifiHelper()} where we can choose whether to do the wifi helper
     * setup or not.
     */
    @VisibleForTesting
    IWifiHelper createWifiHelper(boolean doSetup) throws DeviceNotAvailableException {
        if (doSetup) {
            mWasWifiHelperInstalled = true;
        }
        return new WifiHelper(this, mOptions.getWifiUtilAPKPath(), doSetup);
    }

    /** {@inheritDoc} */
    @Override
    public void postInvocationTearDown(Throwable exception) {
        super.postInvocationTearDown(exception);
        // If wifi was installed and it's a real device, attempt to clean it.
        if (mWasWifiHelperInstalled) {
            mWasWifiHelperInstalled = false;
            if (getIDevice() instanceof StubDevice) {
                return;
            }
            if (!TestDeviceState.ONLINE.equals(getDeviceState())) {
                return;
            }
            if (exception instanceof DeviceNotAvailableException) {
                CLog.e("Skip WifiHelper teardown due to DeviceNotAvailableException.");
                return;
            }
            try {
                // Uninstall the wifi utility if it was installed.
                IWifiHelper wifi = createWifiHelper(false);
                wifi.cleanUp();
            } catch (DeviceNotAvailableException e) {
                CLog.e("Device became unavailable while uninstalling wifi util.");
                CLog.e(e);
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean setDeviceOwner(String componentName, int userId)
            throws DeviceNotAvailableException {
        final String command = "dpm set-device-owner --user " + userId + " '" + componentName + "'";
        final String commandOutput = executeShellCommand(command);
        return commandOutput.startsWith("Success:");
    }

    /** {@inheritDoc} */
    @Override
    public boolean removeAdmin(String componentName, int userId)
            throws DeviceNotAvailableException {
        final String command =
                "dpm remove-active-admin --user " + userId + " '" + componentName + "'";
        final String commandOutput = executeShellCommand(command);
        return commandOutput.startsWith("Success:");
    }

    /** {@inheritDoc} */
    @Override
    public void removeOwners() throws DeviceNotAvailableException {
        String command = "dumpsys device_policy";
        String commandOutput = executeShellCommand(command);
        String[] lines = commandOutput.split("\\r?\\n");
        for (int i = 0; i < lines.length; ++i) {
            String line = lines[i].trim();
            if (line.contains("Profile Owner")) {
                // Line is "Profile owner (User <id>):
                String[] tokens = line.split("\\(|\\)| ");
                int userId = Integer.parseInt(tokens[4]);

                i = moveToNextIndexMatchingRegex(".*admin=.*", lines, i);
                line = lines[i].trim();
                // Line is admin=ComponentInfo{<component>}
                tokens = line.split("\\{|\\}");
                String componentName = tokens[1];
                CLog.d("Cleaning up profile owner " + userId + " " + componentName);
                removeAdmin(componentName, userId);
            } else if (line.contains("Device Owner:")) {
                i = moveToNextIndexMatchingRegex(".*admin=.*", lines, i);
                line = lines[i].trim();
                // Line is admin=ComponentInfo{<component>}
                String[] tokens = line.split("\\{|\\}");
                String componentName = tokens[1];

                // Skip to user id line.
                i = moveToNextIndexMatchingRegex(".*User ID:.*", lines, i);
                line = lines[i].trim();
                // Line is User ID: <N>
                tokens = line.split(":");
                int userId = Integer.parseInt(tokens[1].trim());
                CLog.d("Cleaning up device owner " + userId + " " + componentName);
                removeAdmin(componentName, userId);
            }
        }
    }

    /**
     * Search forward from the current index to find a string matching the given regex.
     *
     * @param regex The regex to match each line against.
     * @param lines An array of strings to be searched.
     * @param currentIndex the index to start searching from.
     * @return The index of a string beginning with the regex.
     * @throws IllegalStateException if the line cannot be found.
     */
    private int moveToNextIndexMatchingRegex(String regex, String[] lines, int currentIndex) {
        while (currentIndex < lines.length && !lines[currentIndex].matches(regex)) {
            currentIndex++;
        }

        if (currentIndex >= lines.length) {
            throw new IllegalStateException(
                    "The output of 'dumpsys device_policy' was not as expected. Owners have not "
                            + "been removed. This will leave the device in an unstable state and "
                            + "will lead to further test failures.");
        }

        return currentIndex;
    }

    /**
     * Helper for Api level checking of features in the new release before we incremented the api
     * number.
     */
    private void checkApiLevelAgainstNextRelease(String feature, int strictMinLevel)
            throws DeviceNotAvailableException {
        if (checkApiLevelAgainstNextRelease(strictMinLevel)) {
            return;
        }
        throw new IllegalArgumentException(
                String.format(
                        "%s not supported on %s. Must be API %d.",
                        feature, getSerialNumber(), strictMinLevel));
    }

    @Override
    public File dumpHeap(String process, String devicePath) throws DeviceNotAvailableException {
        if (Strings.isNullOrEmpty(devicePath) || Strings.isNullOrEmpty(process)) {
            throw new IllegalArgumentException("devicePath or process cannot be null or empty.");
        }
        String pid = getProcessPid(process);
        if (pid == null) {
            return null;
        }
        File dump = dumpAndPullHeap(pid, devicePath);
        // Clean the device.
        deleteFile(devicePath);
        return dump;
    }

    /** Dump the heap file and pull it from the device. */
    private File dumpAndPullHeap(String pid, String devicePath) throws DeviceNotAvailableException {
        executeShellCommand(String.format(DUMPHEAP_CMD, pid, devicePath));
        // Allow a little bit of time for the file to populate on device side.
        int attempt = 0;
        // TODO: add an API to check device file size
        while (!doesFileExist(devicePath) && attempt < 3) {
            getRunUtil().sleep(DUMPHEAP_TIME);
            attempt++;
        }
        File dumpFile = pullFile(devicePath);
        return dumpFile;
    }

    /** {@inheritDoc} */
    @Override
    public Set<Long> listDisplayIds() throws DeviceNotAvailableException {
        Set<Long> displays = new HashSet<>();
        // Zero is the default display
        displays.add(0L);
        CommandResult res = executeShellV2Command("dumpsys SurfaceFlinger | grep 'color modes:'");
        if (!CommandStatus.SUCCESS.equals(res.getStatus())) {
            CLog.e("Something went wrong while listing displays: %s", res.getStderr());
            return displays;
        }
        String output = res.getStdout();
        Pattern p = Pattern.compile(DISPLAY_ID_PATTERN);
        for (String line : output.split("\n")) {
            Matcher m = p.matcher(line);
            if (m.matches()) {
                displays.add(Long.parseLong(m.group("id")));
            }
        }
        return displays;
    }
}
