summaryrefslogtreecommitdiff
path: root/startop/scripts/app_startup/lib/common
blob: bedaa1e10288bc40f113c7aa3ed3af503c3bc06d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#!/bin/bash
# Copyright 2018, 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.

if [[ -z $ANDROID_BUILD_TOP ]]; then
  echo "Please run source build/envsetup.sh first" >&2
  exit 1
fi

source $ANDROID_BUILD_TOP/build/envsetup.sh

verbose_print() {
  if [[ "$verbose" == "y" ]]; then
    echo "$@" >&2
  fi
}

remote_pidof() {
  local procname="$1"
  adb shell ps | grep "$procname" | awk '{print $2;}'
}

remote_pkill() {
  local procname="$1"
  shift

  local the_pids=$(remote_pidof "$procname")
  local pid

  for pid in $the_pids; do
    verbose_print adb shell kill "$@" "$pid"
    adb shell kill "$@" "$pid"
  done
}

get_activity_name() {
  local package="$1"
  local action_key="android.intent.action.MAIN:"

  # Example query-activities output being parsed:
  #
  #  Activity #14:
  #    priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true
  #    com.google.android.videos/com.google.android.youtube.videos.EntryPoint
  #  Activity #15:
  #    priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true
  #    com.google.android.youtube/.app.honeycomb.Shell$HomeActivity

  # Given package 'com.google.android.youtube' return '.app.honeycomb.Shell$HomeActivity'

  local activity_line="$(adb shell cmd package query-activities --brief -a android.intent.action.MAIN -c android.intent.category.LAUNCHER | grep "$package/")"
  IFS="/" read -a array <<< "$activity_line"
  local activity_name="${array[1]}"

  # Activities starting with '.' are shorthand for having their package name prefixed.
  if [[ $activity_name == .* ]]; then
    activity_name="${package}${activity_name}"
  fi
  echo "$activity_name"
}

# Use with logcat_from_timestamp to skip all past log-lines.
logcat_save_timestamp() {
  adb shell 'date -u +"%Y-%m-%d %H:%M:%S.%N"'
}

# Roll forward logcat to only show events
# since the specified timestamp.
#
# i.e. don't look at historical logcat,
# only look at FUTURE logcat.
#
# First use 'logcat_save_timestamp'
# Then do whatever action you want.
# Then use 'logcat_from_timestamp_bg $timestamp'
logcat_from_timestamp_bg() {
  local timestamp="$1"
  shift # drop timestamp from args.
  verbose_print adb logcat -T \"$timestamp\" \"$@\"
  adb logcat -v UTC -T "$timestamp" "$@" &
  logcat_from_timestamp_pid=$!
}

# Starting at timestamp $2, wait until we seen pattern $3
# or until a timeout happens in $1 seconds.
# If successful, also echo the line that matched the pattern.
#
# Set VERBOSE_LOGCAT=1 to debug every line of logcat it tries to parse.
logcat_select_pattern() {
  local timeout="$1"
  local timestamp="$2"
  local pattern="$3"

  local logcat_fd

  coproc logcat_fd {
    kill_children_quietly() {
      kill "$logcat_pidd"
      wait "$logcat_pidd" 2>/dev/null
    }

    trap 'kill_children_quietly' EXIT # kill logcat when this coproc is killed.

    # run logcat in the background so it can be killed.
    logcat_from_timestamp_bg "$timestamp"
    logcat_pidd=$logcat_from_timestamp_pid
    wait "$logcat_pidd"
  }
  local logcat_pid="$!"
  verbose_print "[LOGCAT] Spawn pid $logcat_pid"

  local timeout_ts="$(date -d "now + ${timeout} seconds" '+%s')"
  local now_ts="0"

  local return_code=1

  verbose_print "logcat_wait_for_pattern begin"

  while read -t "$timeout" -r -u "${logcat_fd[0]}" logcat_output; do
    if (( $VERBOSE_LOGCAT )); then
      verbose_print "LOGCAT: $logcat_output"
    fi
    if [[ "$logcat_output:" == *"$pattern"* ]]; then
      verbose_print "LOGCAT: " "$logcat_output"
      verbose_print "WE DID SEE PATTERN" '<<' "$pattern" '>>.'
      echo "$logcat_output"
      return_code=0
      break
    fi
    now_ts="$(date -d "now" '+%s')"
    if (( now_ts >= timeout_ts )); then
      verbose_print "DID TIMEOUT BEFORE SEEING ANYTHING (timeout=$timeout seconds) " '<<' "$pattern" '>>.'
      break
    fi
  done

  # Don't leave logcat lying around since it will keep going.
  kill "$logcat_pid"
  # Suppress annoying 'Terminated...' message.
  wait "$logcat_pid" 2>/dev/null

  verbose_print "[LOGCAT] $logcat_pid should be killed"

  return $return_code
}

# Starting at timestamp $2, wait until we seen pattern $3
# or until a timeout happens in $1 seconds.
#
# Set VERBOSE_LOGCAT=1 to debug every line of logcat it tries to parse.
logcat_wait_for_pattern() {
  logcat_select_pattern "$@" > /dev/null
}

# Starting at timestamp $2, wait until we seen pattern $3
# or until a timeout happens in $1 seconds.
# If successful, extract with the regular expression pattern in #4
# and return the first capture group.
#
# Set VERBOSE_LOGCAT=1 to debug every line of logcat it tries to parse.
logcat_extract_pattern() {
  local timeout="$1"
  local timestamp="$2"
  local pattern="$3"
  local re_pattern="$4"

  local result
  local exit_code

  result="$(logcat_select_pattern "$@")"
  exit_code=$?

  if [[ $exit_code -ne 0 ]]; then
    return $exit_code
  fi

  echo "$result" | sed 's/'"$re_pattern"'/\1/g'
}

# Join array
#   FOO=(a b c)
#   join_by , "${FOO[@]}" #a,b,c
join_by() {
  local IFS="$1"
  shift
  echo "$*"
}