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 logging 18import os 19import time 20 21from simpleperf_utils import remove 22from . test_utils import TestBase, TestHelper 23 24 25class TestApiProfiler(TestBase): 26 def run_api_test(self, package_name, apk_name, expected_reports, min_android_version: int): 27 adb = TestHelper.adb 28 if TestHelper.android_version < min_android_version: 29 logging.info('skip this test on Android < %s.' % min_android_version) 30 return 31 # step 1: Install and run the app. 32 apk_path = TestHelper.testdata_path(apk_name) 33 adb.run(['uninstall', package_name]) 34 adb.check_run(['install', '-t', apk_path]) 35 # Without sleep, the activity may be killed by post install intent ACTION_PACKAGE_CHANGED. 36 time.sleep(3) 37 # step 2: Prepare profiling. 38 self.run_cmd(['api_profiler.py', 'prepare', '-p', package_name, '-d', '1']) 39 if TestHelper.android_version >= 13: 40 # Enable perf_harden to check if profile_app_uid property works. 41 adb.set_property('security.perf_harden', '1') 42 adb.check_run(['shell', 'am', 'start', '-n', package_name + '/.MainActivity']) 43 # step 3: Wait until the app exits. 44 time.sleep(4) 45 while True: 46 result = adb.run(['shell', 'pidof', package_name]) 47 if not result: 48 break 49 time.sleep(1) 50 # step 4: Collect recording data. 51 remove('simpleperf_data') 52 self.run_cmd(['api_profiler.py', 'collect', '-p', package_name, '-o', 'simpleperf_data']) 53 # step 5: Check recording data. 54 names = os.listdir('simpleperf_data') 55 self.assertGreater(len(names), 0) 56 for name in names: 57 path = os.path.join('simpleperf_data', name) 58 remove('report.txt') 59 self.run_cmd(['report.py', '-g', '-o', 'report.txt', '-i', path]) 60 self.check_strings_in_file('report.txt', expected_reports) 61 # step 6: Clean up. 62 adb.check_run(['uninstall', package_name]) 63 64 def run_cpp_api_test(self, apk_name, min_android_version): 65 self.run_api_test('simpleperf.demo.cpp_api', apk_name, ['BusyThreadFunc'], 66 min_android_version) 67 68 def test_cpp_api_on_a_debuggable_app(self): 69 # The source code of the apk is in simpleperf/demo/CppApi. 70 self.run_cpp_api_test('cpp_api-debuggable.apk', 7) 71 72 def test_cpp_api_on_a_profileable_app(self): 73 # a release apk with <profileable android:shell="true" /> 74 self.run_cpp_api_test('cpp_api-profileable.apk', 10) 75 76 def run_java_api_test(self, apk_name, min_android_version): 77 self.run_api_test('simpleperf.demo.java_api', apk_name, 78 ['simpleperf.demo.java_api.MainActivity', 'java.lang.Thread.run'], 79 min_android_version) 80 81 def test_java_api_on_a_debuggable_app(self): 82 # The source code of the apk is in simpleperf/demo/JavaApi. 83 self.run_java_api_test('java_api-debuggable.apk', 9) 84 85 def test_java_api_on_a_profileable_app(self): 86 # a release apk with <profileable android:shell="true" /> 87 self.run_java_api_test('java_api-profileable.apk', 10) 88