Adding support for native profiling of AppRTCMobile.
See perf_setup.sh for instructions. NOTRY=TRUE BUG=NONE Review-Url: https://codereview.webrtc.org/2705063002 Cr-Commit-Position: refs/heads/master@{#16826}
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -46,6 +46,8 @@
|
||||
/testing
|
||||
/third_party
|
||||
/tools
|
||||
/tools-webrtc/android/profiling/flamegraph
|
||||
/tools-webrtc/android/profiling/simpleperf
|
||||
/tools-webrtc/video_quality_toolchain/linux/ffmpeg
|
||||
/tools-webrtc/video_quality_toolchain/linux/zxing
|
||||
/tools-webrtc/video_quality_toolchain/mac/ffmpeg
|
||||
|
470
tools-webrtc/android/profiling/perf_setup.sh
Executable file
470
tools-webrtc/android/profiling/perf_setup.sh
Executable file
@ -0,0 +1,470 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# It is assumed that a release build of AppRTCMobile exists and has been
|
||||
# installed on a rooted and attached Android device.
|
||||
#
|
||||
# Source this script once from the WebRTC src/ directory and resolve any
|
||||
# reported issues. Add relative path to build directory as parameter.
|
||||
# Required tools will be downloaded if they don't already exist.
|
||||
#
|
||||
# Once all tests are passed, a list of available functions will be given.
|
||||
# Use these functions to do the actual profiling and visualization of the
|
||||
# results.
|
||||
#
|
||||
# Example usage:
|
||||
#
|
||||
# > . tools-webrtc/android/profiling/perf_setup.sh out/Release
|
||||
# > perf_record 120
|
||||
# > flame_graph
|
||||
# > plot_flame_graph
|
||||
# > perf_cleanup
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
source "${SCRIPT_DIR}/utilities.sh"
|
||||
|
||||
# Root directory for local symbol cache.
|
||||
SYMBOL_DIR="${TMPDIR:-/tmp}/android_symbols"
|
||||
# Used as a temporary folder on the Android device for data storage.
|
||||
DEV_TMP_DIR="/data/local/tmp"
|
||||
# Relative path to native shared library containing symbols.
|
||||
NATIVE_LIB_PATH="/lib.unstripped/libjingle_peerconnection_so.so"
|
||||
# Name of application package for the AppRTCMobile demo.
|
||||
APP_NAME="org.appspot.apprtc"
|
||||
|
||||
# Make sure we're being sourced.
|
||||
if [[ -n "${BASH_VERSION}" && "${BASH_SOURCE:-$0}" == "$0" ]]; then
|
||||
error "perf_setup must be sourced"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function usage() {
|
||||
printf "usage: . perf_setup.sh <build_dir>\n"
|
||||
}
|
||||
|
||||
# Ensure that user includes name of build directory (e.g. out/Release) as
|
||||
# input parameter. Store path in BUILD_DIR.
|
||||
if [[ "$#" -eq 1 ]]; then
|
||||
if is_not_dir "$1"; then
|
||||
error "$1 is invalid"
|
||||
return 1
|
||||
fi
|
||||
BUILD_DIR="$1"
|
||||
else
|
||||
unset BUILD_DIR
|
||||
error "Missing required parameter".
|
||||
usage
|
||||
fi
|
||||
|
||||
# Helper method to simpify usage of the simpleperf binary on the device.
|
||||
function simpleperf_android() {
|
||||
local simpleperf="${DEV_TMP_DIR}/simpleperf"
|
||||
if [ ! -z "$1" ]; then
|
||||
adb shell "${simpleperf}" "$@"
|
||||
else
|
||||
adb shell $simpleperf --help
|
||||
fi
|
||||
}
|
||||
|
||||
# Full (relative) path to the libjingle_peerconnection_so.so file.
|
||||
function native_shared_lib_path() {
|
||||
echo "${BUILD_DIR}${NATIVE_LIB_PATH}"
|
||||
}
|
||||
|
||||
# Target CPU architecture for the native shared library.
|
||||
# Example: AArch64.
|
||||
function native_shared_lib_arch() {
|
||||
readelf -h $(native_shared_lib_path) | grep Machine | awk '{print $2}'
|
||||
}
|
||||
|
||||
# Returns true if the device architecture and the build target are the same.
|
||||
function arch_is_ok() {
|
||||
if [[ "$(dev_arch)" == "aarch64" ]] \
|
||||
&& [[ "$(native_shared_lib_arch)" == "AArch64" ]]; then
|
||||
return 0
|
||||
elif [[ "$(dev_arch)" == "aarch32" ]] \
|
||||
&& [[ "$(native_shared_lib_arch)" == "AArch32" ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Copies the native shared library from the local host to the symbol cache
|
||||
# which is used by simpleperf as base when searching for symbols.
|
||||
function copy_native_shared_library_to_symbol_cache() {
|
||||
local arm_lib="arm"
|
||||
if [ "$(native_shared_lib_arch)" == "AArch64" ]; then
|
||||
arm_lib="arm64"
|
||||
fi
|
||||
for num in 1 2; do
|
||||
local dir="${SYMBOL_DIR}/data/app/${APP_NAME}-${num}/lib/${arm_lib}"
|
||||
mkdir -p "${dir}"
|
||||
cp -u $(native_shared_lib_path) "${dir}"
|
||||
done
|
||||
}
|
||||
|
||||
# Copy kernel symbols from device to symbol cache in tmp.
|
||||
function copy_kernel_symbols_from_device_to_symbol_cache() {
|
||||
local symbol_cache="${SYMBOL_DIR}/kallsyms"
|
||||
adb pull /proc/kallsyms "${symbol_cache}"
|
||||
} 1> /dev/null
|
||||
|
||||
# Download the correct version of 'simpleperf' to $DEV_TMP_DIR
|
||||
# on the device and enable profiling.
|
||||
function copy_simpleperf_to_device() {
|
||||
local perf_binary
|
||||
[[ $(dev_arch) == "aarch64" ]] \
|
||||
&& perf_binary="/arm64/simpleperf" \
|
||||
|| perf_binary="/arm/simpleperf"
|
||||
local simpleperf="${DEV_TMP_DIR}/simpleperf"
|
||||
# Avoid copying to device if simpleperf already exists.
|
||||
if [[ ! $(dev_ls "${simpleperf}") ]]; then
|
||||
adb push "${SIMPLE_PERF_DIR}${perf_binary}" "${DEV_TMP_DIR}"
|
||||
adb shell chmod a+x $simpleperf
|
||||
fi
|
||||
# Enable profiling on the device.
|
||||
enable_profiling
|
||||
# Allows usage of running report commands on the device.
|
||||
enable_report_symbols
|
||||
}
|
||||
|
||||
# Copy the recorded 'perf.data' file from the device to the current directory.
|
||||
# TODO(henrika): add support for specifying the destination.
|
||||
function pull_perf_data_from_device() {
|
||||
adb pull "${DEV_TMP_DIR}/perf.data" .
|
||||
} 1> /dev/null
|
||||
|
||||
|
||||
# Wraps calls to simpleperf report. Used by e.g. perf_report_threads.
|
||||
# A valid profile input file must exist in the current folder.
|
||||
# TODO(henrika): possibly add support to add path to alternative input file.
|
||||
function perf_report() {
|
||||
local perf_data="perf.data"
|
||||
is_file "${perf_data}" \
|
||||
&& simpleperf report \
|
||||
-n \
|
||||
-i "${perf_data}" \
|
||||
"$@" \
|
||||
|| error "$(pwd)/${perf_data} is invalid"
|
||||
}
|
||||
|
||||
# Removes the folder specified as input parameter. Mainly intended for removal
|
||||
# of simpleperf and Flame Graph tools.
|
||||
function remove_tool() {
|
||||
local tool_dir="$1"
|
||||
if is_dir "${tool_dir}"; then
|
||||
echo "Removing ${tool_dir}..."
|
||||
rm -rf "${tool_dir}"
|
||||
path_remove "${tool_dir}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Utility method which deletes the downloaded simpleperf tool from the repo.
|
||||
# It also removes the simpleperf root folder from PATH.
|
||||
function rm_simpleperf() {
|
||||
remove_tool "${SCRIPT_DIR}/simpleperf"
|
||||
}
|
||||
|
||||
# Utility method which deletes the downloaded Flame Graph tool from the repo.
|
||||
# It also removes the Flame Graph root folder from PATH.
|
||||
function rm_flame_graph() {
|
||||
remove_tool "${SCRIPT_DIR}/flamegraph"
|
||||
}
|
||||
|
||||
# Lists the main available functions after sourcing this script.
|
||||
function print_function_help() {
|
||||
printf "\nAvailable functions in this shell:\n"
|
||||
printf " perf_record [duration, default=60sec]\n"
|
||||
printf " perf_report_threads\n"
|
||||
printf " perf_report_bins\n"
|
||||
printf " perf_report_symbols\n"
|
||||
printf " perf_report_graph\n"
|
||||
printf " perf_report_graph_callee\n"
|
||||
printf " perf_update\n"
|
||||
printf " perf_clean\n"
|
||||
printf " flame_graph\n"
|
||||
printf " plot_flame_graph\n"
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
unset -f main
|
||||
unset BUILD_DIR
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Main methods to be used after sourcing the main script.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Call this method after the application as been rebuilt and installed on the
|
||||
# device to ensure that symbols are up-to-date.
|
||||
function perf_update() {
|
||||
copy_native_shared_library_to_symbol_cache
|
||||
copy_kernal_symbols_from_device_to_symbol_cache
|
||||
}
|
||||
|
||||
# Record stack frame based call graphs while using the application.
|
||||
# We use default events (cpu-cycles), and write records to 'perf.data' in the
|
||||
# tmp folder on the device. Default duration is 60 seconds but it can be changed
|
||||
# by adding one parameter. As soon as the recording is done, 'perf.data' is
|
||||
# copied to the directory from which this method is called and a summary of
|
||||
# the load distribution per thread is printed.
|
||||
function perf_record() {
|
||||
if app_is_running "${APP_NAME}"; then
|
||||
# Ensure that the latest native shared library exists in the local cache.
|
||||
copy_native_shared_library_to_symbol_cache
|
||||
local duration=60
|
||||
if [ "$#" -eq 1 ]; then
|
||||
duration="$1"
|
||||
fi
|
||||
local pid=$(find_app_pid "${APP_NAME}")
|
||||
echo "Profiling PID $pid for $duration seconds (media must be is active)..."
|
||||
local output_file="${DEV_TMP_DIR}/perf.data"
|
||||
simpleperf_android record \
|
||||
--call-graph fp \
|
||||
-p "${pid}" \
|
||||
-o $output_file \
|
||||
-f 1000 \
|
||||
--duration "${duration}" \
|
||||
--log error
|
||||
app_stop "${APP_NAME}"
|
||||
# Copy profile results from device to current directory.
|
||||
pull_perf_data_from_device
|
||||
# Print out a summary report (load per thread).
|
||||
perf_report_threads | tail -n +6
|
||||
else
|
||||
# AppRTCMobile was not enabled. Start it up automatically and ask the user
|
||||
# to start media and then call this method again.
|
||||
warning "AppRTCMobile must be active"
|
||||
app_start "${APP_NAME}"
|
||||
echo "Start media and then call perf_record again..."
|
||||
fi 2> /dev/null
|
||||
}
|
||||
|
||||
# Analyze the profile report and show samples per threads.
|
||||
function perf_report_threads() {
|
||||
perf_report --sort comm
|
||||
} 2> /dev/null
|
||||
|
||||
# Analyze the profile report and show samples per binary.
|
||||
function perf_report_bins() {
|
||||
perf_report --sort dso
|
||||
} 2> /dev/null
|
||||
|
||||
# Analyze the profile report and show samples per symbol.
|
||||
function perf_report_symbols() {
|
||||
perf_report --sort symbol --symfs "${SYMBOL_DIR}"
|
||||
}
|
||||
|
||||
# Print call graph showing how functions call others.
|
||||
function perf_report_graph() {
|
||||
perf_report -g caller --symfs "${SYMBOL_DIR}"
|
||||
}
|
||||
|
||||
# Print call graph showing how functions are called from others.
|
||||
function perf_report_graph_callee() {
|
||||
perf_report -g callee --symfs "${SYMBOL_DIR}"
|
||||
}
|
||||
|
||||
# Plots the default Flame Graph file if no parameter is provided.
|
||||
# If a parameter is given, it will be used as file name instead of the default.
|
||||
function plot_flame_graph() {
|
||||
local file_name="flame_graph.svg"
|
||||
if [[ "$#" -eq 1 ]]; then
|
||||
file_name="$1"
|
||||
fi
|
||||
# Open up the SVG file in Chrome. Try unstable first and revert to stable
|
||||
# if unstable fails.
|
||||
google-chrome-unstable "${file_name}" \
|
||||
|| google-chrome-stable "${file_name}" \
|
||||
|| error "failed to find any Chrome instance"
|
||||
} 2> /dev/null
|
||||
|
||||
# Generate Flame Graph in interactive SVG format.
|
||||
# First input parameter corresponds to output file name and second input
|
||||
# parameter is the heading of the plot.
|
||||
# Defaults will be utilized if parameters are not provided.
|
||||
# See https://github.com/brendangregg/FlameGraph for details on Flame Graph.
|
||||
function flame_graph() {
|
||||
local perf_data="perf.data"
|
||||
if is_not_file $perf_data; then
|
||||
error "$(pwd)/${perf_data} is invalid"
|
||||
return 1
|
||||
fi
|
||||
local file_name="flame_graph.svg"
|
||||
local title="WebRTC Flame Graph"
|
||||
if [[ "$#" -eq 1 ]]; then
|
||||
file_name="$1"
|
||||
fi
|
||||
if [[ "$#" -eq 2 ]]; then
|
||||
file_name="$1"
|
||||
title="$2"
|
||||
fi
|
||||
report_sample.py \
|
||||
--symfs "${SYMBOL_DIR}" \
|
||||
--kallsyms "${SYMBOL_DIR}/kallsyms" \
|
||||
perf.data >out.perf
|
||||
stackcollapse-perf.pl out.perf >out.folded
|
||||
flamegraph.pl --title="${title}" out.folded >"${file_name}"
|
||||
rm out.perf
|
||||
rm out.folded
|
||||
}
|
||||
|
||||
# Remove all downloaded third-party tools.
|
||||
function perf_cleanup () {
|
||||
rm_simpleperf
|
||||
rm_flame_graph
|
||||
}
|
||||
|
||||
main() {
|
||||
printf "%s\n" "Preparing profiling of AppRTCMobile on Android:"
|
||||
# Verify that this script is called from the root folder of WebRTC,
|
||||
# i.e., the src folder one step below where the .gclient file exists.
|
||||
local -r project_root_dir=$(pwd)
|
||||
local dir=${project_root_dir##*/}
|
||||
if [[ "${dir}" != "src" ]]; then
|
||||
error "script must be called from the WebRTC project root (src) folder"
|
||||
return 1
|
||||
fi
|
||||
ok "project root: ${project_root_dir}"
|
||||
|
||||
# Verify that user has sourced envsetup.sh.
|
||||
# TODO(henrika): might be possible to remove this check.
|
||||
if [[ -z "$ENVSETUP_GYP_CHROME_SRC" ]]; then
|
||||
error "must source envsetup script first"
|
||||
return 1
|
||||
fi
|
||||
ok "envsetup script has been sourced"
|
||||
|
||||
# Given that envsetup is sourced, the adb tool should be accessible but
|
||||
# do one extra check just in case.
|
||||
local adb_full_path=$(which adb);
|
||||
if [[ ! -x "${adb_full_path}" ]]; then
|
||||
error "unable to find the Android Debug Bridge (adb) tool"
|
||||
return 1
|
||||
fi
|
||||
ok "adb tool is working"
|
||||
|
||||
# Exactly one Android device must be connected.
|
||||
if [[ ! one_device_connected ]]; then
|
||||
error "one device must be connected"
|
||||
return 1
|
||||
fi
|
||||
ok "one device is connected via USB"
|
||||
|
||||
# Ensure that the device is rooted.
|
||||
if image_is_not_root; then
|
||||
error "device is not rooted"
|
||||
return 1
|
||||
fi
|
||||
ok "device is rooted"
|
||||
|
||||
# Restart adb with root permissions if needed.
|
||||
if adb_has_no_root_permissions; then
|
||||
adb root
|
||||
fi
|
||||
ok "adbd is running as root"
|
||||
|
||||
# Create an empty symbol cache in the tmp folder.
|
||||
# TODO(henrika): it might not be required to start from a clean cache.
|
||||
is_dir "${SYMBOL_DIR}" && rm -rf "${SYMBOL_DIR}"
|
||||
mkdir "${SYMBOL_DIR}" \
|
||||
&& ok "empty symbol cache created at ${SYMBOL_DIR}" \
|
||||
|| error "failed to create symbol cache"
|
||||
|
||||
# Ensure that path to the native library with symbols is valid.
|
||||
local native_lib=$(native_shared_lib_path)
|
||||
if is_not_file ${native_lib}; then
|
||||
error "${native_lib} is not a valid file"
|
||||
return 1
|
||||
fi
|
||||
ok "native library: "${native_lib}""
|
||||
|
||||
# Verify that the architechture of the device matches the architecture
|
||||
# of the native library.
|
||||
if ! arch_is_ok; then
|
||||
error "device is $(dev_arch) and lib is $(native_shared_lib_arch)"
|
||||
return 1
|
||||
fi
|
||||
ok "device is $(dev_arch) and lib is $(native_shared_lib_arch)"
|
||||
|
||||
# Copy native shared library to symbol cache after creating an
|
||||
# application specific tree structure under ${SYMBOL_DIR}/data.
|
||||
copy_native_shared_library_to_symbol_cache
|
||||
ok "native library copied to ${SYMBOL_DIR}/data/app/${APP_NAME}"
|
||||
|
||||
# Verify that the application is installed on the device.
|
||||
if ! app_is_installed "${APP_NAME}"; then
|
||||
error "${APP_NAME} is not installed on the device"
|
||||
return 1
|
||||
fi
|
||||
ok "${APP_NAME} is installed on the device"
|
||||
|
||||
# Download simpleperf to <src>/tools-webrtc/android/profiling/simpleperf/.
|
||||
# Cloning will only take place if the target does not already exist.
|
||||
# The PATH variable will also be updated.
|
||||
# TODO(henrika): would it be better to use a target outside the WebRTC repo?
|
||||
local simpleperf_dir="${SCRIPT_DIR}/simpleperf"
|
||||
if is_not_dir "${simpleperf_dir}"; then
|
||||
echo "Dowloading simpleperf..."
|
||||
git clone https://android.googlesource.com/platform/prebuilts/simpleperf \
|
||||
"${simpleperf_dir}"
|
||||
chmod u+x "${simpleperf_dir}/report_sample.py"
|
||||
fi
|
||||
path_add "${simpleperf_dir}"
|
||||
ok "${simpleperf_dir}" is added to PATH
|
||||
|
||||
# Update the PATH variable with the path to the Linux version of simpleperf.
|
||||
local simpleperf_linux_dir="${SCRIPT_DIR}/simpleperf/bin/linux/x86_64/"
|
||||
if is_not_dir "${simpleperf_linux_dir}"; then
|
||||
error "${simpleperf_linux_dir} is invalid"
|
||||
return 1
|
||||
fi
|
||||
path_add "${simpleperf_linux_dir}"
|
||||
ok "${simpleperf_linux_dir}" is added to PATH
|
||||
|
||||
# Copy correct version (arm or arm64) of simpleperf to the device
|
||||
# and enable profiling at the same time.
|
||||
if ! copy_simpleperf_to_device; then
|
||||
error "failed to install simpleperf on the device"
|
||||
return 1
|
||||
fi
|
||||
ok "simpleperf is installed on the device"
|
||||
|
||||
# Refresh the symbol cache and read kernal symbols from device if not
|
||||
# already done.
|
||||
perf_update
|
||||
ok "symbol cache is updated"
|
||||
|
||||
# Download Flame Graph to <src>/tools-webrtc/android/profiling/flamegraph/.
|
||||
# Cloning will only take place if the target does not already exist.
|
||||
# The PATH variable will also be updated.
|
||||
# TODO(henrika): would it be better to use a target outside the WebRTC repo?
|
||||
local flamegraph_dir="${SCRIPT_DIR}/flamegraph"
|
||||
if is_not_dir "${flamegraph_dir}"; then
|
||||
echo "Dowloading Flame Graph visualization tool..."
|
||||
git clone https://github.com/brendangregg/FlameGraph.git "${flamegraph_dir}"
|
||||
fi
|
||||
path_add "${flamegraph_dir}"
|
||||
ok "${flamegraph_dir}" is added to PATH
|
||||
|
||||
print_function_help
|
||||
|
||||
cleanup
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Only call main() if proper input parameter has been provided.
|
||||
if is_set $BUILD_DIR; then
|
||||
main "$@"
|
||||
fi
|
154
tools-webrtc/android/profiling/utilities.sh
Executable file
154
tools-webrtc/android/profiling/utilities.sh
Executable file
@ -0,0 +1,154 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
# Utility functions to be used by perf_setup.sh.
|
||||
# Contains helper methods and functions that wraps usage of adb.
|
||||
|
||||
function error() {
|
||||
echo "[ERROR] "$@"" >&2
|
||||
}
|
||||
|
||||
function warning() {
|
||||
echo "[WARNING] "$@"" >&1
|
||||
}
|
||||
|
||||
function ok() {
|
||||
echo "[OK] "$@"" >&1
|
||||
}
|
||||
|
||||
function abs_path {
|
||||
(cd $1; pwd)
|
||||
}
|
||||
|
||||
function is_set() {
|
||||
local var="$1"
|
||||
[[ -n "${var}" ]]
|
||||
}
|
||||
|
||||
function is_file() {
|
||||
local file="$1"
|
||||
[[ -f "${file}" ]]
|
||||
}
|
||||
|
||||
function is_not_file() {
|
||||
local file="$1"
|
||||
[[ ! -f "${file}" ]]
|
||||
}
|
||||
|
||||
function is_dir() {
|
||||
local dir="$1"
|
||||
[[ -d "${dir}" ]]
|
||||
}
|
||||
|
||||
function is_not_dir() {
|
||||
local dir="$1"
|
||||
[[ ! -d "${dir}" ]]
|
||||
}
|
||||
|
||||
# Adds (prepends) the PATH environment variable while avoid duplicates.
|
||||
function path_add() {
|
||||
case ":${PATH:=$1}:" in
|
||||
*:$1:*) ;;
|
||||
*) PATH="$1:$PATH" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Removes a path from the PATH environment variable using search-and-replace
|
||||
# parameter expansion.
|
||||
function path_remove {
|
||||
local path="$1"
|
||||
# Substitute first occurrence of ":path" in PATH with an empty string.
|
||||
# Deletes instances in the middle or at the end.
|
||||
PATH=${PATH/":$path"/}
|
||||
# Substitute first occurrence of "path:" in PATH with an empty string.
|
||||
# Delete instances at the beginning.
|
||||
PATH=${PATH/"$path:"/}
|
||||
}
|
||||
|
||||
# Returns the process ID (PID) of the process that corresponds to the
|
||||
# application name given as input parameter.
|
||||
function find_app_pid() {
|
||||
local app_name="$1"
|
||||
adb shell ps | grep "${app_name}" | awk '{print $2}'
|
||||
}
|
||||
|
||||
function app_is_installed() {
|
||||
local app_name="$1"
|
||||
local installed_app_name=$(adb shell pm list packages \
|
||||
| grep "${app_name}" | awk -F':' '{print $2}')
|
||||
is_set "${installed_app_name}" \
|
||||
&& [[ "${installed_app_name}" = "${app_name}" ]]
|
||||
}
|
||||
|
||||
function app_is_running() {
|
||||
local app_name="$1"
|
||||
local app_pid=$(find_app_pid "${app_name}")
|
||||
is_set "${app_pid}"
|
||||
}
|
||||
|
||||
function app_start() {
|
||||
local app_name="$1"
|
||||
adb shell am start \
|
||||
-n "${app_name}/.ConnectActivity" \
|
||||
-a android.intent.action.MAIN
|
||||
}
|
||||
|
||||
function app_stop() {
|
||||
local app_name="$1"
|
||||
adb shell am force-stop "${app_name}"
|
||||
}
|
||||
|
||||
function app_uninstall() {
|
||||
local app_name="$1"
|
||||
adb uninstall "${app_name}"
|
||||
}
|
||||
|
||||
function dev_arch() {
|
||||
adb shell uname -m
|
||||
}
|
||||
|
||||
function dev_ls() {
|
||||
local dir="$1"
|
||||
adb shell ls "${dir}"
|
||||
}
|
||||
|
||||
# Returns true if exactly on device is connected.
|
||||
function one_device_connected() {
|
||||
[[ $(adb devices | wc -l) = 3 ]]
|
||||
}
|
||||
|
||||
# Returns true if device is rooted.
|
||||
function image_is_root() {
|
||||
[[ $(adb shell getprop ro.build.type) = "userdebug" ]]
|
||||
}
|
||||
|
||||
# Returns true if device is not rooted.
|
||||
function image_is_not_root() {
|
||||
[[ $(adb shell getprop ro.build.type) = "user" ]]
|
||||
}
|
||||
|
||||
# Returns true if adb is not already running as root.
|
||||
# Should only be called on rooted devices.
|
||||
function adb_has_no_root_permissions() {
|
||||
[[ $(adb shell getprop service.adb.root) = 0 ]]
|
||||
}
|
||||
|
||||
# Android devices may disable profiling by default. We must enable it.
|
||||
function enable_profiling() {
|
||||
adb shell setprop security.perf_harden 0
|
||||
}
|
||||
|
||||
# To make the report of symbols on device successful, we need to execute
|
||||
# `echo 0 >/proc/sys/kernel/kptr_restrict`.
|
||||
# Only needed if we run report commands on the same machine as we run
|
||||
# record commands.
|
||||
function enable_report_symbols() {
|
||||
adb shell "echo 0 > /proc/sys/kernel/kptr_restrict"
|
||||
}
|
Reference in New Issue
Block a user