|
#!/bin/sh -eu |
|
|
|
Exit () { |
|
if [ $# -ge 1 ] && [ -n "$1" ] && [ "$1" -eq "$1" ] 2>/dev/null; then exitCode="$1"; shift; fi |
|
if [ $# -ge 1 ] ; then printf '%s\n' "$@" 1>&2; fi |
|
if (return 0 2>/dev/null); then # file was sourced rather than run |
|
kill -INT 0 # Ensures exiting of the script, even from nested subshells |
|
else |
|
exit "${exitCode:-1}"; |
|
fi |
|
} |
|
|
|
unset adbSerial |
|
unset androidVersion |
|
unset debug |
|
while getopts ":ds:v:" OPT; do |
|
case "$OPT" in |
|
d ) debug=true ;; |
|
s ) adbSerial="$OPTARG" ;; |
|
v ) androidVersion="$OPTARG" ;; |
|
\? ) Exit 2 "Argument '-$OPTARG' not recognized" ;; |
|
esac |
|
done |
|
shift $((OPTIND-1)) |
|
|
|
AssertExecutablesAreAvailable () { |
|
bins= |
|
for b in "$@"; do [ -n "$(command -v "$b" 2>/dev/null)" ] || bins="${bins-}$b "; done |
|
if [ ${#bins} -eq 0 ]; then return 0; fi |
|
printf '%s\n' "Cannot find the following executables:" "$bins" |
|
printf 'Install them now? ' |
|
read -r REPLY |
|
[ "$REPLY" != "${REPLY#[Yy]}" ] || Exit 1 "Exiting due to insufficient dependencies" |
|
sudo apt install "$bins" |
|
} |
|
AssertExecutablesAreAvailable 'adb' 'wget' 'tr' 'sed' 'cut' 'grep' 'head' 'tail' 'base64' 'printf' 'cat' 'sort' |
|
|
|
googleSource="https://android.googlesource.com" |
|
repoPath="platform/frameworks/base" |
|
|
|
if [ -n "${debug:+true}" ]; then |
|
echo "Stopping pre-processing due to debug=$debug"; |
|
return 0 2>/dev/null || exit 0; |
|
fi |
|
|
|
if [ $# -eq 0 ]; then |
|
Exit 2 "Please provide a service name argument" |
|
else |
|
serviceName="$1" |
|
fi |
|
|
|
# Use adbSerial variable for device, or grab the first available device's serial number |
|
adbSerial="${adbSerial:-$(adb devices | sed -e '1d' -e '2s/[[:space:]].*//' -e 'q')}" |
|
|
|
ADBShell () { adb ${adbSerial:+-s $adbSerial} shell -T -x "$1" | tr -d '\r'; } |
|
|
|
GetAndroidVersion () { |
|
ver="$(ADBShell 'getprop ro.build.version.release')"; |
|
echo "ro.build.version.release = $ver" 1>&2; |
|
echo "$ver"; |
|
} |
|
|
|
GetAndroidTagForVersion () { |
|
version="${1-}"; |
|
[ -n "$version" ] || Exit 1 "Android version was not provided in GetAndroidTagForVersion"; |
|
allTags="$(wget -qO - "$googleSource/$repoPath/+refs/tags/?format=text" | sed -e '/\^{}/d; s/.*\///' -e 'h' -e '/android-[0-9]/!d' | sort -V )" |
|
latestTags="$(echo "$allTags" | sed -e 'h' -e 'N' -e '/^\(android-[0-9.]\+[a-z]*_r\)\([.0-9a-z]*\)\n\1/D' -e 'x' )" |
|
localTag="$(echo "$latestTags" | sed -e "/android-$(echo "$version" | sed -e 'y/././')/p;d" | tail -n 1)" |
|
[ -n "$localTag" ] || Exit 1 "TAG not valid!" "List of valid tags:" "$allTags" |
|
echo "$localTag" |
|
} |
|
|
|
GetServicePackageName () { |
|
service="${1-}" |
|
[ -n "$service" ] || Exit 1 "Service name was not provided in GetServicePackageName"; |
|
packageName=$(ADBShell 'service list' | sed -e '1d' -e 's/[0-9]*[[:space:]]'"$service"': \[\(.*\)\]/\1/p' -e 'd'); |
|
[ -n "$packageName" ] || Exit 1 "Unable to find service package name for '$service'"; |
|
echo "$packageName"; |
|
} |
|
|
|
GetGoogleSourceFile () { |
|
[ -n "$1" ] || Exit 1 "Tag was not provided in GetGoogleSourceFile"; |
|
[ -n "$2" ] || Exit 1 "File was not provided in GetGoogleSourceFile"; |
|
wget -qO - "$googleSource/$repoPath/+/$1/$2?format=text" | base64 -d |
|
} |
|
|
|
GetAllServicesForTag () { |
|
version="${1-}"; localTag="${2-}"; |
|
[ -n "$version" ] || Exit 1 "Android version was not provided in GetAllServicesForTag"; |
|
baseVersion="${version%%.*}" |
|
[ "$baseVersion" -eq "$baseVersion" ] 2>/dev/null || Exit 1 "Could not parse number from Android version in GetAllServicesForTag"; |
|
[ -n "$localTag" ] || Exit 1 "Tag was not provided in GetAllServicesForTag"; |
|
if [ "$baseVersion" -gt 8 ]; then file='Android.bp'; else file='Android.mk'; fi |
|
GetGoogleSourceFile "$localTag" "$file" | tr -d ' \\\t,"' | sed -e '/\.aidl$/!d' -e '/^gen:/d' | sort -u |
|
} |
|
|
|
ParseServiceAIDL () { |
|
localTag="${1-}"; servicesList="${2-}"; packageName="${3-}" |
|
[ -n "$localTag" ] || Exit 1 "TAG was not provided in ParseServiceAIDL"; |
|
[ -n "$servicesList" ] || Exit 1 "Services list was not provided in ParseServiceAIDL"; |
|
[ -n "$packageName" ] || Exit 1 "Service package name was not provided in ParseServiceAIDL"; |
|
packageFilePath="$(echo "$packageName" | tr '.' '/')\.aidl" |
|
servicePath="$(echo "$servicesList" | grep -m 1 "$packageFilePath\$")" |
|
GetGoogleSourceFile "$localTag" "$servicePath" | sed -e '1,/interface/d' -e '/^$/d' -e 's/^[[:space:]]*//' -e '/^[^a-zA-Z]/d' -e '/^[^;]*$/{$!N}' -e '$d' -e 's/\(^\|\n\)[[:space:]]*\|\([[:space:]]\)\{2,\}/\2/g' | cat -n |
|
} |
|
|
|
|
|
echo "ADBSerial=$adbSerial" |
|
echo "AndroidOSVersion=${androidVersion:="$(GetAndroidVersion)"}" |
|
echo "VersionTag=${tag:="$(GetAndroidTagForVersion "$androidVersion")"}" |
|
allServices="$(GetAllServicesForTag "$androidVersion" "$tag")"; |
|
echo "ServiceName=$serviceName" |
|
echo "ServicePackageName=${servicePackage:="$(GetServicePackageName "$serviceName")"}" |
|
|
|
ParseServiceAIDL "$tag" "$allServices" "$servicePackage" |