blob: e48881a4530002fb795c03055ffba5c02c338f28 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (C) 2023 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 a
#
# 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.
from python.generators.diff_tests.testing import Path, DataPath, Metric
from python.generators.diff_tests.testing import Csv, Json, TextProto
from python.generators.diff_tests.testing import DiffTestBlueprint
from python.generators.diff_tests.testing import TestSuite
class Android(TestSuite):
def test_android_system_property_counter(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
timestamp: 1000
android_system_property {
values {
name: "debug.tracing.screen_state"
value: "2"
}
values {
name: "debug.tracing.device_state"
value: "some_state_from_sysprops"
}
}
}
packet {
ftrace_events {
cpu: 1
event {
timestamp: 2000
pid: 1
print {
buf: "C|1000|ScreenState|1\n"
}
}
event {
timestamp: 3000
pid: 1
print {
buf: "N|1000|DeviceStateChanged|some_state_from_atrace\n"
}
}
}
}
"""),
query="""
SELECT t.type, t.name, c.id, c.ts, c.type, c.value
FROM counter_track t JOIN counter c ON t.id = c.track_id
WHERE name = 'ScreenState';
""",
out=Csv("""
"type","name","id","ts","type","value"
"counter_track","ScreenState",0,1000,"counter",2.000000
"counter_track","ScreenState",1,2000,"counter",1.000000
"""))
def test_android_system_property_slice(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
timestamp: 1000
android_system_property {
values {
name: "debug.tracing.screen_state"
value: "2"
}
values {
name: "debug.tracing.device_state"
value: "some_state_from_sysprops"
}
}
}
packet {
ftrace_events {
cpu: 1
event {
timestamp: 2000
pid: 1
print {
buf: "C|1000|ScreenState|1\n"
}
}
event {
timestamp: 3000
pid: 1
print {
buf: "N|1000|DeviceStateChanged|some_state_from_atrace\n"
}
}
}
}
"""),
query="""
SELECT t.type, t.name, s.id, s.ts, s.dur, s.type, s.name
FROM track t JOIN slice s ON s.track_id = t.id
WHERE t.name = 'DeviceStateChanged';
""",
out=Path('android_system_property_slice.out'))
def test_android_battery_stats_event_slices(self):
# The following has three events
# * top (123, mail) from 1000 to 9000 explicit
# * job (456, mail_job) starting at 3000 (end is inferred as trace end)
# * job (789, video_job) ending at 4000 (start is inferred as trace start)
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
ftrace_events {
cpu: 1
event {
timestamp: 1000
pid: 1
print {
buf: "N|1000|battery_stats.top|+top=123:\"mail\"\n"
}
}
event {
timestamp: 3000
pid: 1
print {
buf: "N|1000|battery_stats.job|+job=456:\"mail_job\"\n"
}
}
event {
timestamp: 4000
pid: 1
print {
buf: "N|1000|battery_stats.job|-job=789:\"video_job\"\n"
}
}
event {
timestamp: 9000
pid: 1
print {
buf: "N|1000|battery_stats.top|-top=123:\"mail\"\n"
}
}
}
}
"""),
query="""
SELECT IMPORT('android.battery_stats');
SELECT * FROM android_battery_stats_event_slices
ORDER BY str_value;
""",
out=Path('android_battery_stats_event_slices.out'))
def test_android_battery_stats_counters(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
ftrace_events {
cpu: 1
event {
timestamp: 1000
pid: 1
print {
buf: "C|1000|battery_stats.data_conn|13\n"
}
}
event {
timestamp: 4000
pid: 1
print {
buf: "C|1000|battery_stats.data_conn|20\n"
}
}
event {
timestamp: 1000
pid: 1
print {
buf: "C|1000|battery_stats.audio|1\n"
}
}
}
}
"""),
query="""
SELECT IMPORT('android.battery_stats');
SELECT * FROM android_battery_stats_state
ORDER BY ts, track_name;
""",
out=Path('android_battery_stats_state.out'))
def test_android_network_activity(self):
# The following should have three activity regions:
# * uid=123 from 1000 to 2010 (note: end is max(ts)+idle_ns)
# * uid=456 from 1005 to 3115 (note: doesn't group with above due to name)
# * Also tests that groups form based on (ts+dur), not just start ts.
# * uid=123 from 3000 to 5500 (note: gap between 1010 to 3000 > idle_ns)
# Note: packet_timestamps are delta encoded from the base timestamp.
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
timestamp: 0
network_packet_bundle {
ctx {
direction: DIR_EGRESS
interface: "wlan"
uid: 123
}
packet_timestamps: [
1000, 1010,
3000, 3050, 4000, 4500
],
packet_lengths: [
50, 50,
50, 50, 50, 50
],
}
}
packet {
timestamp: 1005
network_packet_bundle {
ctx {
direction: DIR_EGRESS
interface: "wlan"
uid: 456
}
total_duration: 100
total_packets: 2
total_length: 300
}
}
packet {
timestamp: 2015
network_packet_bundle {
ctx {
direction: DIR_EGRESS
interface: "wlan"
uid: 456
}
total_duration: 100
total_packets: 1
total_length: 50
}
}
packet {
timestamp: 0
network_packet_bundle {
ctx {
direction: DIR_INGRESS
interface: "loopback"
uid: 123
}
packet_timestamps: [6000]
packet_lengths: [100]
}
}
"""),
query="""
SELECT RUN_METRIC(
'android/network_activity_template.sql',
'view_name', 'android_network_activity',
'group_by', 'package_name',
'filter', 'iface = "wlan"',
'idle_ns', '1000',
'quant_ns', '100'
);
SELECT * FROM android_network_activity
ORDER BY package_name, ts;
""",
out=Path('android_network_activity.out'))
def test_binder_sync_binder_metrics(self):
return DiffTestBlueprint(
trace=DataPath('android_binder_metric_trace.atr'),
query="""
SELECT IMPORT('android.binder');
SELECT
aidl_name,
binder_txn_id,
client_process,
client_thread,
client_upid,
client_utid,
client_tid,
is_main_thread,
client_ts,
client_dur,
binder_reply_id,
server_process,
server_thread,
server_upid,
server_utid,
server_tid,
server_ts,
server_dur
FROM android_sync_binder_metrics_by_txn
WHERE binder_txn_id = 34382
ORDER BY client_ts
LIMIT 1;
""",
out=Csv("""
"aidl_name","binder_txn_id","client_process","client_thread","client_upid","client_utid","client_tid","is_main_thread","client_ts","client_dur","binder_reply_id","server_process","server_thread","server_upid","server_utid","server_tid","server_ts","server_dur"
"AIDL::java::ISensorPrivacyManager::isSensorPrivacyEnabled::server",34382,"/system/bin/audioserver","audioserver",281,281,492,1,25505818197,3125407,34383,"system_server","binder:641_4",311,539,1596,25505891588,3000749
"""))
def test_binder_sync_binder_thread_state(self):
return DiffTestBlueprint(
trace=DataPath('android_binder_metric_trace.atr'),
query="""
SELECT IMPORT('android.binder');
SELECT
binder_txn_id,
client_ts,
client_tid,
binder_reply_id,
server_ts,
server_tid,
thread_state_type,
thread_state,
thread_state_dur,
thread_state_count
FROM android_sync_binder_thread_state_by_txn
WHERE binder_txn_id = 34382
ORDER BY thread_state_dur;
""",
out=Csv("""
"binder_txn_id","client_ts","client_tid","binder_reply_id","server_ts","server_tid","thread_state_type","thread_state","thread_state_dur","thread_state_count"
34382,25505818197,492,34383,25505891588,1596,"binder_reply","R+",10030,1
34382,25505818197,492,34383,25505891588,1596,"binder_txn","Running",26597,2
34382,25505818197,492,34383,25505891588,1596,"binder_txn","R",38947,1
34382,25505818197,492,34383,25505891588,1596,"binder_reply","Running",533663,3
34382,25505818197,492,34383,25505891588,1596,"binder_reply","D",864664,1
34382,25505818197,492,34383,25505891588,1596,"binder_reply","R",1592392,1
34382,25505818197,492,34383,25505891588,1596,"binder_txn","S",3059863,1
"""))
def test_binder_sync_binder_blocked_function(self):
return DiffTestBlueprint(
trace=DataPath('android_binder_metric_trace.atr'),
query="""
SELECT IMPORT('android.binder');
SELECT
binder_txn_id,
client_ts,
client_tid,
binder_reply_id,
server_ts,
server_tid,
thread_state_type,
blocked_function,
blocked_function_dur,
blocked_function_count
FROM android_sync_binder_blocked_functions_by_txn
WHERE binder_txn_id = 34382
ORDER BY blocked_function_dur;
""",
out=Csv("""
"binder_txn_id","client_ts","client_tid","binder_reply_id","server_ts","server_tid","thread_state_type","blocked_function","blocked_function_dur","blocked_function_count"
34382,25505818197,492,34383,25505891588,1596,"binder_reply","filemap_fault",864664,1
"""))
def test_binder_metric(self):
return DiffTestBlueprint(
trace=DataPath('android_binder_metric_trace.atr'),
query=Metric('android_binder'),
out=Path('android_binder_metric.out'))
def test_android_blocking_calls_cuj(self):
return DiffTestBlueprint(
trace=Path('android_blocking_calls_cuj_metric.py'),
query=Metric('android_blocking_calls_cuj_metric'),
out=Path('android_blocking_calls_cuj_metric.out'))
def test_android_blocking_calls_on_jank_cujs(self):
return DiffTestBlueprint(
trace=Path('../graphics/android_jank_cuj.py'),
query=Metric('android_blocking_calls_cuj_metric'),
out=Path('android_blocking_calls_on_jank_cuj_metric.out'))
def test_android_slices_standardization_for_aggregation(self):
return DiffTestBlueprint(
trace=Path('android_slice_standardization.py'),
query="""
SELECT IMPORT('android.slices');
SELECT ANDROID_STANDARDIZE_SLICE_NAME(slice.name) name
FROM slice
ORDER BY name;
""",
out=Path('android_slice_standardization.out'))
def test_android_sysui_notifications_blocking_calls(self):
return DiffTestBlueprint(
trace=Path('android_sysui_notifications_blocking_calls_metric.py'),
query=Metric('android_sysui_notifications_blocking_calls_metric'),
out=Path('android_sysui_notifications_blocking_calls_metric.out'))
def test_monitor_contention_extraction(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query="""
SELECT IMPORT('android.monitor_contention');
SELECT
blocking_method,
blocked_method,
short_blocking_method,
short_blocked_method
FROM android_monitor_contention
WHERE binder_reply_id IS NOT NULL
ORDER BY dur DESC
LIMIT 1;
""",
out=Csv("""
"blocking_method","blocked_method","short_blocking_method","short_blocked_method"
"boolean com.android.server.am.ActivityManagerService.forceStopPackageLocked(java.lang.String, int, boolean, boolean, boolean, boolean, boolean, int, java.lang.String)","boolean com.android.server.am.ActivityManagerService.isUidActive(int, java.lang.String)","com.android.server.am.ActivityManagerService.forceStopPackageLocked","com.android.server.am.ActivityManagerService.isUidActive"
"""))
def test_monitor_contention_chain_blocked_functions(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query="""
SELECT IMPORT('android.monitor_contention');
SELECT
*
FROM android_monitor_contention_chain_blocked_functions_by_txn
WHERE id = 13934
ORDER BY blocked_function_dur;
""",
out=Csv("""
"id","blocked_function","blocked_function_dur","blocked_function_count"
13934,"blkdev_issue_flush",11950576,1
"""))
def test_monitor_contention_chain_thread_states(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query="""
SELECT IMPORT('android.monitor_contention');
SELECT
*
FROM android_monitor_contention_chain_thread_state_by_txn
WHERE id = 13934
ORDER BY thread_state_dur;
""",
out=Csv("""
"id","thread_state","thread_state_dur","thread_state_count"
13934,"R+",7649,1
13934,"R",300606,3
13934,"Running",649961,3
13934,"D",11950576,1
"""))
def test_monitor_contention_chain_extraction_parent(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query="""
SELECT IMPORT('android.monitor_contention');
SELECT * FROM android_monitor_contention_chain
WHERE parent_id IS NOT NULL
ORDER BY dur DESC
LIMIT 1;
""",
out=Csv("""
"parent_id","blocking_method","blocked_method","short_blocking_method","short_blocked_method","blocking_src","blocked_src","waiter_count","blocked_utid","blocked_thread_name","blocking_utid","blocking_thread_name","blocking_tid","upid","process_name","id","ts","dur","track_id","is_blocked_thread_main","blocked_thread_tid","is_blocking_thread_main","blocking_thread_tid","binder_reply_id","binder_reply_ts","binder_reply_tid","pid"
956,"void com.android.server.am.AppProfiler.collectPssInBackground()","void com.android.server.am.ProcessRecord.setPid(int)","com.android.server.am.AppProfiler.collectPssInBackground","com.android.server.am.ProcessRecord.setPid","AppProfiler.java:514","ProcessRecord.java:596",0,656,"binder:642_12",506,"android.bg",670,250,"system_server",949,1737122781871,7301144,1236,0,2720,0,670,"[NULL]","[NULL]","[NULL]",642
"""))
def test_monitor_contention_metric(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query=Metric('android_monitor_contention'),
out=Path('android_monitor_contention.out'))
def test_thread_creation_spam(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query="""
SELECT IMPORT('android.thread');
SELECT * FROM ANDROID_THREAD_CREATION_SPAM(1e9, 1e9);
""",
out=Csv("""
"process_name","pid","thread_name_prefix","max_count_per_sec"
"com.android.providers.media.module",3487,"SharedPreferenc",3
"com.android.providers.media.module",3487,"MediaCodec_loop",2
"/apex/com.android.adbd/bin/adbd",527,"shell",1
"media.swcodec",563,"id.hevc.decoder",1
"system_server",642,"Thread",1
"sh",3474,"sh",1
"sh",3476,"sh",1
"sh",3478,"sh",1
"am",3480,"am",1
"cmd",3482,"binder",1
"cmd",3482,"cmd",1
"com.android.providers.media.module",3487,"CodecLooper",1
"sh",3517,"sh",1
"sgdisk",3521,"sgdisk",1
"blkid",3523,"blkid",1
"binder:243_4",3524,"binder",1
"fsck_msdos",3525,"fsck_msdos",1
"binder:243_4",3526,"binder",1
"sh",3532,"sh",1
"cut",3534,"cut",1
"sh",3536,"sh",1
"sh",3544,"sh",1
"sh",3546,"sh",1
"sh",3564,"sh",1
"""))