1#!/usr/bin/env python3 2# 3# Copyright (C) 2021 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import os 18import time 19 20from simpleperf_utils import log_info, remove 21from . test_utils import TestBase, TestHelper 22 23 24class TestApiProfiler(TestBase): 25 def run_api_test(self, package_name, apk_name, expected_reports, min_android_version): 26 adb = TestHelper.adb 27 if TestHelper.android_version < ord(min_android_version) - ord('L') + 5: 28 log_info('skip this test on Android < %s.' % min_android_version) 29 return 30 # step 1: Prepare profiling. 31 self.run_cmd(['api_profiler.py', 'prepare']) 32 # step 2: Install and run the app. 33 apk_path = TestHelper.testdata_path(apk_name) 34 adb.run(['uninstall', package_name]) 35 adb.check_run(['install', '-t', apk_path]) 36 # Without sleep, the activity may be killed by post install intent ACTION_PACKAGE_CHANGED. 37 time.sleep(3) 38 adb.check_run(['shell', 'am', 'start', '-n', package_name + '/.MainActivity']) 39 # step 3: Wait until the app exits. 40 time.sleep(4) 41 while True: 42 result = adb.run(['shell', 'pidof', package_name]) 43 if not result: 44 break 45 time.sleep(1) 46 # step 4: Collect recording data. 47 remove('simpleperf_data') 48 self.run_cmd(['api_profiler.py', 'collect', '-p', package_name, '-o', 'simpleperf_data']) 49 # step 5: Check recording data. 50 names = os.listdir('simpleperf_data') 51 self.assertGreater(len(names), 0) 52 for name in names: 53 path = os.path.join('simpleperf_data', name) 54 remove('report.txt') 55 self.run_cmd(['report.py', '-g', '-o', 'report.txt', '-i', path]) 56 self.check_strings_in_file('report.txt', expected_reports) 57 # step 6: Clean up. 58 adb.check_run(['uninstall', package_name]) 59 60 def run_cpp_api_test(self, apk_name, min_android_version): 61 self.run_api_test('simpleperf.demo.cpp_api', apk_name, ['BusyThreadFunc'], 62 min_android_version) 63 64 def test_cpp_api_on_a_debuggable_app_targeting_prev_q(self): 65 # The source code of the apk is in simpleperf/demo/CppApi (with a small change to exit 66 # after recording). 67 self.run_cpp_api_test('cpp_api-debug_prev_Q.apk', 'N') 68 69 def test_cpp_api_on_a_debuggable_app_targeting_q(self): 70 self.run_cpp_api_test('cpp_api-debug_Q.apk', 'N') 71 72 def test_cpp_api_on_a_profileable_app_targeting_prev_q(self): 73 # a release apk with <profileable android:shell="true" /> 74 self.run_cpp_api_test('cpp_api-profile_prev_Q.apk', 'Q') 75 76 def test_cpp_api_on_a_profileable_app_targeting_q(self): 77 self.run_cpp_api_test('cpp_api-profile_Q.apk', 'Q') 78 79 def run_java_api_test(self, apk_name, min_android_version): 80 self.run_api_test('simpleperf.demo.java_api', apk_name, 81 ['simpleperf.demo.java_api.MainActivity', 'java.lang.Thread.run'], 82 min_android_version) 83 84 def test_java_api_on_a_debuggable_app_targeting_prev_q(self): 85 # The source code of the apk is in simpleperf/demo/JavaApi (with a small change to exit 86 # after recording). 87 self.run_java_api_test('java_api-debug_prev_Q.apk', 'P') 88 89 def test_java_api_on_a_debuggable_app_targeting_q(self): 90 self.run_java_api_test('java_api-debug_Q.apk', 'P') 91 92 def test_java_api_on_a_profileable_app_targeting_prev_q(self): 93 # a release apk with <profileable android:shell="true" /> 94 self.run_java_api_test('java_api-profile_prev_Q.apk', 'Q') 95 96 def test_java_api_on_a_profileable_app_targeting_q(self): 97 self.run_java_api_test('java_api-profile_Q.apk', 'Q') 98