diff options
Diffstat (limited to 'cmds/statsd/tools/loadtest')
26 files changed, 0 insertions, 2695 deletions
diff --git a/cmds/statsd/tools/loadtest/Android.bp b/cmds/statsd/tools/loadtest/Android.bp deleted file mode 100644 index bf87fc51dce1..000000000000 --- a/cmds/statsd/tools/loadtest/Android.bp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2017 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. -// -// - -android_app { - name: "StatsdLoadtest", - platform_apis: true, - - srcs: ["src/**/*.java"], - - resource_dirs: ["res"], - static_libs: [ - "platformprotoslite", - "statsdprotolite", - ], - - certificate: "platform", - privileged: true, - dex_preopt: { - enabled: false, - }, - optimize: { - enabled: false, - }, -} diff --git a/cmds/statsd/tools/loadtest/AndroidManifest.xml b/cmds/statsd/tools/loadtest/AndroidManifest.xml deleted file mode 100644 index 2bf8ca95d846..000000000000 --- a/cmds/statsd/tools/loadtest/AndroidManifest.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, 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. -*/ ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.statsd.loadtest" - android:sharedUserId="android.uid.system" - android:versionCode="1" - android:versionName="1.0" > - - <uses-permission android:name="android.permission.DUMP" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <application - android:allowBackup="true" - android:icon="@drawable/ic_launcher" - android:label="@string/app_name" > - <activity - android:name=".LoadtestActivity" - android:label="@string/app_name" - android:launchMode="singleTop" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - <receiver android:name=".LoadtestActivity$PusherAlarmReceiver" /> - <receiver android:name=".LoadtestActivity$StopperAlarmReceiver"/> - <receiver android:name=".PerfData$PerfAlarmReceiver"/> - </application> -</manifest> diff --git a/cmds/statsd/tools/loadtest/res/drawable-hdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-hdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 55621cc1074f..000000000000 --- a/cmds/statsd/tools/loadtest/res/drawable-hdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/drawable-mdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-mdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 11ec2068be19..000000000000 --- a/cmds/statsd/tools/loadtest/res/drawable-mdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/drawable-xhdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-xhdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 7c02b784aa5d..000000000000 --- a/cmds/statsd/tools/loadtest/res/drawable-xhdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/drawable-xxhdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-xxhdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 915d91441349..000000000000 --- a/cmds/statsd/tools/loadtest/res/drawable-xxhdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml b/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml deleted file mode 100644 index d6f804734385..000000000000 --- a/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, 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. -*/ ---> -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" > - - <LinearLayout - android:id="@+id/outside" - android:clickable="true" - android:focusable="true" - android:focusableInTouchMode="true" - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginRight="10dp" - android:layout_marginLeft="10dp" - android:orientation="vertical"> - <requestFocus /> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/replication_label" /> - <EditText - android:id="@+id/replication" - android:inputType="number" - android:layout_weight="1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:maxLength="4" - android:text="@integer/replication_default" - android:textSize="30dp"/> - </LinearLayout> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/bucket_label" /> - <Spinner - android:id="@+id/bucket_spinner" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:prompt="@string/bucket_label"/> - </LinearLayout> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/period_label" /> - <EditText - android:id="@+id/period" - android:inputType="number" - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:maxLength="3" - android:text="@integer/period_default" - android:textSize="30dp"/> - </LinearLayout> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/burst_label" /> - <EditText - android:id="@+id/burst" - android:inputType="number" - android:layout_weight="1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:maxLength="4" - android:text="@integer/burst_default" - android:textSize="30dp"/> - </LinearLayout> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/duration_label" /> - <EditText - android:id="@+id/duration" - android:inputType="number" - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:maxLength="4" - android:text="@integer/duration_default" - android:textSize="30dp"/> - </LinearLayout> - <CheckBox - android:id="@+id/placebo" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/placebo" - android:checked="false" /> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <CheckBox - android:id="@+id/include_count" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/count" - android:checked="true"/> - <CheckBox - android:id="@+id/include_duration" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/duration" - android:checked="true"/> - <CheckBox - android:id="@+id/include_event" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/event" - android:checked="true"/> - <CheckBox - android:id="@+id/include_value" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/value" - android:checked="true"/> - <CheckBox - android:id="@+id/include_gauge" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/gauge" - android:checked="true"/> - </LinearLayout> - - <Space - android:layout_width="1dp" - android:layout_height="30dp"/> - - <Button - android:id="@+id/start_stop" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="#ffff0000" - android:text="@string/start" - android:textSize="50dp"/> - - <Space - android:layout_width="1dp" - android:layout_height="30dp"/> - - <Space - android:layout_width="1dp" - android:layout_height="30dp"/> - - <TextView - android:id="@+id/report_text" - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - </LinearLayout> - -</ScrollView> diff --git a/cmds/statsd/tools/loadtest/res/layout/spinner_item.xml b/cmds/statsd/tools/loadtest/res/layout/spinner_item.xml deleted file mode 100644 index b03da06f7a77..000000000000 --- a/cmds/statsd/tools/loadtest/res/layout/spinner_item.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<TextView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textSize="30dp" - android:gravity="left" - android:padding="5dip" - /> diff --git a/cmds/statsd/tools/loadtest/res/raw/loadtest_config b/cmds/statsd/tools/loadtest/res/raw/loadtest_config Binary files differdeleted file mode 100755 index 24221908cbeb..000000000000 --- a/cmds/statsd/tools/loadtest/res/raw/loadtest_config +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/values/integers.xml b/cmds/statsd/tools/loadtest/res/values/integers.xml deleted file mode 100644 index c2407d3b85f2..000000000000 --- a/cmds/statsd/tools/loadtest/res/values/integers.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, 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. -*/ ---> -<resources> - <integer name="burst_default">1</integer> - <integer name="period_default">2</integer> - <integer name="replication_default">1</integer> - <integer name="duration_default">240</integer> -</resources> diff --git a/cmds/statsd/tools/loadtest/res/values/strings.xml b/cmds/statsd/tools/loadtest/res/values/strings.xml deleted file mode 100644 index e8ae3f82a7e3..000000000000 --- a/cmds/statsd/tools/loadtest/res/values/strings.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, 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. -*/ ---> -<resources> - <string name="app_name">Statsd Loadtest</string> - <string name="bucket_label">bucket size (mins): </string> - <string name="burst_label">burst: </string> - <string name="bucket_default">FIVE_MINUTES</string> - <string name="placebo">placebo</string> - <string name="period_label">logging period (secs): </string> - <string name="replication_label">metric replication: </string> - <string name="duration_label">test duration (mins): </string> - <string name="start">  Start  </string> - <string name="stop">  Stop  </string> - <string name="count"> count </string> - <string name="duration"> duration </string> - <string name="event"> event </string> - <string name="value"> value </string> - <string name="gauge"> gauge </string> - -</resources> diff --git a/cmds/statsd/tools/loadtest/run_loadtest.sh b/cmds/statsd/tools/loadtest/run_loadtest.sh deleted file mode 100755 index 3c93a0613183..000000000000 --- a/cmds/statsd/tools/loadtest/run_loadtest.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/sh -# -# Script that measures statsd's PSS under an increasing number of metrics. - -# Globals. -pss="" -pid="" - -# Starts the loadtest. -start_loadtest() { - echo "Starting loadtest" - adb shell am start -n com.android.statsd.loadtest/.LoadtestActivity --es "type" "start" -} - -# Stops the loadtest. -stop_loadtest() { - echo "Stopping loadtest" - adb shell am start -n com.android.statsd.loadtest/.LoadtestActivity --es "type" "stop" -} - -# Sets the metrics replication. -# Arguments: -# $1: The replication factor. -set_replication() { - adb shell am start -n com.android.statsd.loadtest/.LoadtestActivity --es "type" "set_replication" --ei "replication" "${1}" - echo "Replication set to ${1}" -} - -# Reads statsd's pid and PSS. -update_pid_and_pss() { - # Command that reads the PSS for statsd. This also gives us its pid. - get_mem=$(adb shell dumpsys meminfo |grep statsd) - # Looks for statsd's pid. - regex="([0-9,]+)K: statsd \(pid ([0-9]+)\).*" - if [[ $get_mem =~ $regex ]]; then - pss=$(echo "${BASH_REMATCH[1]}" | tr -d , | sed 's/\.//g') - pid=$(echo "${BASH_REMATCH[2]}") - else - echo $cmd doesnt match $regex - fi -} - -# Kills statsd. -# Assumes the pid has been set. -kill_statsd() { - echo "Killing statsd (pid ${pid})" - adb shell kill -9 "${pid}" -} - -# Main loop. -main() { - start_time=$(date +%s) - values=() - stop_loadtest - - echo "" - echo "********************* NEW LOADTEST ************************" - update_pid_and_pss - for replication in 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 - do - echo "**** Starting test at replication ${replication} ****" - - # (1) Restart statsd. This will ensure its state is empty. - kill_statsd - sleep 3 # wait a bit for it to restart - update_pid_and_pss - echo "Before the test, statsd's PSS is ${pss}" - - # (2) Set the replication. - set_replication "${replication}" - sleep 1 # wait a bit - - # (3) Start the loadtest. - start_loadtest - - # (4) Wait several seconds, then read the PSS. - sleep 100 && update_pid_and_pss - echo "During the test, statsd's PSS is ${pss}" - values+=(${pss}) - - echo "Values: ${values[@]}" - - # (5) Stop loadtest. - stop_loadtest - sleep 2 - - echo "" - done - - end_time=$(date +%s) - echo "Completed loadtest in $((${end_time} - ${start_time})) seconds." - - values_as_str=$(IFS=$'\n'; echo "${values[*]}") - echo "The PSS values are:" - echo "${values_as_str}" - echo "" -} - -main diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java deleted file mode 100644 index bab0c1e3f540..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.content.Context; -import android.util.Log; -import com.android.internal.os.StatsdConfigProto.TimeUnit; -import java.text.ParseException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class BatteryDataRecorder extends PerfDataRecorder { - private static final String TAG = "loadtest.BatteryDataRecorder"; - private static final String DUMP_FILENAME = TAG + "_dump.tmp"; - - public BatteryDataRecorder(boolean placebo, int replication, TimeUnit bucket, long periodSecs, - int burst, boolean includeCountMetric, boolean includeDurationMetric, - boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - } - - @Override - public void startRecording(Context context) { - // Reset batterystats. - runDumpsysStats(context, DUMP_FILENAME, "batterystats", "--reset"); - } - - @Override - public void onAlarm(Context context) { - // Nothing to do as for battery, the whole data is in the final dumpsys call. - } - - @Override - public void stopRecording(Context context) { - StringBuilder sb = new StringBuilder(); - // Don't use --checkin. - runDumpsysStats(context, DUMP_FILENAME, "batterystats"); - readDumpData(context, DUMP_FILENAME, new BatteryStatsParser(), sb); - writeData(context, "battery_", "time,battery_level", sb); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryStatsParser.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryStatsParser.java deleted file mode 100644 index 203d97acefd8..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryStatsParser.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.util.Log; -import java.text.ParseException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class BatteryStatsParser implements PerfParser { - - private static final Pattern LINE_PATTERN = - Pattern.compile("\\s*\\+*(\\S*)\\s\\(\\d+\\)\\s(\\d\\d\\d)\\s.*"); - private static final Pattern TIME_PATTERN = - Pattern.compile("(\\d+)?(h)?(\\d+)?(m)?(\\d+)?(s)?(\\d+)?(ms)?"); - private static final String TAG = "loadtest.BatteryStatsParser"; - - private boolean mHistoryStarted; - private boolean mHistoryEnded; - - public BatteryStatsParser() { - } - - @Override - @Nullable - public String parseLine(String line) { - if (mHistoryEnded) { - return null; - } - if (!mHistoryStarted) { - if (line.contains("Battery History")) { - mHistoryStarted = true; - } - return null; - } - if (line.isEmpty()) { - mHistoryEnded = true; - return null; - } - Matcher lineMatcher = LINE_PATTERN.matcher(line); - if (lineMatcher.find() && lineMatcher.group(1) != null && lineMatcher.group(2) != null) { - if (lineMatcher.group(1).equals("0")) { - return "0," + lineMatcher.group(2) + "\n"; - } else { - Matcher timeMatcher = TIME_PATTERN.matcher(lineMatcher.group(1)); - if (timeMatcher.find()) { - Long time = getTime(lineMatcher.group(1)); - if (time != null) { - return time + "," + lineMatcher.group(2) + "\n"; - } else { - return null; // bad time - } - } else { - return null; // bad or no time - } - } - } - return null; - } - - @Nullable - private Long getTime(String group) { - if ("0".equals(group)) { - return 0L; - } - Matcher timeMatcher = TIME_PATTERN.matcher(group); - if (!timeMatcher.find()) { - return null; - } - - // Get rid of "ms". - String[] matches = group.split("ms", -1); - if (matches.length > 1) { - group = matches[0]; - } - - long time = 0L; - matches = group.split("h"); - if (matches.length > 1) { - time += Long.parseLong(matches[0]) * 60 * 60 * 1000; // hours - group = matches[1]; - } - matches = group.split("m"); - if (matches.length > 1) { - time += Long.parseLong(matches[0]) * 60 * 1000; // minutes - group = matches[1]; - } - matches = group.split("s"); - if (matches.length > 1) { - time += Long.parseLong(matches[0]) * 1000; // seconds - group = matches[1]; - } - - if (!group.isEmpty()) { - time += Long.parseLong(group); // milliseconds - } - return time; - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java deleted file mode 100644 index 2e0161be8096..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.content.Context; -import android.content.res.Resources; -import android.util.Log; - -import com.android.internal.os.StatsdConfigProto.Predicate; -import com.android.internal.os.StatsdConfigProto.CountMetric; -import com.android.internal.os.StatsdConfigProto.DurationMetric; -import com.android.internal.os.StatsdConfigProto.MetricConditionLink; -import com.android.internal.os.StatsdConfigProto.EventMetric; -import com.android.internal.os.StatsdConfigProto.GaugeMetric; -import com.android.internal.os.StatsdConfigProto.ValueMetric; -import com.android.internal.os.StatsdConfigProto.FieldValueMatcher; -import com.android.internal.os.StatsdConfigProto.AtomMatcher; -import com.android.internal.os.StatsdConfigProto.SimplePredicate; -import com.android.internal.os.StatsdConfigProto.StatsdConfig; -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -import java.io.InputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Creates StatsdConfig protos for loadtesting. - */ -public class ConfigFactory { - public static class ConfigMetadata { - public final byte[] bytes; - public final int numMetrics; - - public ConfigMetadata(byte[] bytes, int numMetrics) { - this.bytes = bytes; - this.numMetrics = numMetrics; - } - } - - public static final long CONFIG_ID = 123456789; - - private static final String TAG = "loadtest.ConfigFactory"; - - private final StatsdConfig mTemplate; - - public ConfigFactory(Context context) { - // Read the config template from the resoures. - Resources res = context.getResources(); - byte[] template = null; - StatsdConfig templateProto = null; - try { - InputStream inputStream = res.openRawResource(R.raw.loadtest_config); - template = new byte[inputStream.available()]; - inputStream.read(template); - templateProto = StatsdConfig.parseFrom(template); - } catch (IOException e) { - Log.e(TAG, "Unable to read or parse loadtest config template. Using an empty config."); - } - mTemplate = templateProto == null ? StatsdConfig.newBuilder().build() : templateProto; - - Log.d(TAG, "Loadtest template config: " + mTemplate); - } - - /** - * Generates a config. - * - * All configs are based on the same template. - * That template is designed to make the most use of the set of atoms that {@code SequencePusher} - * pushes, and to exercise as many of the metrics features as possible. - * Furthermore, by passing a replication factor to this method, one can artificially inflate - * the number of metrics in the config. One can also adjust the bucket size for aggregate - * metrics. - * - * @param replication The number of times each metric is replicated in the config. - * If the config template has n metrics, the generated config will have n * replication - * ones - * @param bucketMillis The bucket size, in milliseconds, for aggregate metrics - * @param placebo If true, only return an empty config - * @return The serialized config and the number of metrics. - */ - public ConfigMetadata getConfig(int replication, TimeUnit bucket, boolean placebo, - boolean includeCount, boolean includeDuration, boolean includeEvent, - boolean includeValue, boolean includeGauge) { - StatsdConfig.Builder config = StatsdConfig.newBuilder() - .setId(CONFIG_ID); - if (placebo) { - replication = 0; // Config will be empty, aside from a name. - } - int numMetrics = 0; - for (int i = 0; i < replication; i++) { - // metrics - if (includeEvent) { - for (EventMetric metric : mTemplate.getEventMetricList()) { - addEventMetric(metric, i, config); - numMetrics++; - } - } - if (includeCount) { - for (CountMetric metric : mTemplate.getCountMetricList()) { - addCountMetric(metric, i, bucket, config); - numMetrics++; - } - } - if (includeDuration) { - for (DurationMetric metric : mTemplate.getDurationMetricList()) { - addDurationMetric(metric, i, bucket, config); - numMetrics++; - } - } - if (includeGauge) { - for (GaugeMetric metric : mTemplate.getGaugeMetricList()) { - addGaugeMetric(metric, i, bucket, config); - numMetrics++; - } - } - if (includeValue) { - for (ValueMetric metric : mTemplate.getValueMetricList()) { - addValueMetric(metric, i, bucket, config); - numMetrics++; - } - } - // predicates - for (Predicate predicate : mTemplate.getPredicateList()) { - addPredicate(predicate, i, config); - } - // matchers - for (AtomMatcher matcher : mTemplate.getAtomMatcherList()) { - addMatcher(matcher, i, config); - } - } - - Log.d(TAG, "Loadtest config is : " + config.build()); - Log.d(TAG, "Generated config has " + numMetrics + " metrics"); - - return new ConfigMetadata(config.build().toByteArray(), numMetrics); - } - - /** - * Creates {@link MetricConditionLink}s that are identical to the one passed to this method, - * except that the names are appended with the provided suffix. - */ - private List<MetricConditionLink> getLinks( - List<MetricConditionLink> links, int suffix) { - List<MetricConditionLink> newLinks = new ArrayList(); - for (MetricConditionLink link : links) { - newLinks.add(link.toBuilder() - .setCondition(link.getCondition() + suffix) - .build()); - } - return newLinks; - } - - /** - * Creates an {@link EventMetric} based on the template. Makes sure that all names are appended - * with the provided suffix. Then adds that metric to the config. - */ - private void addEventMetric(EventMetric template, int suffix, StatsdConfig.Builder config) { - EventMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - config.addEventMetric(metric); - } - - /** - * Creates a {@link CountMetric} based on the template. Makes sure that all names are appended - * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. - */ - private void addCountMetric(CountMetric template, int suffix, TimeUnit bucket, - StatsdConfig.Builder config) { - CountMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - metric.setBucket(bucket); - config.addCountMetric(metric); - } - - /** - * Creates a {@link DurationMetric} based on the template. Makes sure that all names are appended - * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. - */ - private void addDurationMetric(DurationMetric template, int suffix, TimeUnit bucket, - StatsdConfig.Builder config) { - DurationMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - metric.setBucket(bucket); - config.addDurationMetric(metric); - } - - /** - * Creates a {@link GaugeMetric} based on the template. Makes sure that all names are appended - * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. - */ - private void addGaugeMetric(GaugeMetric template, int suffix, TimeUnit bucket, - StatsdConfig.Builder config) { - GaugeMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - metric.setBucket(bucket); - config.addGaugeMetric(metric); - } - - /** - * Creates a {@link ValueMetric} based on the template. Makes sure that all names are appended - * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. - */ - private void addValueMetric(ValueMetric template, int suffix, TimeUnit bucket, - StatsdConfig.Builder config) { - ValueMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - metric.setBucket(bucket); - config.addValueMetric(metric); - } - - /** - * Creates a {@link Predicate} based on the template. Makes sure that all names - * are appended with the provided suffix. Then adds that predicate to the config. - */ - private void addPredicate(Predicate template, int suffix, StatsdConfig.Builder config) { - Predicate.Builder predicate = template.toBuilder() - .setId(template.getId() + suffix); - if (template.hasCombination()) { - Predicate.Combination.Builder cb = template.getCombination().toBuilder() - .clearPredicate(); - for (long child : template.getCombination().getPredicateList()) { - cb.addPredicate(child + suffix); - } - predicate.setCombination(cb.build()); - } - if (template.hasSimplePredicate()) { - SimplePredicate.Builder sc = template.getSimplePredicate().toBuilder() - .setStart(template.getSimplePredicate().getStart() + suffix) - .setStop(template.getSimplePredicate().getStop() + suffix); - if (template.getSimplePredicate().hasStopAll()) { - sc.setStopAll(template.getSimplePredicate().getStopAll() + suffix); - } - predicate.setSimplePredicate(sc.build()); - } - config.addPredicate(predicate); - } - - /** - * Creates a {@link AtomMatcher} based on the template. Makes sure that all names - * are appended with the provided suffix. Then adds that matcher to the config. - */ - private void addMatcher(AtomMatcher template, int suffix, StatsdConfig.Builder config) { - AtomMatcher.Builder matcher = template.toBuilder() - .setId(template.getId() + suffix); - if (template.hasCombination()) { - AtomMatcher.Combination.Builder cb = template.getCombination().toBuilder() - .clearMatcher(); - for (long child : template.getCombination().getMatcherList()) { - cb.addMatcher(child + suffix); - } - matcher.setCombination(cb); - } - config.addAtomMatcher(matcher); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java deleted file mode 100644 index d55f3f31fd9f..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.text.format.DateFormat; - -import com.android.os.StatsLog; - -import java.util.List; - -public class DisplayProtoUtils { - private static final int MAX_NUM_METRICS_TO_DISPLAY = 10; - - public static void displayLogReport(StringBuilder sb, StatsLog.ConfigMetricsReportList reports) { - sb.append("******************** Report ********************\n"); - if (reports.hasConfigKey()) { - sb.append("ConfigKey: "); - com.android.os.StatsLog.ConfigMetricsReportList.ConfigKey key = reports.getConfigKey(); - sb.append("\tuid: ").append(key.getUid()).append(" id: ").append(key.getId()) - .append("\n"); - } - - int numMetrics = 0; - for (StatsLog.ConfigMetricsReport report : reports.getReportsList()) { - sb.append("StatsLogReport size: ").append(report.getMetricsCount()).append("\n"); - sb.append("Last report time:").append(getDateStr(report.getLastReportElapsedNanos())). - append("\n"); - sb.append("Current report time:").append(getDateStr(report.getCurrentReportElapsedNanos())). - append("\n"); - for (StatsLog.StatsLogReport log : report.getMetricsList()) { - numMetrics++; - if (numMetrics > MAX_NUM_METRICS_TO_DISPLAY) { - sb.append("... output truncated\n"); - sb.append("************************************************"); - return; - } - sb.append("\n"); - sb.append("metric id: ").append(log.getMetricId()).append("\n"); - - switch (log.getDataCase()) { - case DURATION_METRICS: - sb.append("Duration metric data\n"); - displayDurationMetricData(sb, log); - break; - case EVENT_METRICS: - sb.append("Event metric data\n"); - displayEventMetricData(sb, log); - break; - case COUNT_METRICS: - sb.append("Count metric data\n"); - displayCountMetricData(sb, log); - break; - case GAUGE_METRICS: - sb.append("Gauge metric data\n"); - displayGaugeMetricData(sb, log); - break; - case VALUE_METRICS: - sb.append("Value metric data\n"); - displayValueMetricData(sb, log); - break; - case DATA_NOT_SET: - sb.append("No metric data\n"); - break; - } - } - } - sb.append("************************************************"); - } - - public static String getDateStr(long nanoSec) { - return DateFormat.format("dd/MM hh:mm:ss", nanoSec/1000000).toString(); - } - - private static void displayDimension(StringBuilder sb, StatsLog.DimensionsValue dimensionValue) { - sb.append(dimensionValue.getField()).append(":"); - if (dimensionValue.hasValueBool()) { - sb.append(dimensionValue.getValueBool()); - } else if (dimensionValue.hasValueFloat()) { - sb.append(dimensionValue.getValueFloat()); - } else if (dimensionValue.hasValueInt()) { - sb.append(dimensionValue.getValueInt()); - } else if (dimensionValue.hasValueStr()) { - sb.append(dimensionValue.getValueStr()); - } else if (dimensionValue.hasValueTuple()) { - sb.append("{"); - for (StatsLog.DimensionsValue child : - dimensionValue.getValueTuple().getDimensionsValueList()) { - displayDimension(sb, child); - } - sb.append("}"); - } - sb.append(" "); - } - - public static void displayDurationMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - StatsLog.StatsLogReport.DurationMetricDataWrapper durationMetricDataWrapper - = log.getDurationMetrics(); - sb.append("Dimension size: ").append(durationMetricDataWrapper.getDataCount()).append("\n"); - for (StatsLog.DurationMetricData duration : durationMetricDataWrapper.getDataList()) { - sb.append("dimension_in_what: "); - displayDimension(sb, duration.getDimensionsInWhat()); - sb.append("\n"); - if (duration.hasDimensionsInCondition()) { - sb.append("dimension_in_condition: "); - displayDimension(sb, duration.getDimensionsInCondition()); - sb.append("\n"); - } - - for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") - .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") - .append(info.getDurationNanos()).append(" ns\n"); - } - } - } - - public static void displayEventMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - sb.append("Contains ").append(log.getEventMetrics().getDataCount()).append(" events\n"); - StatsLog.StatsLogReport.EventMetricDataWrapper eventMetricDataWrapper = - log.getEventMetrics(); - for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) { - sb.append(getDateStr(event.getElapsedTimestampNanos())).append(": "); - sb.append(event.getAtom().getPushedCase().toString()).append("\n"); - } - } - - public static void displayCountMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - StatsLog.StatsLogReport.CountMetricDataWrapper countMetricDataWrapper - = log.getCountMetrics(); - sb.append("Dimension size: ").append(countMetricDataWrapper.getDataCount()).append("\n"); - for (StatsLog.CountMetricData count : countMetricDataWrapper.getDataList()) { - sb.append("dimension_in_what: "); - displayDimension(sb, count.getDimensionsInWhat()); - sb.append("\n"); - if (count.hasDimensionsInCondition()) { - sb.append("dimension_in_condition: "); - displayDimension(sb, count.getDimensionsInCondition()); - sb.append("\n"); - } - - for (StatsLog.CountBucketInfo info : count.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") - .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") - .append(info.getCount()).append("\n"); - } - } - } - - public static void displayGaugeMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - sb.append("Display me!"); - } - - public static void displayValueMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - sb.append("Display me!"); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java deleted file mode 100644 index 769f78c726e8..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java +++ /dev/null @@ -1,756 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.app.Activity; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.app.StatsManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.graphics.Color; -import android.os.Bundle; -import android.os.Handler; -import android.os.IStatsManager; -import android.os.PowerManager; -import android.os.PowerManager.WakeLock; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Log; -import android.util.StatsLog; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.view.MotionEvent; -import android.view.View.OnFocusChangeListener; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -import com.android.os.StatsLog.ConfigMetricsReport; -import com.android.os.StatsLog.ConfigMetricsReportList; -import com.android.os.StatsLog.StatsdStatsReport; -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Runs a load test for statsd. - * How it works: - * <ul> - * <li> Sets up and pushes a custom config with metrics that exercise a large swath of code paths. - * <li> Periodically logs certain atoms into logd. - * <li> Impact on battery can be printed to logcat, or a bug report can be filed and analyzed - * in battery Historian. - * </ul> - * The load depends on how demanding the config is, as well as how frequently atoms are pushsed - * to logd. Those are all controlled by 4 adjustable parameters: - * <ul> - * <li> The 'replication' parameter artificially multiplies the number of metrics in the config. - * <li> The bucket size controls the time-bucketing the aggregate metrics. - * <li> The period parameter controls how frequently atoms are pushed to logd. - * <li> The 'burst' parameter controls how many atoms are pushed at the same time (per period). - * </ul> - */ -public class LoadtestActivity extends Activity implements AdapterView.OnItemSelectedListener { - - private static final String TAG = "loadtest.LoadtestActivity"; - public static final String TYPE = "type"; - private static final String PUSH_ALARM = "push_alarm"; - public static final String PERF_ALARM = "perf_alarm"; - private static final String SET_REPLICATION = "set_replication"; - private static final String REPLICATION = "replication"; - private static final String START = "start"; - private static final String STOP = "stop"; - private static final Map<String, TimeUnit> TIME_UNIT_MAP = initializeTimeUnitMap(); - private static final List<String> TIME_UNIT_LABELS = initializeTimeUnitLabels(); - - public final static class PusherAlarmReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Intent activityIntent = new Intent(context, LoadtestActivity.class); - activityIntent.putExtra(TYPE, PUSH_ALARM); - context.startActivity(activityIntent); - } - } - - public final static class StopperAlarmReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Intent activityIntent = new Intent(context, LoadtestActivity.class); - activityIntent.putExtra(TYPE, STOP); - context.startActivity(activityIntent); - } - } - - private static Map<String, TimeUnit> initializeTimeUnitMap() { - Map<String, TimeUnit> labels = new HashMap(); - labels.put("1m", TimeUnit.ONE_MINUTE); - labels.put("5m", TimeUnit.FIVE_MINUTES); - labels.put("10m", TimeUnit.TEN_MINUTES); - labels.put("30m", TimeUnit.THIRTY_MINUTES); - labels.put("1h", TimeUnit.ONE_HOUR); - labels.put("3h", TimeUnit.THREE_HOURS); - labels.put("6h", TimeUnit.SIX_HOURS); - labels.put("12h", TimeUnit.TWELVE_HOURS); - labels.put("1d", TimeUnit.ONE_DAY); - labels.put("1s", TimeUnit.CTS); - return labels; - } - - private static List<String> initializeTimeUnitLabels() { - List<String> labels = new ArrayList(); - labels.add("1s"); - labels.add("1m"); - labels.add("5m"); - labels.add("10m"); - labels.add("30m"); - labels.add("1h"); - labels.add("3h"); - labels.add("6h"); - labels.add("12h"); - labels.add("1d"); - return labels; - } - - private AlarmManager mAlarmMgr; - - /** - * Used to periodically log atoms to logd. - */ - private PendingIntent mPushPendingIntent; - - /** - * Used to end the loadtest. - */ - private PendingIntent mStopPendingIntent; - - private Button mStartStop; - private EditText mReplicationText; - private Spinner mBucketSpinner; - private EditText mPeriodText; - private EditText mBurstText; - private EditText mDurationText; - private TextView mReportText; - private CheckBox mPlaceboCheckBox; - private CheckBox mCountMetricCheckBox; - private CheckBox mDurationMetricCheckBox; - private CheckBox mEventMetricCheckBox; - private CheckBox mValueMetricCheckBox; - private CheckBox mGaugeMetricCheckBox; - - /** - * When the load test started. - */ - private long mStartedTimeMillis; - - /** - * For measuring perf data. - */ - private PerfData mPerfData; - - /** - * For communicating with statsd. - */ - private StatsManager mStatsManager; - - private PowerManager mPowerManager; - private WakeLock mWakeLock; - - /** - * If true, we only measure the effect of the loadtest infrastructure. No atom are pushed and - * the configuration is empty. - */ - private boolean mPlacebo; - - /** - * Whether to include CountMetric in the config. - */ - private boolean mIncludeCountMetric; - - /** - * Whether to include DurationMetric in the config. - */ - private boolean mIncludeDurationMetric; - - /** - * Whether to include EventMetric in the config. - */ - private boolean mIncludeEventMetric; - - /** - * Whether to include ValueMetric in the config. - */ - private boolean mIncludeValueMetric; - - /** - * Whether to include GaugeMetric in the config. - */ - private boolean mIncludeGaugeMetric; - - /** - * The burst size. - */ - private int mBurst; - - /** - * The metrics replication. - */ - private int mReplication; - - /** - * The period, in seconds, at which batches of atoms are pushed. - */ - private long mPeriodSecs; - - /** - * The bucket size, in minutes, for aggregate metrics. - */ - private TimeUnit mBucket; - - /** - * The duration, in minutes, of the loadtest. - */ - private long mDurationMins; - - /** - * Whether the loadtest has started. - */ - private boolean mStarted = false; - - /** - * Orchestrates the logging of pushed events into logd. - */ - private SequencePusher mPusher; - - /** - * Generates statsd configs. - */ - private ConfigFactory mFactory; - - /** - * For intra-minute periods. - */ - private final Handler mHandler = new Handler(); - - /** - * Number of metrics in the current config. - */ - private int mNumMetrics; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Log.d(TAG, "Starting loadtest Activity"); - - setContentView(R.layout.activity_loadtest); - mReportText = (TextView) findViewById(R.id.report_text); - initBurst(); - initReplication(); - initBucket(); - initPeriod(); - initDuration(); - initPlacebo(); - initMetricWhitelist(); - - // Hide the keyboard outside edit texts. - findViewById(R.id.outside).setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - InputMethodManager imm = - (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - if (getCurrentFocus() != null) { - imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); - } - return true; - } - }); - - mStartStop = findViewById(R.id.start_stop); - mStartStop.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (mStarted) { - stopLoadtest(); - } else { - startLoadtest(); - } - } - }); - - mAlarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE); - mStatsManager = (StatsManager) getSystemService("stats"); - mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); - mFactory = new ConfigFactory(this); - stopLoadtest(); - mReportText.setText(""); - } - - @Override - public void onNewIntent(Intent intent) { - String type = intent.getStringExtra(TYPE); - if (type == null) { - return; - } - switch (type) { - case PERF_ALARM: - onPerfAlarm(); - break; - case PUSH_ALARM: - onAlarm(); - break; - case SET_REPLICATION: - if (intent.hasExtra(REPLICATION)) { - setReplication(intent.getIntExtra(REPLICATION, 0)); - } - break; - case START: - startLoadtest(); - break; - case STOP: - stopLoadtest(); - break; - default: - throw new IllegalArgumentException("Unknown type: " + type); - } - } - - @Override - public void onDestroy() { - Log.d(TAG, "Destroying"); - mPerfData.onDestroy(); - stopLoadtest(); - clearConfigs(); - super.onDestroy(); - } - - @Nullable - public StatsdStatsReport getMetadata() { - if (!statsdRunning()) { - return null; - } - if (mStatsManager != null) { - byte[] data; - try { - data = mStatsManager.getStatsMetadata(); - } catch (StatsManager.StatsUnavailableException e) { - Log.e(TAG, "Failed to get data from statsd", e); - return null; - } - if (data != null) { - StatsdStatsReport report = null; - boolean good = false; - try { - return StatsdStatsReport.parseFrom(data); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - Log.d(TAG, "Bad StatsdStatsReport"); - } - } - } - return null; - } - - @Nullable - public List<ConfigMetricsReport> getData() { - if (!statsdRunning()) { - return null; - } - if (mStatsManager != null) { - byte[] data; - try { - data = mStatsManager.getReports(ConfigFactory.CONFIG_ID); - } catch (StatsManager.StatsUnavailableException e) { - Log.e(TAG, "Failed to get data from statsd", e); - return null; - } - if (data != null) { - ConfigMetricsReportList reports = null; - try { - reports = ConfigMetricsReportList.parseFrom(data); - Log.d(TAG, "Num reports: " + reports.getReportsCount()); - StringBuilder sb = new StringBuilder(); - DisplayProtoUtils.displayLogReport(sb, reports); - Log.d(TAG, sb.toString()); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - Log.d(TAG, "Invalid data"); - } - if (reports != null) { - return reports.getReportsList(); - } - } - } - return null; - } - - @Override - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - String item = parent.getItemAtPosition(position).toString(); - - mBucket = TIME_UNIT_MAP.get(item); - } - - @Override - public void onNothingSelected(AdapterView<?> parent) { - // Another interface callback - } - - private void onPerfAlarm() { - if (mPerfData != null) { - mPerfData.onAlarm(this); - } - // Piggy-back on that alarm to show the elapsed time. - long elapsedTimeMins = (long) Math.floor( - (SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000); - mReportText.setText("Loadtest in progress.\n" - + "num metrics =" + mNumMetrics - + "\nElapsed time = " + elapsedTimeMins + " min(s)"); - } - - private void onAlarm() { - Log.d(TAG, "ON ALARM"); - - // Set the next task. - scheduleNext(); - - // Do the work. - mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "StatsdLoadTest"); - mWakeLock.acquire(); - if (mPusher != null) { - mPusher.next(); - } - mWakeLock.release(); - mWakeLock = null; - } - - /** - * Schedules the next cycle of pushing atoms into logd. - */ - private void scheduleNext() { - Intent intent = new Intent(this, PusherAlarmReceiver.class); - intent.putExtra(TYPE, PUSH_ALARM); - mPushPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); - long nextTime = SystemClock.elapsedRealtime() + mPeriodSecs * 1000; - mAlarmMgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextTime, mPushPendingIntent); - } - - private synchronized void startLoadtest() { - if (mStarted) { - return; - } - - // Clean up the state. - stopLoadtest(); - - // Prepare to push a sequence of atoms to logd. - mPusher = new SequencePusher(mBurst, mPlacebo); - - // Create a config and push it to statsd. - if (!setConfig(mFactory.getConfig(mReplication, mBucket, mPlacebo, - mIncludeCountMetric, mIncludeDurationMetric, mIncludeEventMetric, - mIncludeValueMetric, mIncludeGaugeMetric))) { - return; - } - - // Remember to stop in the future. - Intent intent = new Intent(this, StopperAlarmReceiver.class); - intent.putExtra(TYPE, STOP); - mStopPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); - long nextTime = SystemClock.elapsedRealtime() + mDurationMins * 60 * 1000; - mAlarmMgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextTime, mStopPendingIntent); - - // Log atoms. - scheduleNext(); - - // Start tracking performance. - mPerfData = new PerfData(this, mPlacebo, mReplication, mBucket, mPeriodSecs, mBurst, - mIncludeCountMetric, mIncludeDurationMetric, mIncludeEventMetric, mIncludeValueMetric, - mIncludeGaugeMetric); - mPerfData.startRecording(this); - - mReportText.setText("Loadtest in progress.\nnum metrics =" + mNumMetrics); - mStartedTimeMillis = SystemClock.elapsedRealtime(); - - updateStarted(true); - } - - private synchronized void stopLoadtest() { - if (mPushPendingIntent != null) { - Log.d(TAG, "Canceling pre-existing push alarm"); - mAlarmMgr.cancel(mPushPendingIntent); - mPushPendingIntent = null; - } - if (mStopPendingIntent != null) { - Log.d(TAG, "Canceling pre-existing stop alarm"); - mAlarmMgr.cancel(mStopPendingIntent); - mStopPendingIntent = null; - } - if (mWakeLock != null) { - mWakeLock.release(); - mWakeLock = null; - } - if (mPerfData != null) { - mPerfData.stopRecording(this); - mPerfData.onDestroy(); - mPerfData = null; - } - - // Obtain the latest data and display it. - getData(); - - long elapsedTimeMins = (long) Math.floor( - (SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000); - mReportText.setText("Loadtest ended. Elapsed time = " + elapsedTimeMins + " min(s)"); - clearConfigs(); - updateStarted(false); - } - - private synchronized void updateStarted(boolean started) { - mStarted = started; - mStartStop.setBackgroundColor(started ? - Color.parseColor("#FFFF0000") : Color.parseColor("#FF00FF00")); - mStartStop.setText(started ? getString(R.string.stop) : getString(R.string.start)); - updateControlsEnabled(); - } - - private void updateControlsEnabled() { - mBurstText.setEnabled(!mPlacebo && !mStarted); - mReplicationText.setEnabled(!mPlacebo && !mStarted); - mPeriodText.setEnabled(!mStarted); - mBucketSpinner.setEnabled(!mPlacebo && !mStarted); - mDurationText.setEnabled(!mStarted); - mPlaceboCheckBox.setEnabled(!mStarted); - - boolean enabled = !mStarted && !mPlaceboCheckBox.isChecked(); - mCountMetricCheckBox.setEnabled(enabled); - mDurationMetricCheckBox.setEnabled(enabled); - mEventMetricCheckBox.setEnabled(enabled); - mValueMetricCheckBox.setEnabled(enabled); - mGaugeMetricCheckBox.setEnabled(enabled); - } - - private boolean statsdRunning() { - if (IStatsManager.Stub.asInterface(ServiceManager.getService("stats")) == null) { - Log.d(TAG, "Statsd not running"); - Toast.makeText(LoadtestActivity.this, "Statsd NOT running!", Toast.LENGTH_LONG).show(); - return false; - } - return true; - } - - private int sanitizeInt(int val, int min, int max) { - if (val > max) { - val = max; - } else if (val < min) { - val = min; - } - return val; - } - - private void clearConfigs() { - // TODO: Clear all configs instead of specific ones. - if (mStatsManager != null) { - if (mStarted) { - try { - mStatsManager.removeConfig(ConfigFactory.CONFIG_ID); - Log.d(TAG, "Removed loadtest statsd configs."); - } catch (StatsManager.StatsUnavailableException e) { - Log.e(TAG, "Failed to remove loadtest configs.", e); - } - } - } - } - - private boolean setConfig(ConfigFactory.ConfigMetadata configData) { - if (mStatsManager != null) { - try { - mStatsManager.addConfig(ConfigFactory.CONFIG_ID, configData.bytes); - mNumMetrics = configData.numMetrics; - Log.d(TAG, "Config pushed to statsd"); - return true; - } catch (StatsManager.StatsUnavailableException | IllegalArgumentException e) { - Log.e(TAG, "Failed to push config to statsd", e); - } - } - return false; - } - - private synchronized void setReplication(int replication) { - if (mStarted) { - return; - } - mReplicationText.setText("" + replication); - } - - private synchronized void setPeriodSecs(long periodSecs) { - mPeriodSecs = periodSecs; - } - - private synchronized void setBurst(int burst) { - mBurst = burst; - } - - private synchronized void setDurationMins(long durationMins) { - mDurationMins = durationMins; - } - - - private void handleFocus(EditText editText) { - /* - editText.setOnFocusChangeListener(new OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (!hasFocus && editText.getText().toString().isEmpty()) { - editText.setText("-1", TextView.BufferType.EDITABLE); - } - } - }); - */ - } - - private void initBurst() { - mBurst = getResources().getInteger(R.integer.burst_default); - mBurstText = (EditText) findViewById(R.id.burst); - mBurstText.addTextChangedListener(new NumericalWatcher(mBurstText, 0, 1000) { - @Override - public void onNewValue(int newValue) { - setBurst(newValue); - } - }); - handleFocus(mBurstText); - } - - private void initReplication() { - mReplication = getResources().getInteger(R.integer.replication_default); - mReplicationText = (EditText) findViewById(R.id.replication); - mReplicationText.addTextChangedListener(new NumericalWatcher(mReplicationText, 1, 4096) { - @Override - public void onNewValue(int newValue) { - mReplication = newValue; - } - }); - handleFocus(mReplicationText); - } - - private void initBucket() { - String defaultValue = getResources().getString(R.string.bucket_default); - mBucket = TimeUnit.valueOf(defaultValue); - mBucketSpinner = (Spinner) findViewById(R.id.bucket_spinner); - - ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>( - this, R.layout.spinner_item, TIME_UNIT_LABELS); - - mBucketSpinner.setAdapter(dataAdapter); - mBucketSpinner.setOnItemSelectedListener(this); - - for (String label : TIME_UNIT_MAP.keySet()) { - if (defaultValue.equals(TIME_UNIT_MAP.get(label).toString())) { - mBucketSpinner.setSelection(dataAdapter.getPosition(label)); - } - } - } - - private void initPeriod() { - mPeriodSecs = getResources().getInteger(R.integer.period_default); - mPeriodText = (EditText) findViewById(R.id.period); - mPeriodText.addTextChangedListener(new NumericalWatcher(mPeriodText, 1, 60) { - @Override - public void onNewValue(int newValue) { - setPeriodSecs(newValue); - } - }); - handleFocus(mPeriodText); - } - - private void initDuration() { - mDurationMins = getResources().getInteger(R.integer.duration_default); - mDurationText = (EditText) findViewById(R.id.duration); - mDurationText.addTextChangedListener(new NumericalWatcher(mDurationText, 1, 24 * 60) { - @Override - public void onNewValue(int newValue) { - setDurationMins(newValue); - } - }); - handleFocus(mDurationText); - } - - private void initPlacebo() { - mPlaceboCheckBox = findViewById(R.id.placebo); - mPlacebo = false; - mPlaceboCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mPlacebo = mPlaceboCheckBox.isChecked(); - updateControlsEnabled(); - } - }); - } - - private void initMetricWhitelist() { - mCountMetricCheckBox = findViewById(R.id.include_count); - mCountMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeCountMetric = mCountMetricCheckBox.isChecked(); - } - }); - mDurationMetricCheckBox = findViewById(R.id.include_duration); - mDurationMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeDurationMetric = mDurationMetricCheckBox.isChecked(); - } - }); - mEventMetricCheckBox = findViewById(R.id.include_event); - mEventMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeEventMetric = mEventMetricCheckBox.isChecked(); - } - }); - mValueMetricCheckBox = findViewById(R.id.include_value); - mValueMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeValueMetric = mValueMetricCheckBox.isChecked(); - } - }); - mGaugeMetricCheckBox = findViewById(R.id.include_gauge); - mGaugeMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeGaugeMetric = mGaugeMetricCheckBox.isChecked(); - } - }); - - mIncludeCountMetric = mCountMetricCheckBox.isChecked(); - mIncludeDurationMetric = mDurationMetricCheckBox.isChecked(); - mIncludeEventMetric = mEventMetricCheckBox.isChecked(); - mIncludeValueMetric = mValueMetricCheckBox.isChecked(); - mIncludeGaugeMetric = mGaugeMetricCheckBox.isChecked(); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemInfoParser.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemInfoParser.java deleted file mode 100644 index 01eebf2ad1cf..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemInfoParser.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.os.SystemClock; -import android.util.Log; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** Parses PSS info from dumpsys meminfo */ -public class MemInfoParser implements PerfParser { - - private static final Pattern LINE_PATTERN = - Pattern.compile("\\s*(\\d*,*\\d*)K:\\s(\\S*)\\s\\.*"); - private static final String PSS_BY_PROCESS = "Total PSS by process:"; - private static final String TAG = "loadtest.MemInfoParser"; - - private boolean mPssStarted; - private boolean mPssEnded; - private final long mStartTimeMillis; - - public MemInfoParser(long startTimeMillis) { - mStartTimeMillis = startTimeMillis; - } - - @Override - @Nullable - public String parseLine(String line) { - if (mPssEnded) { - return null; - } - if (!mPssStarted) { - if (line.contains(PSS_BY_PROCESS)) { - mPssStarted = true; - } - return null; - } - if (line.isEmpty()) { - mPssEnded = true; - return null; - } - Matcher lineMatcher = LINE_PATTERN.matcher(line); - if (lineMatcher.find() && lineMatcher.group(1) != null && lineMatcher.group(2) != null) { - if (lineMatcher.group(2).equals("statsd")) { - long timeDeltaMillis = SystemClock.elapsedRealtime() - mStartTimeMillis; - return timeDeltaMillis + "," + convertToPss(lineMatcher.group(1)); - } - } - return null; - } - - private String convertToPss(String input) { - return input.replace(",", ""); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java deleted file mode 100644 index af7bd4d35966..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.content.Context; -import android.os.SystemClock; -import android.util.Log; -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -public class MemoryDataRecorder extends PerfDataRecorder { - private static final String TAG = "loadtest.MemoryDataDataRecorder"; - private static final String DUMP_FILENAME = TAG + "_dump.tmp"; - - private long mStartTimeMillis; - private StringBuilder mSb; - - public MemoryDataRecorder(boolean placebo, int replication, TimeUnit bucket, long periodSecs, - int burst, boolean includeCountMetric, boolean includeDurationMetric, - boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - } - - @Override - public void startRecording(Context context) { - mStartTimeMillis = SystemClock.elapsedRealtime(); - mSb = new StringBuilder(); - } - - @Override - public void onAlarm(Context context) { - runDumpsysStats(context, DUMP_FILENAME, "meminfo"); - readDumpData(context, DUMP_FILENAME, new MemInfoParser(mStartTimeMillis), mSb); - } - - @Override - public void stopRecording(Context context) { - writeData(context, "meminfo_", "time,pss", mSb); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/NumericalWatcher.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/NumericalWatcher.java deleted file mode 100644 index 555e6dd2d99d..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/NumericalWatcher.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Log; -import android.widget.TextView; - -public abstract class NumericalWatcher implements TextWatcher { - - private static final String TAG = "loadtest.NumericalWatcher"; - - private final TextView mTextView; - private final int mMin; - private final int mMax; - private int currentValue = -1; - - public NumericalWatcher(TextView textView, int min, int max) { - mTextView = textView; - mMin = min; - mMax = max; - } - - public abstract void onNewValue(int newValue); - - @Override - final public void afterTextChanged(Editable editable) { - String s = mTextView.getText().toString(); - if (s.isEmpty()) { - return; - } - int unsanitized = Integer.parseInt(s); - int newValue = sanitize(unsanitized); - if (currentValue != newValue || unsanitized != newValue) { - currentValue = newValue; - editable.clear(); - editable.append(newValue + ""); - } - onNewValue(newValue); - } - - @Override - final public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override - final public void onTextChanged(CharSequence s, int start, int before, int count) {} - - private int sanitize(int val) { - if (val > mMax) { - val = mMax; - } else if (val < mMin) { - val = mMin; - } - return val; - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java deleted file mode 100644 index 7a01adedfaa4..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -import android.annotation.Nullable; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.SystemClock; -import android.util.Log; - -import java.util.HashSet; -import java.util.Set; - -/** Prints some information about the device via Dumpsys in order to evaluate health metrics. */ -public class PerfData extends PerfDataRecorder { - - private static final String TAG = "loadtest.PerfData"; - - /** Polling period for performance snapshots like memory. */ - private static final long POLLING_PERIOD_MILLIS = 1 * 60 * 1000; - - public final static class PerfAlarmReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Intent activityIntent = new Intent(context, LoadtestActivity.class); - activityIntent.putExtra(LoadtestActivity.TYPE, LoadtestActivity.PERF_ALARM); - context.startActivity(activityIntent); - } - } - - private AlarmManager mAlarmMgr; - - /** Used to periodically poll some dumpsys data. */ - private PendingIntent mPendingIntent; - - private final Set<PerfDataRecorder> mRecorders; - - public PerfData(LoadtestActivity loadtestActivity, boolean placebo, int replication, - TimeUnit bucket, long periodSecs, int burst, boolean includeCountMetric, - boolean includeDurationMetric, boolean includeEventMetric, boolean includeValueMetric, - boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - mRecorders = new HashSet(); - mRecorders.add(new BatteryDataRecorder(placebo, replication, bucket, periodSecs, burst, - includeCountMetric, includeDurationMetric, includeEventMetric, includeValueMetric, - includeGaugeMetric)); - mRecorders.add(new MemoryDataRecorder(placebo, replication, bucket, periodSecs, burst, - includeCountMetric, includeDurationMetric, includeEventMetric, includeValueMetric, - includeGaugeMetric)); - mRecorders.add(new StatsdStatsRecorder(loadtestActivity, placebo, replication, bucket, - periodSecs, burst, includeCountMetric, includeDurationMetric, includeEventMetric, - includeValueMetric, includeGaugeMetric)); - mRecorders.add(new ValidationRecorder(loadtestActivity, placebo, replication, bucket, - periodSecs, burst, includeCountMetric, includeDurationMetric, includeEventMetric, - includeValueMetric, includeGaugeMetric)); - mAlarmMgr = (AlarmManager) loadtestActivity.getSystemService(Context.ALARM_SERVICE); - } - - public void onDestroy() { - if (mPendingIntent != null) { - mAlarmMgr.cancel(mPendingIntent); - mPendingIntent = null; - } - } - - @Override - public void startRecording(Context context) { - Intent intent = new Intent(context, PerfAlarmReceiver.class); - intent.putExtra(LoadtestActivity.TYPE, LoadtestActivity.PERF_ALARM); - mPendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); - mAlarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, -1 /* now */, - POLLING_PERIOD_MILLIS, mPendingIntent); - - for (PerfDataRecorder recorder : mRecorders) { - recorder.startRecording(context); - } - } - - @Override - public void onAlarm(Context context) { - for (PerfDataRecorder recorder : mRecorders) { - recorder.onAlarm(context); - } - } - - @Override - public void stopRecording(Context context) { - if (mPendingIntent != null) { - mAlarmMgr.cancel(mPendingIntent); - mPendingIntent = null; - } - - for (PerfDataRecorder recorder : mRecorders) { - recorder.stopRecording(context); - } - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java deleted file mode 100644 index 8613ac1c4796..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.content.Context; -import android.os.Environment; -import android.util.Log; -import android.os.Debug; - -import com.android.internal.os.StatsdConfigProto.TimeUnit; -import java.io.BufferedReader; -import java.io.Closeable; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.InputStreamReader; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; - -public abstract class PerfDataRecorder { - private static final String TAG = "loadtest.PerfDataRecorder"; - - protected final String mTimeAsString; - protected final String mColumnSuffix; - - protected PerfDataRecorder(boolean placebo, int replication, TimeUnit bucket, long periodSecs, - int burst, boolean includeCountMetric, boolean includeDurationMetric, - boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) { - mTimeAsString = new SimpleDateFormat("YYYY_MM_dd_HH_mm_ss").format(new Date()); - mColumnSuffix = getColumnSuffix(placebo, replication, bucket, periodSecs, burst, - includeCountMetric, includeDurationMetric, includeEventMetric, includeValueMetric, - includeGaugeMetric); - } - - /** Starts recording performance data. */ - public abstract void startRecording(Context context); - - /** Called periodically. For the recorder to sample data, if needed. */ - public abstract void onAlarm(Context context); - - /** Stops recording performance data, and writes it to disk. */ - public abstract void stopRecording(Context context); - - /** Runs the dumpsys command. */ - protected void runDumpsysStats(Context context, String dumpFilename, String cmd, - String... args) { - boolean success = false; - // Call dumpsys Dump statistics to a file. - FileOutputStream fo = null; - try { - fo = context.openFileOutput(dumpFilename, Context.MODE_PRIVATE); - if (!Debug.dumpService(cmd, fo.getFD(), args)) { - Log.w(TAG, "Dumpsys failed."); - } - success = true; - } catch (IOException | SecurityException | NullPointerException e) { - // SecurityException may occur when trying to dump multi-user info. - // NPE can occur during dumpService (root cause unknown). - throw new RuntimeException(e); - } finally { - closeQuietly(fo); - } - } - - /** - * Reads a text file and parses each line, one by one. The result of the parsing is stored - * in the passed {@link StringBuffer}. - */ - protected void readDumpData(Context context, String dumpFilename, PerfParser parser, - StringBuilder sb) { - FileInputStream fi = null; - BufferedReader br = null; - try { - fi = context.openFileInput(dumpFilename); - br = new BufferedReader(new InputStreamReader(fi)); - String line = br.readLine(); - while (line != null) { - String recordLine = parser.parseLine(line); - if (recordLine != null) { - sb.append(recordLine).append('\n'); - } - line = br.readLine(); - } - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - closeQuietly(br); - } - } - - /** Writes CSV data to a file. */ - protected void writeData(Context context, String filePrefix, String columnPrefix, - StringBuilder sb) { - File dataFile = new File(getStorageDir(), filePrefix + mTimeAsString + ".csv"); - - FileWriter writer = null; - try { - writer = new FileWriter(dataFile); - writer.append(columnPrefix + mColumnSuffix + "\n"); - writer.append(sb.toString()); - writer.flush(); - Log.d(TAG, "Finished writing data at " + dataFile.getAbsolutePath()); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - closeQuietly(writer); - } - } - - /** Gets the suffix to use in the column name for perf data. */ - private String getColumnSuffix(boolean placebo, int replication, TimeUnit bucket, - long periodSecs, int burst, boolean includeCountMetric, boolean includeDurationMetric, - boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) { - if (placebo) { - return "_placebo_p=" + periodSecs; - } - StringBuilder sb = new StringBuilder() - .append("_r=" + replication) - .append("_bkt=" + bucket) - .append("_p=" + periodSecs) - .append("_bst=" + burst) - .append("_m="); - if (includeCountMetric) { - sb.append("c"); - } - if (includeEventMetric) { - sb.append("e"); - } - if (includeDurationMetric) { - sb.append("d"); - } - if (includeGaugeMetric) { - sb.append("g"); - } - if (includeValueMetric) { - sb.append("v"); - } - return sb.toString(); - } - - private File getStorageDir() { - File file = new File(Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_DOCUMENTS), "loadtest/" + mTimeAsString); - if (!file.mkdirs()) { - Log.e(TAG, "Directory not created"); - } - return file; - } - - private void closeQuietly(@Nullable Closeable c) { - if (c != null) { - try { - c.close(); - } catch (IOException ignore) { - } - } - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfParser.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfParser.java deleted file mode 100644 index e000918fa0f7..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfParser.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; - -public interface PerfParser { - - /** - * Parses one line of the dumpsys output, and returns a string to write to the data file, - * or null if no string should be written. - */ - @Nullable String parseLine(String line); -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java deleted file mode 100644 index 5dcce9acb401..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.util.Log; -import android.util.StatsLog; - -import java.util.ArrayList; -import java.util.List; - -/** - * Manages the pushing of atoms into logd for loadtesting. - * We rely on small number of pushed atoms, and a config with metrics based on those atoms. - * The atoms are: - * <ul> - * <li> BatteryLevelChanged - For EventMetric, CountMetric and GaugeMetric (no dimensions). - * <li> BleScanResultReceived - For CountMetric and ValueMetric, sliced by uid. - * <li> ChargingStateChanged - For DurationMetric (no dimension). - * <li> GpsScanStateChanged - For DurationMetric, sliced by uid. - * <li> ScreenStateChanged - For Conditions with no dimensions. - * <li> AudioStateChanged - For Conditions with dimensions (uid). - * </ul> - * The sequence is played over and over at a given frequency. - */ -public class SequencePusher { - private static final String TAG = "SequencePusher"; - - /** Some atoms are pushed in burst of {@code mBurst} events. */ - private final int mBurst; - - /** If this is true, we don't log anything in logd. */ - private final boolean mPlacebo; - - /** Current state in the automaton. */ - private int mCursor = 0; - - public SequencePusher(int burst, boolean placebo) { - mBurst = burst; - mPlacebo = placebo; - } - - /** - * Pushes the next atom to logd. - * This follows a small automaton which makes the right events and conditions overlap: - * (0) Push a burst of BatteryLevelChanged atoms. - * (1) Push a burst of BleScanResultReceived atoms. - * (2) Push ChargingStateChanged with BATTERY_STATUS_CHARGING once. - * (3) Push a burst of GpsScanStateChanged atoms with ON, with a different uid each time. - * (4) Push ChargingStateChanged with BATTERY_STATUS_NOT_CHARGING once. - * (5) Push a burst GpsScanStateChanged atoms with OFF, with a different uid each time. - * (6) Push ScreenStateChanged with STATE_ON once. - * (7) Push a burst of AudioStateChanged with ON, with a different uid each time. - * (8) Repeat steps (0)-(5). - * (9) Push ScreenStateChanged with STATE_OFF once. - * (10) Push a burst of AudioStateChanged with OFF, with a different uid each time. - * and repeat. - */ - public void next() { - Log.d(TAG, "Next step: " + mCursor); - if (mPlacebo) { - return; - } - switch (mCursor) { - case 0: - case 8: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.BATTERY_LEVEL_CHANGED, 50 + i /* battery_level */); - } - break; - case 1: - case 9: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED, i /* uid */, - 100 /* num_of_results */); - } - break; - case 2: - case 10: - StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, - StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_CHARGING - /* charging_state */); - break; - case 3: - case 11: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, i /* uid */, - StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON /* state */); - } - break; - case 4: - case 12: - StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, - StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_NOT_CHARGING - /* charging_state */); - break; - case 5: - case 13: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, i /* uid */, - StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF /* state */); - } - break; - case 6: - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_ON /* display_state */); - break; - case 7: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */, - StatsLog.AUDIO_STATE_CHANGED__STATE__ON /* state */); - } - break; - case 14: - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF /* display_state */); - break; - case 15: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */, - StatsLog.AUDIO_STATE_CHANGED__STATE__OFF /* state */); - } - break; - default: - } - mCursor++; - if (mCursor > 15) { - mCursor = 0; - } - } - - /** - * Properly finishes in order to be close all conditions and durations. - */ - public void finish() { - // Screen goes back to off. This will ensure that conditions get back to false. - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF /* display_state */); - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */, - StatsLog.AUDIO_STATE_CHANGED__STATE__OFF /* state */); - } - // Stop charging, to ensure the corresponding durations are closed. - StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, - StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_NOT_CHARGING - /* charging_state */); - // Stop scanning GPS, to ensure the corresponding conditions get back to false. - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, i /* uid */, - StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF /* state */); - } - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java deleted file mode 100644 index 3939e7e0b2fa..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.content.Context; -import com.android.os.StatsLog.StatsdStatsReport; -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -public class StatsdStatsRecorder extends PerfDataRecorder { - private static final String TAG = "loadtest.StatsdStatsRecorder"; - - private final LoadtestActivity mLoadtestActivity; - - public StatsdStatsRecorder(LoadtestActivity loadtestActivity, boolean placebo, int replication, - TimeUnit bucket, long periodSecs, int burst, boolean includeCountMetric, - boolean includeDurationMetric, boolean includeEventMetric, boolean includeValueMetric, - boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - mLoadtestActivity = loadtestActivity; - } - - @Override - public void startRecording(Context context) { - // Nothing to do. - } - - @Override - public void onAlarm(Context context) { - // Nothing to do. - } - - @Override - public void stopRecording(Context context) { - StatsdStatsReport metadata = mLoadtestActivity.getMetadata(); - if (metadata != null) { - int numConfigs = metadata.getConfigStatsCount(); - StringBuilder sb = new StringBuilder(); - StatsdStatsReport.ConfigStats configStats = metadata.getConfigStats(numConfigs - 1); - sb.append("metric_count,") - .append(configStats.getMetricCount() + "\n") - .append("condition_count,") - .append(configStats.getConditionCount() + "\n") - .append("matcher_count,") - .append(configStats.getMatcherCount() + "\n"); - writeData(context, "statsdstats_", "stat,value", sb); - } - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java deleted file mode 100644 index d9f0ca9d2461..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.content.Context; -import android.util.Log; -import com.android.os.StatsLog.ConfigMetricsReport; -import com.android.os.StatsLog.EventMetricData; -import com.android.os.StatsLog.StatsLogReport; -import com.android.internal.os.StatsdConfigProto.TimeUnit; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Checks the correctness of the stats. - */ -public class ValidationRecorder extends PerfDataRecorder { - private static final String TAG = "loadtest.ValidationRecorder"; - - private final LoadtestActivity mLoadtestActivity; - - public ValidationRecorder(LoadtestActivity loadtestActivity, boolean placebo, int replication, - TimeUnit bucket, long periodSecs, int burst, boolean includeCountMetric, - boolean includeDurationMetric, boolean includeEventMetric, boolean includeValueMetric, - boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - mLoadtestActivity = loadtestActivity; - } - - @Override - public void startRecording(Context context) { - // Nothing to do. - } - - @Override - public void onAlarm(Context context) { - validateData(); - } - - @Override - public void stopRecording(Context context) { - validateData(); - } - - private void validateData() { - // The code below is commented out because it calls getData, which has the side-effect - // of clearing statsd's data buffer. - /* - List<ConfigMetricsReport> reports = mLoadtestActivity.getData(); - if (reports != null) { - Log.d(TAG, "GOT DATA"); - for (ConfigMetricsReport report : reports) { - for (StatsLogReport logReport : report.getMetricsList()) { - if (!logReport.hasMetricId()) { - Log.e(TAG, "Metric missing name."); - } - } - } - } - */ - } - - private void validateEventBatteryLevelChanges(StatsLogReport logReport) { - Log.d(TAG, "Validating " + logReport.getMetricId()); - if (logReport.hasEventMetrics()) { - Log.d(TAG, "Num events captured: " + logReport.getEventMetrics().getDataCount()); - for (EventMetricData data : logReport.getEventMetrics().getDataList()) { - Log.d(TAG, " Event : " + data.getAtom()); - } - } else { - Log.d(TAG, "Metric is invalid"); - } - } - - private void validateEventBatteryLevelChangesWhileScreenIsOn(StatsLogReport logReport) { - Log.d(TAG, "Validating " + logReport.getMetricId()); - } -} |