diff options
119 files changed, 2453 insertions, 2110 deletions
diff --git a/build/tasks/tests/native_test_list.mk b/build/tasks/tests/native_test_list.mk index 08b348cf2..28b73c3d6 100644 --- a/build/tasks/tests/native_test_list.mk +++ b/build/tasks/tests/native_test_list.mk @@ -14,22 +14,21 @@ native_tests := \ adbd_test \ - android_logger_device_test_src_lib \ - android_logger_device_test_tests_config_log_level \ - android_logger_device_test_tests_default_init \ - android_logger_device_test_tests_multiple_init \ - anyhow_device_test_src_lib \ - anyhow_device_test_tests_test_autotrait \ - anyhow_device_test_tests_test_boxed \ - anyhow_device_test_tests_test_chain \ - anyhow_device_test_tests_test_context \ - anyhow_device_test_tests_test_convert \ - anyhow_device_test_tests_test_downcast \ - anyhow_device_test_tests_test_ffi \ - anyhow_device_test_tests_test_fmt \ - anyhow_device_test_tests_test_macros \ - anyhow_device_test_tests_test_repr \ - anyhow_device_test_tests_test_source \ + android_logger_test_src_lib \ + android_logger_test_tests_config_log_level \ + android_logger_test_tests_default_init \ + android_logger_test_tests_multiple_init \ + anyhow_test_src_lib \ + anyhow_test_tests_test_autotrait \ + anyhow_test_tests_test_boxed \ + anyhow_test_tests_test_chain \ + anyhow_test_tests_test_context \ + anyhow_test_tests_test_convert \ + anyhow_test_tests_test_downcast \ + anyhow_test_tests_test_fmt \ + anyhow_test_tests_test_macros \ + anyhow_test_tests_test_repr \ + anyhow_test_tests_test_source \ audio_health_tests \ backtrace_test \ bionic-unit-tests \ @@ -65,13 +64,14 @@ native_tests := \ inputflinger_tests \ installd_cache_test \ installd_dexopt_test \ + installd_file_test \ installd_otapreopt_test \ installd_service_test \ installd_utils_test \ keystore2_crypto_test_rust \ keystore2_selinux_test \ keystore2_test \ - lazy_static_device_test_tests_test \ + lazy_static_test_tests_test \ libandroidfw_tests \ libappfuse_test \ libbase_test \ @@ -85,7 +85,7 @@ native_tests := \ liblog-unit-tests \ libminijail_unittest_gtest \ libnativehelper_tests \ - libnetdbpf_test \ + libnetworkstats_test \ libprocinfo_test \ libtextclassifier_tests \ libsurfaceflinger_unittest \ @@ -134,100 +134,98 @@ native_tests := \ resolv_gold_test \ resolv_integration_test \ resolv_unit_test \ - ring_device_test_src_lib \ - ring_device_test_tests_aead_tests \ - ring_device_test_tests_agreement_tests \ - ring_device_test_tests_constant_time_tests \ - ring_device_test_tests_digest_tests \ - ring_device_test_tests_ecdsa_tests \ - ring_device_test_tests_ed25519_tests \ - ring_device_test_tests_hkdf_tests \ - ring_device_test_tests_hmac_tests \ - ring_device_test_tests_pbkdf2_tests \ - ring_device_test_tests_quic_tests \ - ring_device_test_tests_rand_tests \ - ring_device_test_tests_rsa_tests \ - ring_device_test_tests_signature_tests \ + ring_test_src_lib \ + ring_test_tests_aead_tests \ + ring_test_tests_agreement_tests \ + ring_test_tests_constant_time_tests \ + ring_test_tests_digest_tests \ + ring_test_tests_ecdsa_tests \ + ring_test_tests_ed25519_tests \ + ring_test_tests_hkdf_tests \ + ring_test_tests_hmac_tests \ + ring_test_tests_pbkdf2_tests \ + ring_test_tests_quic_tests \ + ring_test_tests_rand_tests \ + ring_test_tests_rsa_tests \ + ring_test_tests_signature_tests \ scrape_mmap_addr \ simpleperf_cpu_hotplug_test \ simpleperf_unit_test \ statsd_test \ syscall_filter_unittest_gtest \ time-unit-tests \ - tokio_device_test_tests__require_full \ - tokio_device_test_tests_buffered \ - tokio_device_test_tests_io_async_fd \ - tokio_device_test_tests_io_async_read \ - tokio_device_test_tests_io_chain \ - tokio_device_test_tests_io_copy \ - tokio_device_test_tests_io_copy_bidirectional \ - tokio_device_test_tests_io_driver \ - tokio_device_test_tests_io_driver_drop \ - tokio_device_test_tests_io_lines \ - tokio_device_test_tests_io_mem_stream \ - tokio_device_test_tests_io_read \ - tokio_device_test_tests_io_read_buf \ - tokio_device_test_tests_io_read_exact \ - tokio_device_test_tests_io_read_line \ - tokio_device_test_tests_io_read_to_end \ - tokio_device_test_tests_io_read_to_string \ - tokio_device_test_tests_io_read_until \ - tokio_device_test_tests_io_split \ - tokio_device_test_tests_io_take \ - tokio_device_test_tests_io_write \ - tokio_device_test_tests_io_write_all \ - tokio_device_test_tests_io_write_buf \ - tokio_device_test_tests_io_write_int \ - tokio_device_test_tests_macros_join \ - tokio_device_test_tests_macros_pin \ - tokio_device_test_tests_macros_select \ - tokio_device_test_tests_macros_test \ - tokio_device_test_tests_macros_try_join \ - tokio_device_test_tests_net_bind_resource \ - tokio_device_test_tests_net_lookup_host \ - tokio_device_test_tests_no_rt \ - tokio_device_test_tests_process_kill_on_drop \ - tokio_device_test_tests_rt_basic \ - tokio_device_test_tests_rt_common \ - tokio_device_test_tests_rt_threaded \ - tokio_device_test_tests_sync_barrier \ - tokio_device_test_tests_sync_broadcast \ - tokio_device_test_tests_sync_errors \ - tokio_device_test_tests_sync_mpsc \ - tokio_device_test_tests_sync_mutex \ - tokio_device_test_tests_sync_mutex_owned \ - tokio_device_test_tests_sync_notify \ - tokio_device_test_tests_sync_oneshot \ - tokio_device_test_tests_sync_rwlock \ - tokio_device_test_tests_sync_semaphore \ - tokio_device_test_tests_sync_semaphore_owned \ - tokio_device_test_tests_sync_watch \ - tokio_device_test_tests_task_abort \ - tokio_device_test_tests_task_blocking \ - tokio_device_test_tests_task_local \ - tokio_device_test_tests_task_local_set \ - tokio_device_test_tests_tcp_accept \ - tokio_device_test_tests_tcp_connect \ - tokio_device_test_tests_tcp_echo \ - tokio_device_test_tests_tcp_into_split \ - tokio_device_test_tests_tcp_into_std \ - tokio_device_test_tests_tcp_peek \ - tokio_device_test_tests_tcp_shutdown \ - tokio_device_test_tests_tcp_socket \ - tokio_device_test_tests_tcp_split \ - tokio_device_test_tests_time_rt \ - tokio_device_test_tests_udp \ - tokio_device_test_tests_uds_cred \ - tokio_device_test_tests_uds_split \ - tokio-test_device_test_src_lib \ - tokio-test_device_test_tests_block_on \ - tokio-test_device_test_tests_io \ - tokio-test_device_test_tests_macros \ - unicode-xid_device_test_src_lib \ + tokio_test_tests__require_full \ + tokio_test_tests_buffered \ + tokio_test_tests_io_async_fd \ + tokio_test_tests_io_async_read \ + tokio_test_tests_io_chain \ + tokio_test_tests_io_copy \ + tokio_test_tests_io_copy_bidirectional \ + tokio_test_tests_io_driver \ + tokio_test_tests_io_driver_drop \ + tokio_test_tests_io_lines \ + tokio_test_tests_io_mem_stream \ + tokio_test_tests_io_read \ + tokio_test_tests_io_read_buf \ + tokio_test_tests_io_read_exact \ + tokio_test_tests_io_read_line \ + tokio_test_tests_io_read_to_end \ + tokio_test_tests_io_read_to_string \ + tokio_test_tests_io_read_until \ + tokio_test_tests_io_split \ + tokio_test_tests_io_take \ + tokio_test_tests_io_write \ + tokio_test_tests_io_write_all \ + tokio_test_tests_io_write_buf \ + tokio_test_tests_io_write_int \ + tokio_test_tests_macros_join \ + tokio_test_tests_macros_pin \ + tokio_test_tests_macros_select \ + tokio_test_tests_macros_test \ + tokio_test_tests_macros_try_join \ + tokio_test_tests_net_bind_resource \ + tokio_test_tests_net_lookup_host \ + tokio_test_tests_no_rt \ + tokio_test_tests_process_kill_on_drop \ + tokio_test_tests_rt_basic \ + tokio_test_tests_rt_common \ + tokio_test_tests_rt_threaded \ + tokio_test_tests_sync_barrier \ + tokio_test_tests_sync_broadcast \ + tokio_test_tests_sync_errors \ + tokio_test_tests_sync_mpsc \ + tokio_test_tests_sync_mutex \ + tokio_test_tests_sync_mutex_owned \ + tokio_test_tests_sync_notify \ + tokio_test_tests_sync_oneshot \ + tokio_test_tests_sync_rwlock \ + tokio_test_tests_sync_semaphore \ + tokio_test_tests_sync_semaphore_owned \ + tokio_test_tests_sync_watch \ + tokio_test_tests_task_abort \ + tokio_test_tests_task_blocking \ + tokio_test_tests_task_local \ + tokio_test_tests_task_local_set \ + tokio_test_tests_tcp_accept \ + tokio_test_tests_tcp_connect \ + tokio_test_tests_tcp_echo \ + tokio_test_tests_tcp_into_split \ + tokio_test_tests_tcp_into_std \ + tokio_test_tests_tcp_peek \ + tokio_test_tests_tcp_shutdown \ + tokio_test_tests_tcp_socket \ + tokio_test_tests_tcp_split \ + tokio_test_tests_time_rt \ + tokio_test_tests_udp \ + tokio_test_tests_uds_cred \ + tokio_test_tests_uds_split \ + tokio-test_test_tests_block_on \ + tokio-test_test_tests_io \ + tokio-test_test_tests_macros \ + unicode-xid_test_src_lib \ update_engine_unittests \ - url_device_test_src_lib \ - url_device_test_tests_data \ - url_device_test_tests_unit \ + url_test_tests_data \ + url_test_tests_unit \ vintf_object_test \ wificond_unit_test \ ziparchive-tests \ diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java index a25324da5..81e72efe5 100644 --- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java +++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java @@ -16,8 +16,7 @@ package android.platform.helpers; - -public interface IAutoDialHelper extends IAppHelper { +public interface IAutoDialHelper extends IAppHelper, Scrollable { /** enum class for contact list order type. */ enum OrderType { diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoHomeHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoHomeHelper.java index 2f67107e9..e7ed90b07 100644 --- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoHomeHelper.java +++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoHomeHelper.java @@ -38,4 +38,9 @@ public interface IAutoHomeHelper extends IAppHelper { * <p>Checks if exists a assistant widget. */ boolean hasAssistantWidget(); + + /** + * Opens Media Widget from home screen. + */ + void openMediaWidget(); } diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaHelper.java index 569c5a3b3..530fb46d9 100644 --- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaHelper.java +++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaHelper.java @@ -16,6 +16,8 @@ package android.platform.helpers; +import java.util.List; + public interface IAutoMediaHelper extends IAppHelper { /** * Setup expectations: media app is open @@ -128,4 +130,25 @@ public interface IAutoMediaHelper extends IAppHelper { * else returns false */ boolean isPlaying(); + + /** + * Setup expectations: Media app is open. + * + * @return Media App Title + */ + String getMediaAppTitle(); + + /** + * Setup expectations: Media app is open. + * Opens the drop down menu in the Media Apps + */ + void openMediaAppMenuItems(); + + /** + * Setup expectations: "Media apps" Grid is open. + * + * @param mediaAppsNames : List of media apps names + * @return true if all app names in mediaAppsNames shows up in Media Apps Grid + */ + boolean areMediaAppsPresent(List<String> mediaAppsNames); } diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoProfileHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoUserHelper.java index 6bff0c4e5..aed8fee33 100644 --- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoProfileHelper.java +++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoUserHelper.java @@ -16,49 +16,49 @@ package android.platform.helpers; -public interface IAutoProfileHelper extends IAppHelper { +public interface IAutoUserHelper extends IAppHelper { /** * Setup expectation: Profiles and Accounts setting is open. * * <p>This method is to add an a new user. */ - void addProfile(); + void addUser(); /** * Setup expectation: Profiles and Accounts setting is open. * * <p>This method is to add an a new user. */ - void addProfileQuickSettings(String userName); + void addUserQuickSettings(String userName); /** * Setup expectation: Profiles and Accounts setting is open. * * <p>This method is to delete an existing user. */ - void deleteProfile(String user); + void deleteUser(String user); /** * Setup expectation: Profiles and Accounts setting is open. * * <p>This method is to delete user's own profile. */ - void deleteCurrentProfile(); + void deleteCurrentUser(); /** * Setup expectation: Profiles and Accounts setting is open. * * <p>This method is to check if user already exists. */ - boolean isProfilePresent(String userName); + boolean isUserPresent(String userName); /** * Setup expectation: Profiles and Accounts setting is open. * * <p>This method is to switch between existing users. */ - void switchProfile(String userFrom, String userTo); + void switchUser(String userFrom, String userTo); /** * Setup expectation: Profiles and Accounts setting is open. diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/utility/Scrollable.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/utility/Scrollable.java index cc8f9a831..5c08e97cc 100644 --- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/utility/Scrollable.java +++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/utility/Scrollable.java @@ -29,6 +29,7 @@ import androidx.test.InstrumentationRegistry; */ public interface Scrollable { int DEFAULT_MARGIN = 5; + int DEFAULT_DURATION_MS = 1000; /** * Setup expectations: None @@ -50,6 +51,15 @@ public interface Scrollable { } /** + * Scroll up from the bottom of the scrollable region to top of the scrollable region (i.e. by + * one page). + */ + public default boolean scrollUpOnePage() { + scrollUpOnePage(DEFAULT_DURATION_MS); + return true; + } + + /** * Setup expectations: None. * * <p>Scroll up from the bottom of the scrollable region towards the top of the scrollable @@ -77,6 +87,15 @@ public interface Scrollable { } /** + * Scroll down from the top of the scrollable region to bottom of the scrollable region (i.e. by + * one page). + */ + public default boolean scrollDownOnePage() { + scrollDownOnePage(DEFAULT_DURATION_MS); + return true; + } + + /** * Setup expectations: None. * * <p>Scroll down from the top of the scrollable region towards the bottom of the scrollable diff --git a/libraries/automotive-helpers/home-helper/src/android/platform/helpers/HomeHelperImpl.java b/libraries/automotive-helpers/home-helper/src/android/platform/helpers/HomeHelperImpl.java index 5ed6713e1..15d87fb95 100644 --- a/libraries/automotive-helpers/home-helper/src/android/platform/helpers/HomeHelperImpl.java +++ b/libraries/automotive-helpers/home-helper/src/android/platform/helpers/HomeHelperImpl.java @@ -16,6 +16,7 @@ package android.platform.helpers; import android.app.Instrumentation; +import android.support.test.uiautomator.UiObject2; public class HomeHelperImpl extends AbstractAutoStandardAppHelper implements IAutoHomeHelper { @@ -52,6 +53,22 @@ public class HomeHelperImpl extends AbstractAutoStandardAppHelper implements IAu != null); } + @Override + public void openMediaWidget() { + pressHome(); + waitForIdle(); + UiObject2 mediaWidget = findUiObject( + getResourceFromConfig( + AutoConfigConstants.HOME, + AutoConfigConstants.HOME_VIEW, + AutoConfigConstants.BOTTOM_CARD)); + if (mediaWidget != null) { + clickAndWaitForIdleScreen(mediaWidget); + } else { + throw new IllegalStateException("Unable to find Media Widget on Home Screen."); + } + } + /** {@inheritDoc} */ @Override public void open() { diff --git a/libraries/automotive-helpers/media-center-app-helper/src/android/platform/helpers/MediaCenterHelperImpl.java b/libraries/automotive-helpers/media-center-app-helper/src/android/platform/helpers/MediaCenterHelperImpl.java index 9b5530dd3..93e6688a0 100644 --- a/libraries/automotive-helpers/media-center-app-helper/src/android/platform/helpers/MediaCenterHelperImpl.java +++ b/libraries/automotive-helpers/media-center-app-helper/src/android/platform/helpers/MediaCenterHelperImpl.java @@ -26,13 +26,14 @@ import android.os.SystemClock; import android.platform.helpers.exceptions.UnknownUiException; import android.support.test.uiautomator.By; import android.support.test.uiautomator.Direction; -import android.support.test.uiautomator.UiObject2; import android.support.test.uiautomator.UiObject; +import android.support.test.uiautomator.UiObject2; import android.support.test.uiautomator.UiObjectNotFoundException; import android.support.test.uiautomator.UiScrollable; import android.support.test.uiautomator.UiSelector; import java.util.List; +import java.util.regex.Pattern; public class MediaCenterHelperImpl extends AbstractAutoStandardAppHelper implements IAutoMediaHelper { @@ -343,7 +344,9 @@ public class MediaCenterHelperImpl extends AbstractAutoStandardAppHelper } } - /** Minimize the Now Playing window. */ + /** + * Minimize the Now Playing window. + */ private void minimizeNowPlaying() { UiObject2 trackNameText = findUiObject( @@ -383,4 +386,57 @@ public class MediaCenterHelperImpl extends AbstractAutoStandardAppHelper PlaybackState state = controllers.get(0).getPlaybackState(); return state.getState() == PlaybackState.STATE_PLAYING; } + + /** {@inheritDoc} */ + @Override + public String getMediaAppTitle() { + UiObject2 mediaAppTitle = findUiObject(getResourceFromConfig( + AutoConfigConstants.MEDIA_CENTER, + AutoConfigConstants.MEDIA_APP, + AutoConfigConstants.MEDIA_APP_TITLE)); + if (mediaAppTitle == null) { + throw new UnknownUiException("Unable to find Media app title text."); + } + return mediaAppTitle.getText(); + } + + /** {@inheritDoc} */ + @Override + public void openMediaAppMenuItems() { + List<UiObject2> menuItemElements = findUiObjects(getResourceFromConfig( + AutoConfigConstants.MEDIA_CENTER, + AutoConfigConstants.MEDIA_APP, + AutoConfigConstants.MEDIA_APP_DROP_DOWN_MENU)); + if (menuItemElements.size() == 0) { + throw new UnknownUiException("Unable to find Media drop down."); + } + clickAndWaitForIdleScreen(menuItemElements.get(1)); + } + + /** {@inheritDoc} */ + @Override + public boolean areMediaAppsPresent(List<String> mediaAppsNames) { + UiObject2 mediaAppPageTitle = + findUiObject( + getResourceFromConfig( + AutoConfigConstants.MEDIA_CENTER, + AutoConfigConstants.MEDIA_APPS_GRID, + AutoConfigConstants.MEDIA_APPS_GRID_TITLE)); + if (mediaAppPageTitle == null) { + throw new RuntimeException("Media apps grid activity not open."); + } + if (mediaAppsNames == null || mediaAppsNames.size() == 0) { + return false; + } + // Scroll and find media apps in Media App Grid + for (String expectedApp : mediaAppsNames) { + UiObject2 mediaApp = + scrollAndFindUiObject( + By.text(Pattern.compile(expectedApp, Pattern.CASE_INSENSITIVE))); + if (mediaApp == null || !mediaApp.getText().equals(expectedApp)) { + return false; + } + } + return true; + } } diff --git a/libraries/automotive-helpers/settings-app-helper/src/android/platform/helpers/SettingAccountsHelperImpl.java b/libraries/automotive-helpers/settings-app-helper/src/android/platform/helpers/SettingAccountsHelperImpl.java deleted file mode 100644 index 2f938078d..000000000 --- a/libraries/automotive-helpers/settings-app-helper/src/android/platform/helpers/SettingAccountsHelperImpl.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.helpers; - -import android.app.Instrumentation; -import android.os.SystemClock; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.UiObject2; - -/** Implementation of {@link IAutoAccountsHelper} to support tests of account settings */ -public class SettingAccountsHelperImpl extends AbstractAutoStandardAppHelper - implements IAutoAccountsHelper { - - // Wait Time - private static final int UI_RESPONSE_WAIT_MS = 5000; - - public SettingAccountsHelperImpl(Instrumentation instr) { - super(instr); - } - - /** {@inheritDoc} */ - @Override - public String getPackage() { - return getApplicationConfig(AutoConfigConstants.SETTINGS_PACKAGE); - } - - /** {@inheritDoc} */ - @Override - public void addAccount(String email, String password) { - if (!doesEmailExist(email)) { - goToSignInPage(); - inputAccount(email); - inputPassowrd(password); - UiObject2 doneButtonObject = - scrollAndFindUiObject( - getResourceFromConfig( - AutoConfigConstants.SETTINGS, - AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS, - AutoConfigConstants.DONE_BUTTON)); - if (doneButtonObject == null) { - throw new RuntimeException("Unable to find Done button."); - } - clickAndWaitForIdleScreen(doneButtonObject); - } - } - - private void goToSignInPage() { - UiObject2 addAccountObject = - scrollAndFindUiObject( - getResourceFromConfig( - AutoConfigConstants.SETTINGS, - AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS, - AutoConfigConstants.ADD_ACCOUNT)); - if (addAccountObject == null) { - throw new RuntimeException("Unable to find Add Account button."); - } - clickAndWaitForIdleScreen(addAccountObject); - UiObject2 signInOnCarScreen = - scrollAndFindUiObject( - By.clickable(true) - .hasDescendant( - getResourceFromConfig( - AutoConfigConstants.SETTINGS, - AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS, - AutoConfigConstants.SIGN_IN_ON_CAR_SCREEN))); - if (signInOnCarScreen == null) { - throw new RuntimeException("Unable to find Sign In on Car Screen button."); - } - clickAndWaitForIdleScreen(signInOnCarScreen); - scrollAndFindUiObject( - getResourceFromConfig( - AutoConfigConstants.SETTINGS, - AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS, - AutoConfigConstants.GOOGLE_SIGN_IN_SCREEN)); - } - - /** {@inheritDoc} */ - @Override - public void removeAccount(String email) { - if (doesEmailExist(email)) { - BySelector accountSelector = By.text(email); - UiObject2 accountObject = - scrollAndFindUiObject(accountSelector, getScrollScreenIndex()) - .getParent() - .getParent(); - clickAndWaitForIdleScreen(accountObject); - UiObject2 removeButtonObject = - scrollAndFindUiObject( - getResourceFromConfig( - AutoConfigConstants.SETTINGS, - AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS, - AutoConfigConstants.REMOVE_BUTTON)); - if (removeButtonObject == null) { - throw new RuntimeException("Unable to find Remove button."); - } - clickAndWaitForIdleScreen(removeButtonObject); - UiObject2 confirmObject = - scrollAndFindUiObject( - getResourceFromConfig( - AutoConfigConstants.SETTINGS, - AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS, - AutoConfigConstants.REMOVE_ACCOUNT_BUTTON)); - if (removeButtonObject == null) { - throw new RuntimeException("Unable to find Remove Account button."); - } - clickAndWaitForIdleScreen(confirmObject); - waitForGone(accountSelector); - } - } - - /** {@inheritDoc} */ - @Override - public boolean doesEmailExist(String email) { - UiObject2 accountObject = scrollAndFindUiObject(By.text(email), getScrollScreenIndex()); - return accountObject != null; - } - - private int getScrollScreenIndex() { - int scrollScreenIndex = 0; - if (hasSplitScreenSettingsUI()) { - scrollScreenIndex = 1; - } - return scrollScreenIndex; - } - - private void inputAccount(String account) { - inputText(account, false); - } - - private void inputPassowrd(String password) { - inputText(password, true); - } - - private void inputText(String text, boolean isPassword) { - BySelector selector = - getResourceFromConfig( - AutoConfigConstants.SETTINGS, - AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS, - AutoConfigConstants.ENTER_EMAIL); - if (isPassword) { - selector = - getResourceFromConfig( - AutoConfigConstants.SETTINGS, - AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS, - AutoConfigConstants.ENTER_PASSWORD); - } - UiObject2 input = scrollAndFindUiObject(selector); - if (input == null) { - throw new RuntimeException( - String.format("%s input is not present", selector.toString())); - } - input.setText(text); - scrollAndFindUiObject(By.text(text).focused(false)); - UiObject2 nextButtonObject = - scrollAndFindUiObject( - getResourceFromConfig( - AutoConfigConstants.SETTINGS, - AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS, - AutoConfigConstants.NEXT_BUTTON)); - if (nextButtonObject == null) { - throw new RuntimeException("Unable to find Next button."); - } - clickAndWaitForGone(nextButtonObject, By.text(text)); - SystemClock.sleep(UI_RESPONSE_WAIT_MS); // to avoid stale object error - } -} diff --git a/libraries/automotive-helpers/settings-app-helper/src/android/platform/helpers/SettingProfileHelperImpl.java b/libraries/automotive-helpers/settings-app-helper/src/android/platform/helpers/SettingUserHelperImpl.java index db68bebff..be2a1c5ea 100644 --- a/libraries/automotive-helpers/settings-app-helper/src/android/platform/helpers/SettingProfileHelperImpl.java +++ b/libraries/automotive-helpers/settings-app-helper/src/android/platform/helpers/SettingUserHelperImpl.java @@ -22,11 +22,12 @@ import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiObject2; import android.util.Log; + /** - * Implementation of {@link IAutoProfileHelper} to support tests of account settings + * Implementation of {@link IAutoUserHelper} to support tests of account settings */ -public class SettingProfileHelperImpl extends AbstractAutoStandardAppHelper - implements IAutoProfileHelper { +public class SettingUserHelperImpl extends AbstractAutoStandardAppHelper + implements IAutoUserHelper { // Packages private static final String APP_NAME = AutoConfigConstants.SETTINGS; @@ -36,9 +37,9 @@ public class SettingProfileHelperImpl extends AbstractAutoStandardAppHelper private static final int UI_RESPONSE_WAIT_MS = 10000; //constants - private static final String TAG = "SettingProfileHelperImpl"; + private static final String TAG = "SettingUserHelperImpl"; - public SettingProfileHelperImpl(Instrumentation instr) { + public SettingUserHelperImpl(Instrumentation instr) { super(instr); } @@ -55,7 +56,7 @@ public class SettingProfileHelperImpl extends AbstractAutoStandardAppHelper */ // Add a new user @Override - public void addProfile() { + public void addUser() { clickbutton(AutoConfigConstants.ADD_PROFILE); clickbutton(AutoConfigConstants.OK); SystemClock.sleep(UI_RESPONSE_WAIT_MS); @@ -63,8 +64,8 @@ public class SettingProfileHelperImpl extends AbstractAutoStandardAppHelper // delete an existing user @Override - public void deleteProfile(String user) { - if (isProfilePresent(user)) { + public void deleteUser(String user) { + if (isUserPresent(user)) { clickbutton(user); clickbutton(AutoConfigConstants.DELETE); clickbutton(AutoConfigConstants.DELETE); @@ -72,9 +73,9 @@ public class SettingProfileHelperImpl extends AbstractAutoStandardAppHelper } } - // delete self profile + // delete self User @Override - public void deleteCurrentProfile() { + public void deleteCurrentUser() { clickbutton(AutoConfigConstants.DELETE_SELF); clickbutton(AutoConfigConstants.DELETE); SystemClock.sleep(UI_RESPONSE_WAIT_MS); @@ -85,50 +86,51 @@ public class SettingProfileHelperImpl extends AbstractAutoStandardAppHelper */ // check if a user is present in the list of existing users @Override - public boolean isProfilePresent(String user) { - UiObject2 AddProfileButton = + public boolean isUserPresent(String user) { + UiObject2 addUserButton = scrollAndFindUiObject( getResourceFromConfig(APP_NAME, APP_CONFIG, AutoConfigConstants.ADD_PROFILE)); Log.v( TAG, String.format( "AddProfileButton = %s ; UI_Obj = %s", - AutoConfigConstants.ADD_PROFILE, AddProfileButton)); - if (AddProfileButton == null) { + AutoConfigConstants.ADD_PROFILE, addUserButton)); + if (addUserButton == null) { clickbutton(AutoConfigConstants.MANAGE_OTHER_PROFILES); - UiObject2 profileObject = scrollAndFindUiObject(By.text(user)); - return profileObject != null; + UiObject2 UserObject = scrollAndFindUiObject(By.text(user)); + return UserObject != null; } return false; } - // switch profile from current user to given user + // switch User from current user to given user @Override - public void switchProfile(String userFrom, String userTo) { + public void switchUser(String userFrom, String userTo) { goToQuickSettings(); clickbutton(userFrom); clickbutton(userTo); SystemClock.sleep(UI_RESPONSE_WAIT_MS); } - // add profile via quick settings + // add User via quick settings @Override - public void addProfileQuickSettings(String userFrom) { + public void addUserQuickSettings(String userFrom) { goToQuickSettings(); clickbutton(userFrom); - addProfile(); + addUser(); } // make an existing user admin @Override public void makeUserAdmin(String user) { - if (isProfilePresent(user)) { + if (isUserPresent(user)) { clickbutton(user); clickbutton(AutoConfigConstants.MAKE_ADMIN); clickbutton(AutoConfigConstants.MAKE_ADMIN_CONFIRM); } } + // click an on-screen element if expected text for that element is present private void clickbutton(String button_text) { UiObject2 buttonObject = @@ -148,8 +150,8 @@ public class SettingProfileHelperImpl extends AbstractAutoStandardAppHelper SystemClock.sleep(UI_RESPONSE_WAIT_MS); } - // go to quick Settings for switching profile + // go to quick Settings for switching User private void goToQuickSettings() { clickbutton(AutoConfigConstants.TIME_PATTERN); } -} +}
\ No newline at end of file diff --git a/libraries/automotive-helpers/standard-app-helper/src/android/platform/helpers/AbstractAutoStandardAppHelper.java b/libraries/automotive-helpers/standard-app-helper/src/android/platform/helpers/AbstractAutoStandardAppHelper.java index 9d01b3c08..a538d4bdb 100644 --- a/libraries/automotive-helpers/standard-app-helper/src/android/platform/helpers/AbstractAutoStandardAppHelper.java +++ b/libraries/automotive-helpers/standard-app-helper/src/android/platform/helpers/AbstractAutoStandardAppHelper.java @@ -55,6 +55,10 @@ public abstract class AbstractAutoStandardAppHelper extends AbstractStandardAppH mAutoJsonUtil = AutoJsonUtility.getInstance(); } + protected void addConfigUtility(String appName, IAutoConfigUtility utility) { + mAutoJsonUtil.addConfigUtility(appName, utility); + } + /** {@inheritDoc} */ @Override public void open() { diff --git a/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoConfigConstants.java b/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoConfigConstants.java index da44880ac..161ac43e2 100644 --- a/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoConfigConstants.java +++ b/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoConfigConstants.java @@ -245,4 +245,12 @@ public class AutoConfigConstants { public static final String BACK_BUTTON = "BACK_BUTTON"; // Media Center On Home Screen public static final String MEDIA_CENTER_ON_HOME_SCREEN = "MEDIA_CENTER_ON_HOME_SCREEN"; + // Media Apps Grid + public static final String MEDIA_APPS_GRID = "MEDIA_APPS_GRID"; + public static final String MEDIA_APPS_GRID_TITLE = "MEDIA_APPS"; + public static final String MEDIA_APPS_GRID_APP_NAME = "MEDIA_APP_NAME"; + // Media App UI View + public static final String MEDIA_APP = "MEDIA_APP"; + public static final String MEDIA_APP_TITLE = "MEDIA_APP_TITLE"; + public static final String MEDIA_APP_DROP_DOWN_MENU = "MEDIA_APP_DROP_DOWN_MENU"; } diff --git a/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoJsonUtility.java b/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoJsonUtility.java index 306a801e3..96a6b8aec 100644 --- a/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoJsonUtility.java +++ b/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoJsonUtility.java @@ -135,7 +135,6 @@ public class AutoJsonUtility { private void buildConfigMaps() { // Build Config Maps with default values ( based on Reference Devices ) buildDefaultConfigMaps(); - // Read Config File Path Param String configFilePath = InstrumentationRegistry.getArguments().getString(CONFIG_FILE_PATH_PARAM, null); @@ -153,6 +152,14 @@ public class AutoJsonUtility { } } + /** Add and Build Extra Config Maps ( Based on Reference Device ) */ + public void addConfigUtility(String appName, IAutoConfigUtility utility) { + if (utility != null || !configUtilityMap.containsKey(appName)) { + configUtilityMap.put(appName, utility); + configUtilityMap.get(appName).loadDefaultConfig(mApplicationConfigMap); + } + } + /** * Reads and parses the Config JSON file and update the Config Maps Sample JSON { * APPLICATION_NAME_1: { APPLICATION_CONFIG: { APPLICATION_PACKAGE: diff --git a/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoMediaCenterConfigUtility.java b/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoMediaCenterConfigUtility.java index d7e1ad15e..f7deeae79 100644 --- a/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoMediaCenterConfigUtility.java +++ b/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoMediaCenterConfigUtility.java @@ -158,6 +158,12 @@ public class AutoMediaCenterConfigUtility implements IAutoConfigUtility { // Default Media Center on Home Screen Config loadDefaultMediaCenterOnHomeScreenConfig(mMediaCenterConfigMap); + + // Default Media Apps Grid Screen Config + loadDefaultMediaCenterAppsGridConfig(mMediaCenterConfigMap); + + // Default Media Apps UI Config + loadDefaultMediaApp(mMediaCenterConfigMap); } private void loadDefaultMediaCenterAppConfig(Map<String, String> mApplicationConfigMap) { @@ -236,4 +242,38 @@ public class AutoMediaCenterConfigUtility implements IAutoConfigUtility { AutoConfigConstants.MEDIA_CENTER_ON_HOME_SCREEN, mediaCenterOnHomeScreenConfiguration); } + + private void loadDefaultMediaCenterAppsGridConfig( + Map<String, AutoConfiguration> mMediaCenterConfigMap) { + AutoConfiguration mediaCenterAppsGridConfiguration = new AutoConfiguration(); + mediaCenterAppsGridConfiguration.addResource( + AutoConfigConstants.MEDIA_APPS_GRID_TITLE, + new AutoConfigResource( + AutoConfigConstants.RESOURCE_ID, + "car_ui_toolbar_title", CAR_LAUNCHER_PACKAGE)); + mediaCenterAppsGridConfiguration.addResource( + AutoConfigConstants.MEDIA_APPS_GRID_APP_NAME, + new AutoConfigResource( + AutoConfigConstants.RESOURCE_ID, + "app_name", CAR_LAUNCHER_PACKAGE)); + mMediaCenterConfigMap.put( + AutoConfigConstants.MEDIA_APPS_GRID, mediaCenterAppsGridConfiguration); + } + + private void loadDefaultMediaApp( + Map<String, AutoConfiguration> mMediaCenterConfigMap) { + AutoConfiguration mediaAppConfiguration = new AutoConfiguration(); + mediaAppConfiguration.addResource( + AutoConfigConstants.MEDIA_APP_DROP_DOWN_MENU, + new AutoConfigResource( + AutoConfigConstants.RESOURCE_ID, + "car_ui_toolbar_menu_item_icon", MEDIA_CENTER_PACKAGE)); + mediaAppConfiguration.addResource( + AutoConfigConstants.MEDIA_APP_TITLE, + new AutoConfigResource( + AutoConfigConstants.RESOURCE_ID, + "car_ui_toolbar_title", MEDIA_CENTER_PACKAGE)); + mMediaCenterConfigMap.put( + AutoConfigConstants.MEDIA_APP, mediaAppConfiguration); + } } diff --git a/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoSettingsConfigUtility.java b/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoSettingsConfigUtility.java index e54c93405..a6fb5a186 100644 --- a/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoSettingsConfigUtility.java +++ b/libraries/automotive-helpers/utility-helper/src/android/platform/helpers/AutoSettingsConfigUtility.java @@ -508,7 +508,10 @@ public class AutoSettingsConfigUtility implements IAutoConfigUtility { new AutoConfigResource(AutoConfigConstants.TEXT, "Done")); accountSettingsConfiguration.addResource( AutoConfigConstants.REMOVE_BUTTON, - new AutoConfigResource(AutoConfigConstants.TEXT, "Remove")); + new AutoConfigResource( + AutoConfigConstants.RESOURCE_ID, + "car_ui_secondary_action", + SETTING_APP_PACKAGE)); accountSettingsConfiguration.addResource( AutoConfigConstants.REMOVE_ACCOUNT_BUTTON, new AutoConfigResource(AutoConfigConstants.TEXT, "Remove Account")); diff --git a/tests/automotive/health/evs/Android.bp b/libraries/collectors-helper/app/Android.bp index 9c3a9fd89..d60aff247 100644 --- a/tests/automotive/health/evs/Android.bp +++ b/libraries/collectors-helper/app/Android.bp @@ -12,21 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Used for collecting app metrics. package { default_applicable_licenses: ["Android-Apache-2.0"], } -java_library_static { - name: "automotive-evs-scenarios", - min_sdk_version: "24", - srcs: [ "src/**/*.java" ], - libs: [ +java_library { + name: "app-collector-helper", + defaults: ["tradefed_errorprone_defaults"], + + srcs: [ + "src/**/*.java", + ], + + static_libs: [ + "androidx.test.core", "androidx.test.runner", - "automotive-settings-app-helper", - "app-helpers-auto-interfaces", - "common-platform-scenarios", - "platform-test-options", - "platform-test-rules", - "ub-uiautomator", + "androidx.test.uiautomator", + "collector-helper-utilities", ], + + sdk_version: "current", } diff --git a/libraries/collectors-helper/app/src/com/android/helpers/AppVersionHelper.java b/libraries/collectors-helper/app/src/com/android/helpers/AppVersionHelper.java new file mode 100644 index 000000000..f8d2678ee --- /dev/null +++ b/libraries/collectors-helper/app/src/com/android/helpers/AppVersionHelper.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2021 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.helpers; + +import static com.android.helpers.MetricUtility.constructKey; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.util.Log; + +import androidx.test.core.app.ApplicationProvider; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This is a collector helper to use PackageManager to get app package versions. + */ +public class AppVersionHelper implements ICollectorHelper<Long> { + + private static final String TAG = AppVersionHelper.class.getSimpleName(); + private static final String METRIC_PREFIX = "app-version-code-long"; + + private Context context; + private PackageManager packageManager; + + private String[] mPackageNames = {}; + + public void setUp(String... packageNames) { + context = ApplicationProvider.getApplicationContext().getApplicationContext(); + packageManager = context.getPackageManager(); + mPackageNames = packageNames; + } + + @Override + public boolean startCollecting() { + return true; + } + + @Override + public Map<String, Long> getMetrics() { + Map<String, Long> metrics = new HashMap<>(); + if (mPackageNames == null || mPackageNames.length == 0 || mPackageNames[0].length() == 0) { + // If no package specified, collects all. + // Additional option flags is set to 0, which is simply default. + List<PackageInfo> pkgInfos = packageManager.getInstalledPackages(0); + for (PackageInfo pkgInfo : pkgInfos) { + metrics.put(constructKey(METRIC_PREFIX, pkgInfo.packageName), + pkgInfo.getLongVersionCode()); + } + } else { + for (String pkg : mPackageNames) { + try { + // Additional option flags is set to 0, which is simply default. + PackageInfo pkgInfo = packageManager.getPackageInfo(pkg, 0); + metrics.put(constructKey(METRIC_PREFIX, pkg), + pkgInfo.getLongVersionCode()); + Log.d(TAG, "Found app version for package name " + pkg); + } catch (PackageManager.NameNotFoundException exception) { + Log.e(TAG, "Can't find package name " + pkg); + continue; + } + } + } + return metrics; + } + + @Override + public boolean stopCollecting() { + return true; + } +} diff --git a/tests/automotive/health/radio/Android.bp b/libraries/collectors-helper/app/test/Android.bp index 89e7987a2..3537f6521 100644 --- a/tests/automotive/health/radio/Android.bp +++ b/libraries/collectors-helper/app/test/Android.bp @@ -16,17 +16,18 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } -java_library_static { - name: "automotive-radio-scenarios", - min_sdk_version: "24", - srcs: [ "src/**/*.java" ], - libs: [ +java_library { + name: "app-collector-helper-test", + defaults: ["tradefed_errorprone_defaults"], + + srcs: ["src/**/*.java"], + + static_libs: [ "androidx.test.runner", - "automotive-settings-app-helper", - "app-helpers-auto-interfaces", - "common-platform-scenarios", - "platform-test-options", - "platform-test-rules", - "ub-uiautomator", + "junit", + "mockito-target", + "app-collector-helper", ], -} + + sdk_version: "current", +}
\ No newline at end of file diff --git a/libraries/collectors-helper/app/test/src/com/android/helpers/tests/AppVersionHelperTest.java b/libraries/collectors-helper/app/test/src/com/android/helpers/tests/AppVersionHelperTest.java new file mode 100644 index 000000000..6d196e6cb --- /dev/null +++ b/libraries/collectors-helper/app/test/src/com/android/helpers/tests/AppVersionHelperTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2021 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.helpers.tests; + +import static com.android.helpers.MetricUtility.constructKey; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.helpers.AppVersionHelper; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Map; + +/** + * Android Unit tests for {@link AppVersionHelper}. + * + * To run: + * atest CollectorsHelperTest:com.android.helpers.tests.AppVersionHelperTest + */ +@RunWith(AndroidJUnit4.class) +public class AppVersionHelperTest { + + // Package name used for testing + private static final String TEST_PACKAGE_NAME = "com.android.systemui"; + // Second package name used for testing + private static final String TEST_PACKAGE_NAME_2 = "com.google.android.apps.nexuslauncher"; + // Invalid package name used for testing + private static final String INVALID_PACKAGE_NAME = "abc"; + // App version metric prefix in Key. + private static final String METRIC_PREFIX = "app-version-code-long"; + + private AppVersionHelper mAppVersionHelper; + private static final String TAG = AppVersionHelper.class.getSimpleName(); + + @Before + public void setUp() { + mAppVersionHelper = new AppVersionHelper(); + } + + /** Test all app version metrics are sampled if package name is empty. */ + @Test + public void testEmptyPackageName() { + mAppVersionHelper.setUp(""); + Map<String, Long> appVersionMetrics = mAppVersionHelper.getMetrics(); + assertFalse("Metrics should not be empty for empty package name.", + appVersionMetrics.isEmpty()); + } + + /** Test all app version metrics are sampled if package names is null */ + @Test + public void testNullPackageName() { + mAppVersionHelper.setUp(null); + Map<String, Long> appVersionMetrics = mAppVersionHelper.getMetrics(); + assertFalse("Metrics should not be empty for null package name.", + appVersionMetrics.isEmpty()); + } + + /** Test getting metrics for single package. */ + @Test + public void testGetMetrics_OnePackage() { + mAppVersionHelper.setUp(TEST_PACKAGE_NAME); + Map<String, Long> appVersionMetrics = mAppVersionHelper.getMetrics(); + assertFalse("Metrics should not be empty for single package name.", + appVersionMetrics.isEmpty()); + String metricKey = constructKey(METRIC_PREFIX, TEST_PACKAGE_NAME); + assertTrue("Missing metric key: " + metricKey, appVersionMetrics.containsKey(metricKey)); + assertTrue("Bad metric for " + metricKey + ": " + appVersionMetrics.get(metricKey), + appVersionMetrics.get(metricKey) > 0); + } + + /** Test getting metrics for multiple packages. */ + @Test + public void testGetMetrics_MultiplePackages() { + mAppVersionHelper.setUp(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2); + Map<String, Long> appVersionMetrics = mAppVersionHelper.getMetrics(); + assertFalse("Metrics should not be empty for multiple package names.", + appVersionMetrics.isEmpty()); + String metricKey1 = constructKey(METRIC_PREFIX, TEST_PACKAGE_NAME); + String metricKey2 = constructKey(METRIC_PREFIX, TEST_PACKAGE_NAME_2); + + assertTrue("Missing metric key: " + metricKey1, + appVersionMetrics.containsKey(metricKey1)); + assertTrue("Missing metric key: " + metricKey2, + appVersionMetrics.containsKey(metricKey2)); + assertTrue("Bad metric for " + metricKey1 + ": " + appVersionMetrics.get(metricKey1), + appVersionMetrics.get(metricKey1) > 0); + assertTrue("Bad metric for " + metricKey2 + ": " + appVersionMetrics.get(metricKey2), + appVersionMetrics.get(metricKey2) > 0); + } + + /** Test app version metric is 0 for invalid package name. */ + @Test + public void testGetMetrics_InvalidPackage() { + mAppVersionHelper.setUp(INVALID_PACKAGE_NAME); + Map<String, Long> appVersionMetrics = mAppVersionHelper.getMetrics(); + assertTrue("Metrics should not be collected for invalid package names.", + appVersionMetrics.isEmpty()); + } +}
\ No newline at end of file diff --git a/libraries/collectors-helper/memory/src/com/android/helpers/ShowmapSnapshotHelper.java b/libraries/collectors-helper/memory/src/com/android/helpers/ShowmapSnapshotHelper.java index c23d652bf..c8eb6bbd5 100644 --- a/libraries/collectors-helper/memory/src/com/android/helpers/ShowmapSnapshotHelper.java +++ b/libraries/collectors-helper/memory/src/com/android/helpers/ShowmapSnapshotHelper.java @@ -32,8 +32,11 @@ import java.util.InputMismatchException; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; /** @@ -55,6 +58,10 @@ public class ShowmapSnapshotHelper implements ICollectorHelper<String> { public static final String OUTPUT_CHILD_PROCESS_COUNT_KEY = CHILD_PROCESS_COUNT_PREFIX + "_%s"; public static final String PROCESS_WITH_CHILD_PROCESS_COUNT = "process_with_child_process_count"; + private static final String CHILD_PROCESS_NAME_REGEX = "(\\S+)$"; + private static final String METRIC_VALUE_SEPARATOR = "_"; + public static final String PARENT_PROCESS_STRING = "parent_process"; + public static final String CHILD_PROCESS_STRING = "child_process"; private String[] mProcessNames = null; private String mTestOutputDir = null; @@ -69,7 +76,7 @@ public class ShowmapSnapshotHelper implements ICollectorHelper<String> { // Maintain metric name and the index it corresponds to in the showmap output // summary - private Map<Integer, String> mMetricNameIndexMap = new HashMap<>(); + private Map<String, List<Integer>> mMetricNameIndexMap = new HashMap<>(); public void setUp(String testOutputDir, String... processNames) { mProcessNames = processNames; @@ -155,7 +162,7 @@ public class ShowmapSnapshotHelper implements ICollectorHelper<String> { // Parse number of child processes for the given pid and update the // total number of child process count for the process name that pid // is associated with. - updateChildProcessesCount(processName, pid); + updateChildProcessesDetails(processName, pid); } } catch (RuntimeException e) { Log.e(TAG, e.getMessage(), e.getCause()); @@ -282,19 +289,21 @@ public class ShowmapSnapshotHelper implements ICollectorHelper<String> { int pos = showmapOutput.lastIndexOf("----"); String summarySplit[] = showmapOutput.substring(pos).trim().split("\\s+"); - for (Map.Entry<Integer, String> entry : mMetricNameIndexMap.entrySet()) { + for (Map.Entry<String, List<Integer>> entry : mMetricNameIndexMap.entrySet()) { + Long metricValue = 0L; String metricKey = constructKey( - String.format(OUTPUT_METRIC_PATTERN, entry.getValue()), + String.format(OUTPUT_METRIC_PATTERN, entry.getKey()), processName); + for (int index = 0; index < entry.getValue().size(); index++) { + metricValue += Long.parseLong(summarySplit[entry.getValue().get(index) + 1]); + } // If there are multiple pids associated with the process name then update the // existing entry in the map otherwise add new entry in the map. if (mMemoryMap.containsKey(metricKey)) { long currValue = Long.parseLong(mMemoryMap.get(metricKey)); - mMemoryMap.put(metricKey, Long.toString(currValue + - (Long.parseLong(summarySplit[entry.getKey() + 1]) * 1024))); + mMemoryMap.put(metricKey, Long.toString(currValue + metricValue * 1024)); } else { - mMemoryMap.put(metricKey, Long.toString(Long.parseLong( - summarySplit[entry.getKey() + 1]) * 1024)); + mMemoryMap.put(metricKey, Long.toString(metricValue * 1024)); } } } catch (IndexOutOfBoundsException | InputMismatchException e) { @@ -330,13 +339,20 @@ public class ShowmapSnapshotHelper implements ICollectorHelper<String> { * map and pass the map to this method. */ public void setMetricNameIndex(String metricNameIndexStr) { + /** + * example: metricNameIndexStr rss:1,pss:2,privatedirty:6:7 + * converted to Map: {'rss': [1], 'pss': [2], 'privatedirty': [6, 7]} + */ Log.i(TAG, String.format("Metric Name index %s", metricNameIndexStr)); String metricDetails[] = metricNameIndexStr.split(","); for (String metricDetail : metricDetails) { + List<Integer> indexList = new ArrayList<>(); String metricDetailsSplit[] = metricDetail.split(":"); - if (metricDetailsSplit.length == 2) { - mMetricNameIndexMap.put(Integer.parseInt( - metricDetailsSplit[1]), metricDetailsSplit[0]); + for (int index = 1; index < metricDetailsSplit.length; index++) { + indexList.add(Integer.parseInt(metricDetailsSplit[index])); + } + if (!indexList.isEmpty()) { + mMetricNameIndexMap.put(metricDetailsSplit[0], indexList); } } Log.i(TAG, String.format("Metric Name index map size %s", mMetricNameIndexMap.size())); @@ -344,12 +360,16 @@ public class ShowmapSnapshotHelper implements ICollectorHelper<String> { /** * Retrieves the number of child processes for the given process id and updates the total - * process count for the process name that pid is associated with. + * process count and adds a child process metric for the process name that pid is associated + * with. * * @param processName * @param pid */ - private void updateChildProcessesCount(String processName, long pid) { + private void updateChildProcessesDetails(String processName, long pid) { + String childProcessName; + String completeChildProcessMetric; + Pattern childProcessPattern = Pattern.compile(CHILD_PROCESS_NAME_REGEX); try { Log.i(TAG, String.format("Retrieving child processes count for process name: %s with" @@ -368,8 +388,29 @@ public class ShowmapSnapshotHelper implements ICollectorHelper<String> { Long.parseLong(mMemoryMap.getOrDefault(childCountMetricKey, "0")) + childProcessCount)); } + for (String line : childProcessStrSplit) { + // To discard the header line in the command output. + if (Objects.equals(line, childProcessStrSplit[0])) continue; + Matcher childProcessMatcher = childProcessPattern.matcher(line); + if (childProcessMatcher.find()) { + /** + * final metric will be of following format + * parent_process_<process>_child_process_<process> + * parent_process_zygote64_child_process_system_server + */ + childProcessName = childProcessMatcher.group(1); + completeChildProcessMetric = + String.join( + METRIC_VALUE_SEPARATOR, + PARENT_PROCESS_STRING, + processName, + CHILD_PROCESS_STRING, + childProcessName); + mMemoryMap.put(completeChildProcessMetric, "1"); + } + } } catch (IOException e) { - throw new RuntimeException("Unable to run child process count command.", e); + throw new RuntimeException("Unable to run child process command.", e); } } diff --git a/libraries/collectors-helper/memory/test/src/com/android/helpers/tests/ShowmapSnapshotHelperTest.java b/libraries/collectors-helper/memory/test/src/com/android/helpers/tests/ShowmapSnapshotHelperTest.java index eaca26b35..d2e7d5bab 100644 --- a/libraries/collectors-helper/memory/test/src/com/android/helpers/tests/ShowmapSnapshotHelperTest.java +++ b/libraries/collectors-helper/memory/test/src/com/android/helpers/tests/ShowmapSnapshotHelperTest.java @@ -48,6 +48,8 @@ public class ShowmapSnapshotHelperTest { private static final String INVALID_OUTPUT_DIR = "/data/local/tmp"; // Valid metric index string. private static final String METRIC_INDEX_STR = "rss:1,pss:2"; + // Valid summation metric index string. + private static final String METRIC_SUM_INDEX_STR = "privatedirty:6:7"; // Invalid metric index string. Reverse order. private static final String METRIC_INVALID_INDEX_STR = "1:pss"; // Empty metric index string. @@ -191,6 +193,17 @@ public class ShowmapSnapshotHelperTest { } @Test + public void testGetMetrics_Summation_Metric_Pattern() { + mShowmapSnapshotHelper.setUp(VALID_OUTPUT_DIR, NO_PROCESS_LIST); + mShowmapSnapshotHelper.setMetricNameIndex(METRIC_SUM_INDEX_STR); + mShowmapSnapshotHelper.setAllProcesses(); + assertTrue(mShowmapSnapshotHelper.startCollecting()); + Map<String, String> metrics = mShowmapSnapshotHelper.getMetrics(); + assertTrue(metrics.size() > 2); + assertTrue(metrics.containsKey(ShowmapSnapshotHelper.OUTPUT_FILE_PATH_KEY)); + } + + @Test public void testGetMetrics_verify_child_processes_metrics() { mShowmapSnapshotHelper.setUp(VALID_OUTPUT_DIR, NO_PROCESS_LIST); mShowmapSnapshotHelper.setMetricNameIndex(METRIC_EMPTY_INDEX_STR); @@ -215,6 +228,26 @@ public class ShowmapSnapshotHelperTest { assertTrue(metrics.containsKey(ShowmapSnapshotHelper.CHILD_PROCESS_COUNT_PREFIX + "_init")); } + @Test + public void testGetMetrics_parent_process_child_processes_metrics() { + mShowmapSnapshotHelper.setUp(VALID_OUTPUT_DIR, NO_PROCESS_LIST); + mShowmapSnapshotHelper.setMetricNameIndex(METRIC_EMPTY_INDEX_STR); + + mShowmapSnapshotHelper.setAllProcesses(); + assertTrue(mShowmapSnapshotHelper.startCollecting()); + Map<String, String> metrics = mShowmapSnapshotHelper.getMetrics(); + + assertTrue(metrics.size() != 0); + + Set<String> parentWithChildProcessSet = + metrics.keySet().stream() + .filter(s -> s.startsWith(ShowmapSnapshotHelper.PARENT_PROCESS_STRING)) + .collect(Collectors.toSet()); + + // At least one process (i.e init) will have child process + assertTrue(parentWithChildProcessSet.size() > 0); + } + private boolean verifyDefaultMetrics(Map<String, String> metrics) { if(metrics.size() == 0) { return false; @@ -223,7 +256,8 @@ public class ShowmapSnapshotHelperTest { if (!(key.equals(ShowmapSnapshotHelper.PROCESS_COUNT) || key.equals(ShowmapSnapshotHelper.OUTPUT_FILE_PATH_KEY) || key.equals(ShowmapSnapshotHelper.PROCESS_WITH_CHILD_PROCESS_COUNT) - || key.startsWith(ShowmapSnapshotHelper.CHILD_PROCESS_COUNT_PREFIX))) { + || key.startsWith(ShowmapSnapshotHelper.CHILD_PROCESS_COUNT_PREFIX) + || key.startsWith(ShowmapSnapshotHelper.PARENT_PROCESS_STRING))) { return false; } } diff --git a/libraries/collectors-helper/statsd/src/com/android/helpers/ThermalHelper.java b/libraries/collectors-helper/statsd/src/com/android/helpers/ThermalHelper.java index 874fb2e0f..b8a27100f 100644 --- a/libraries/collectors-helper/statsd/src/com/android/helpers/ThermalHelper.java +++ b/libraries/collectors-helper/statsd/src/com/android/helpers/ThermalHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2021 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. @@ -47,6 +47,12 @@ import java.util.regex.Pattern; public class ThermalHelper implements ICollectorHelper<StringBuilder> { private static final String LOG_TAG = ThermalHelper.class.getSimpleName(); + @VisibleForTesting static final String DUMP_THERMALSERVICE_CMD = "dumpsys thermalservice"; + private static final String METRIC_KEY_TEMPERATURE = "temperature"; + private static final String METRIC_KEY_VALUE = "value"; + private static final String METRIC_KEY_TYPE = "type"; + private static final String METRIC_KEY_STATUS = "status"; + private static final int UNDEFINED_SEVERITY = -1; private static final Pattern SEVERITY_DUMPSYS_PATTERN = Pattern.compile("Thermal Status: (\\d+)"); @@ -63,7 +69,7 @@ public class ThermalHelper implements ICollectorHelper<StringBuilder> { // Add an initial value because this only detects changes. mInitialSeverity = UNDEFINED_SEVERITY; try { - String[] output = getDevice().executeShellCommand("dumpsys thermalservice").split("\n"); + String[] output = getDevice().executeShellCommand(DUMP_THERMALSERVICE_CMD).split("\n"); for (String line : output) { Matcher severityMatcher = SEVERITY_DUMPSYS_PATTERN.matcher(line); if (severityMatcher.matches()) { @@ -115,24 +121,36 @@ public class ThermalHelper implements ICollectorHelper<StringBuilder> { } } + updateTemperatureMetrics(results); + + return results; + } + + /** Collect temperature metrics into result map. */ + private void updateTemperatureMetrics(Map<String, StringBuilder> results) { + try { - String[] output = getDevice().executeShellCommand("dumpsys thermalservice").split("\n"); + String output = getDevice().executeShellCommand(DUMP_THERMALSERVICE_CMD); + String[] lines = output.split("\n"); boolean inCurrentTempSection = false; - for (String line : output) { + for (String line : lines) { Matcher temperatureMatcher = TEMPERATURE_DUMPSYS_PATTERN.matcher(line); if (inCurrentTempSection && temperatureMatcher.matches()) { Log.v(LOG_TAG, "Matched " + line); String name = temperatureMatcher.group(3); MetricUtility.addMetric( - MetricUtility.constructKey("temperature", name, "value"), + MetricUtility.constructKey( + METRIC_KEY_TEMPERATURE, name, METRIC_KEY_VALUE), Double.parseDouble(temperatureMatcher.group(1)), // value group results); MetricUtility.addMetric( - MetricUtility.constructKey("temperature", name, "type"), + MetricUtility.constructKey( + METRIC_KEY_TEMPERATURE, name, METRIC_KEY_TYPE), Integer.parseInt(temperatureMatcher.group(2)), // type group results); MetricUtility.addMetric( - MetricUtility.constructKey("temperature", name, "status"), + MetricUtility.constructKey( + METRIC_KEY_TEMPERATURE, name, METRIC_KEY_STATUS), Integer.parseInt(temperatureMatcher.group(4)), // status group results); } @@ -151,8 +169,27 @@ public class ThermalHelper implements ICollectorHelper<StringBuilder> { } catch (IOException ioe) { Log.e(LOG_TAG, String.format("Failed to query thermalservice. Error: %s", ioe)); } + } - return results; + /** + * Get latest temperature value for needed name. Return temperature value is in unit of degree + * Celsius + */ + public double getTemperature(String name) { + Map<String, StringBuilder> results = new HashMap<>(); + updateTemperatureMetrics(results); + String temperatureKey = + MetricUtility.constructKey(METRIC_KEY_TEMPERATURE, name, METRIC_KEY_VALUE); + List<Double> values = MetricUtility.getMetricDoubles(temperatureKey, results); + if (values.size() > 0) { + double value = + values.get(values.size() - 1).doubleValue(); // last value is the latest value. + Log.v(LOG_TAG, String.format("Got temperature of %s: %,.6f", name, value)); + return value; + } else { + throw new IllegalArgumentException( + String.format("Failed to get temperature of %s", name)); + } } /** Remove the statsd config used to track thermal events. */ diff --git a/libraries/collectors-helper/statsd/test/src/com/android/helpers/ThermalHelperTest.java b/libraries/collectors-helper/statsd/test/src/com/android/helpers/ThermalHelperTest.java index e10051995..f187e028a 100644 --- a/libraries/collectors-helper/statsd/test/src/com/android/helpers/ThermalHelperTest.java +++ b/libraries/collectors-helper/statsd/test/src/com/android/helpers/ThermalHelperTest.java @@ -18,6 +18,7 @@ package com.android.helpers; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.when; import android.os.nano.OsProtoEnums; @@ -50,6 +51,31 @@ public class ThermalHelperTest { private static final String THROTTLING_KEY = MetricUtility.constructKey("thermal", "throttling", "severity"); private static final String FAKE_SERVICE_DUMP = "F\nA\nK\nE\nThermal Status: 2\nO\nK"; + private static final String SERVICE_DUMP_TEMPLATE = + "IsStatusOverride: false\n" + + "ThermalEventListeners:\n" + + " callbacks: 1\n" + + " killed: false\n" + + " broadcasts count: -1\n" + + "ThermalStatusListeners:\n" + + " callbacks: 1\n" + + " killed: false\n" + + " broadcasts count: -1\n" + + "Thermal Status: 0\n" + + "Cached temperatures:\n" + + " Temperature{mValue=45.67, mType=3, mName=cached temperature sensor," + + " mStatus=0}\n" + + "HAL Ready: true\n" + + "HAL connection:\n" + + " ThermalHAL 2.0 connected: yes\n" + + "Current temperatures from HAL:\n" + + " Temperature{mValue=%s, mType=3, mName=%s, mStatus=0}\n" + + " Temperature{mValue=45.6, mType=3, mName=test temperature sensor2," + + " mStatus=0}\n" + + " Temperature{mValue=56.789, mType=3, mName=test temperature sensor3," + + " mStatus=0}\n" + + "Current cooling devices from HAL:\n" + + " CoolingDevice{mValue=100, mType=0, mName=test cooling device}"; private ThermalHelper mThermalHelper; private StatsdHelper mStatsdHelper; @@ -149,7 +175,8 @@ public class ThermalHelperTest { /** Test that the temperature section is parsed correctly. */ @Test public void testParseTemperature() throws Exception { - // Use real data for this test. It should work everywhere. + // Use real data for this test. It should work everywhere, except for + // aosp_cf_x86_64_phone-userdebug. mThermalHelper = new ThermalHelper(); mThermalHelper.setStatsdHelper(mStatsdHelper); assertTrue(mThermalHelper.startCollecting()); @@ -178,6 +205,97 @@ public class ThermalHelperTest { assertTrue(mThermalHelper.stopCollecting()); } + /** Test that the mock temperature section is parsed correctly. */ + @Test + public void testParseTemperatureMock() throws Exception { + // Use mock data for this test. + final String correctName = "test temperature sensor"; + final double correctValue = 32.1; + final String correctOutput = + String.format(SERVICE_DUMP_TEMPLATE, String.valueOf(correctValue), correctName); + when(mDevice.executeShellCommand(ThermalHelper.DUMP_THERMALSERVICE_CMD)) + .thenReturn(correctOutput); + Map<String, StringBuilder> metrics = mThermalHelper.getMetrics(); + // Validate at least 2 temperature keys exist with all 3 metrics. + int statusMetricsFound = 0; + int valueMetricsFound = 0; + int typeMetricsFound = 0; + for (String key : metrics.keySet()) { + if (!key.startsWith("temperature")) { + continue; + } + + if (key.endsWith("status")) { + statusMetricsFound++; + } else if (key.endsWith("value")) { + valueMetricsFound++; + } else if (key.endsWith("type")) { + typeMetricsFound++; + } + } + + assertTrue( + "Didn't find at least 2 status, value, and type temperature metrics.", + statusMetricsFound >= 2 && valueMetricsFound >= 2 && typeMetricsFound >= 2); + } + + /** Test getting temperature value from DUT correctly. */ + @Test + public void testGetTemperature() throws Exception { + final double THRESHOLD = 0.0001; + final String correctName = "test temperature sensor"; + final double correctValue = 32.1; + final String correctOutput = + String.format(SERVICE_DUMP_TEMPLATE, String.valueOf(correctValue), correctName); + + when(mDevice.executeShellCommand(ThermalHelper.DUMP_THERMALSERVICE_CMD)) + .thenReturn(correctOutput); + assertTrue(Math.abs(mThermalHelper.getTemperature(correctName) - correctValue) < THRESHOLD); + } + + /** Test failing to get temperature value from DUT. */ + @Test + public void testGetTemperatureFailed() throws Exception { + final String correctName = "test temperature sensor"; + final double correctValue = 32.1; + final String correctOutput = + String.format(SERVICE_DUMP_TEMPLATE, String.valueOf(correctValue), correctName); + final String expectedMessage = "Failed to get temperature of "; + + final String badName = "bad temperature sensor"; + when(mDevice.executeShellCommand(ThermalHelper.DUMP_THERMALSERVICE_CMD)) + .thenReturn(correctOutput); + Exception exception1 = + assertThrows( + IllegalArgumentException.class, + () -> { + mThermalHelper.getTemperature(badName); + }); + assertTrue(exception1.getMessage().contains(expectedMessage)); + + final String badOutput = String.format(SERVICE_DUMP_TEMPLATE, "bad", correctName); + when(mDevice.executeShellCommand(ThermalHelper.DUMP_THERMALSERVICE_CMD)) + .thenReturn(badOutput); + Exception exception2 = + assertThrows( + IllegalArgumentException.class, + () -> { + mThermalHelper.getTemperature(correctName); + }); + assertTrue(exception2.getMessage().contains(expectedMessage)); + + final String badOutputEmpty = String.format(SERVICE_DUMP_TEMPLATE, "", correctName); + when(mDevice.executeShellCommand(ThermalHelper.DUMP_THERMALSERVICE_CMD)) + .thenReturn(badOutputEmpty); + Exception exception3 = + assertThrows( + IllegalArgumentException.class, + () -> { + mThermalHelper.getTemperature(correctName); + }); + assertTrue(exception3.getMessage().contains(expectedMessage)); + } + /** * Returns a list of {@link com.android.os.nano.StatsLog.EventMetricData} that statsd returns. */ diff --git a/libraries/collectors-helper/tests/Android.bp b/libraries/collectors-helper/tests/Android.bp index 4a3413a51..502e9fcf9 100644 --- a/libraries/collectors-helper/tests/Android.bp +++ b/libraries/collectors-helper/tests/Android.bp @@ -22,6 +22,7 @@ android_test { static_libs: [ "perfetto-helper-test", + "app-collector-helper-test", "jank-helper-test", "memory-helper-test", "system-helper-test", diff --git a/libraries/collectors-helper/utilities/src/com/android/helpers/MetricUtility.java b/libraries/collectors-helper/utilities/src/com/android/helpers/MetricUtility.java index 5e7e8e5a0..def11392f 100644 --- a/libraries/collectors-helper/utilities/src/com/android/helpers/MetricUtility.java +++ b/libraries/collectors-helper/utilities/src/com/android/helpers/MetricUtility.java @@ -5,9 +5,12 @@ import android.os.ParcelFileDescriptor; import android.util.Log; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.io.InputStream; +import java.io.IOException; import java.text.DecimalFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; /** @@ -73,6 +76,43 @@ public class MetricUtility { } /** + * Get metric values from result map. + * + * @param metricKey Unique key to track the metric. + * @param resultMap Map of all the metrics. + * @return Double List of metric values for metric key + */ + public static List<Double> getMetricDoubles( + String metricKey, Map<String, StringBuilder> resultMap) { + List<Double> result = new ArrayList<Double>(); + if (!resultMap.containsKey(metricKey)) { + Log.e(TAG, String.format("No such metric key %s", metricKey)); + return result; + } else { + String value = resultMap.get(metricKey).toString(); + if (value.length() == 0) { + Log.e(TAG, String.format("Missed value of metric key %s", metricKey)); + return result; + } else { + String[] values = value.split(METRIC_SEPARATOR); + for (int i = 0; i < values.length; i++) { + try { + result.add(DOUBLE_FORMAT.parse(values[i]).doubleValue()); + } catch (ParseException e) { + Log.e( + TAG, + String.format( + "Error parsing value of metric key %s: #%d of value %s", + metricKey, i, value)); + return new ArrayList<Double>(); + } + } + } + } + return result; + } + + /** * Turn executeShellCommand into a blocking operation. * * @param command shell command to be executed. diff --git a/libraries/device-collectors/src/main/Android.bp b/libraries/device-collectors/src/main/Android.bp index f9bee71d1..709f21f74 100644 --- a/libraries/device-collectors/src/main/Android.bp +++ b/libraries/device-collectors/src/main/Android.bp @@ -26,6 +26,7 @@ java_library { "androidx.annotation_annotation", "androidx.test.runner", "androidx.test.uiautomator", + "app-collector-helper", "jank-helper", "junit", "lyric-metric-helper", diff --git a/libraries/device-collectors/src/main/java/android/device/collectors/AppVersionListener.java b/libraries/device-collectors/src/main/java/android/device/collectors/AppVersionListener.java new file mode 100644 index 000000000..809c9bdf3 --- /dev/null +++ b/libraries/device-collectors/src/main/java/android/device/collectors/AppVersionListener.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2021 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 android.device.collectors; + +import android.device.collectors.annotations.OptionClass; +import android.os.Bundle; +import android.util.Log; +import androidx.annotation.VisibleForTesting; + +import com.android.helpers.AppVersionHelper; + +/** + * A {@link AppVersionListener} that captures and records the versions of the app packages + * on the device. + * <p>Options: + * <ul> + * <li>-e pkg-names [pkgNames] : the pkg names we want to get versions for. + * </ul> + */ +@OptionClass(alias = "app-version-listener") +public class AppVersionListener extends BaseCollectionListener<Long> { + + private static final String TAG = AppVersionHelper.class.getSimpleName(); + private AppVersionHelper mAppVersionHelper = new AppVersionHelper(); + @VisibleForTesting static final String PKG_NAME_SEPARATOR = ","; + @VisibleForTesting static final String PKG_NAMES_ARG = "app-version-pkg-names"; + + public AppVersionListener() { + createHelperInstance(mAppVersionHelper); + } + + /** + * Constructor to simulate receiving the instrumentation arguments. Should not be used except + * for testing. + */ + @VisibleForTesting + public AppVersionListener(Bundle args, AppVersionHelper helper) { + super(args, helper); + mAppVersionHelper = helper; + createHelperInstance(mAppVersionHelper); + } + + /** + * Adds the options for app version collector. + */ + @Override + public void setupAdditionalArgs() { + Bundle args = getArgsBundle(); + String pkgNamesString = args.getString(PKG_NAMES_ARG); + if (pkgNamesString == null) { + Log.w(TAG, "No package name provided. All packages will be collected"); + mAppVersionHelper.setUp(); + } + mAppVersionHelper.setUp(pkgNamesString.split(PKG_NAME_SEPARATOR)); + } +} diff --git a/libraries/device-collectors/src/main/java/android/device/collectors/BaseMetricListener.java b/libraries/device-collectors/src/main/java/android/device/collectors/BaseMetricListener.java index ae878aef3..fcd596354 100644 --- a/libraries/device-collectors/src/main/java/android/device/collectors/BaseMetricListener.java +++ b/libraries/device-collectors/src/main/java/android/device/collectors/BaseMetricListener.java @@ -118,8 +118,7 @@ public class BaseMetricListener extends InstrumentationRunListener { @Override public final void testRunStarted(Description description) throws Exception { - parseArguments(); - setupAdditionalArgs(); + setUp(); if (!mLogOnly) { try { mRunData = createDataRecord(); @@ -142,6 +141,7 @@ public class BaseMetricListener extends InstrumentationRunListener { Log.e(getTag(), "Exception during onTestRunEnd.", e); } } + cleanUp(); super.testRunFinished(result); } @@ -207,6 +207,28 @@ public class BaseMetricListener extends InstrumentationRunListener { } /** + * Set up the metric collector. + * + * <p>If another class is invoking the metric collector's callbacks directly, it should call + * this method to make sure that the metric collector is set up properly. + */ + public final void setUp() { + parseArguments(); + setupAdditionalArgs(); + onSetUp(); + } + + /** + * Clean up the metric collector. + * + * <p>If another class is invoking the metric collector's callbacks directly, it should call + * this method to make sure that the metric collector is cleaned up properly after collection. + */ + public final void cleanUp() { + onCleanUp(); + } + + /** * Create a {@link DataRecord}. Exposed for testing. */ @VisibleForTesting @@ -214,6 +236,17 @@ public class BaseMetricListener extends InstrumentationRunListener { return new DataRecord(); } + // ---------- Interfaces that can be implemented to set up and clean up metric collection. + + /** Called if custom set-up is needed for this metric collector. */ + protected void onSetUp() { + // Does nothing by default. + } + + protected void onCleanUp() { + // Does nothing by default. + } + // ---------- Interfaces that can be implemented to take action on each test state. /** diff --git a/libraries/device-collectors/src/main/java/android/device/collectors/PerfettoListener.java b/libraries/device-collectors/src/main/java/android/device/collectors/PerfettoListener.java index 41550ed52..d24e0fc1c 100644 --- a/libraries/device-collectors/src/main/java/android/device/collectors/PerfettoListener.java +++ b/libraries/device-collectors/src/main/java/android/device/collectors/PerfettoListener.java @@ -46,6 +46,8 @@ public class PerfettoListener extends BaseMetricListener { // Default perfetto config file name. private static final String DEFAULT_CONFIG_FILE = "trace_config.pb"; + // Default perfetto config file name when text proto config is used. + private static final String DEFAULT_TEXT_CONFIG_FILE = "trace_config.textproto"; // Default wait time before stopping the perfetto trace. private static final String DEFAULT_WAIT_TIME_MSECS = "3000"; // Option to pass the folder name which contains the perfetto trace config file. @@ -301,8 +303,12 @@ public class PerfettoListener extends BaseMetricListener { mIsConfigTextProto = Boolean.parseBoolean(args.getString(PERFETTO_CONFIG_TEXT_PROTO)); // Perfetto config file has to be under /data/misc/perfetto-traces/ - // defaulted to trace_config.pb is perfetto_config_file is not passed. - mConfigFileName = args.getString(PERFETTO_CONFIG_FILE_ARG, DEFAULT_CONFIG_FILE); + // defaulted to DEFAULT_TEXT_CONFIG_FILE or DEFAULT_CONFIG_FILE if perfetto_config_file is + // not passed. + mConfigFileName = + args.getString( + PERFETTO_CONFIG_FILE_ARG, + mIsConfigTextProto ? DEFAULT_TEXT_CONFIG_FILE : DEFAULT_CONFIG_FILE); // Whether to hold wakelocks on all Prefetto tracing functions. You may want to enable // this if your device is not USB connected. This option prevents the device from diff --git a/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java b/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java index 895ddd14a..76fc1f945 100644 --- a/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java +++ b/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java @@ -18,6 +18,7 @@ package android.device.collectors; import static org.junit.Assert.assertNotNull; import android.device.collectors.annotations.OptionClass; +import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import androidx.annotation.VisibleForTesting; @@ -41,6 +42,12 @@ import org.junit.runner.Description; */ @OptionClass(alias = "screen-record-collector") public class ScreenRecordCollector extends BaseMetricListener { + // Quality is relative to screen resolution. + // * "medium" is 1/2 the resolution. + // * "low" is 1/8 the resolution. + // * Otherwise, use the resolution. + @VisibleForTesting static final String QUALITY_ARG = "video-quality"; + // Maximum parts per test (each part is <= 3min). @VisibleForTesting static final int MAX_RECORDING_PARTS = 5; private static final long VIDEO_TAIL_BUFFER = 500; @@ -51,13 +58,59 @@ public class ScreenRecordCollector extends BaseMetricListener { private RecordingThread mCurrentThread; + private String mVideoDimensions; + // Tracks the test iterations to ensure that each failure gets unique filenames. // Key: test description; value: number of iterations. private Map<String, Integer> mTestIterations = new HashMap<String, Integer>(); + public ScreenRecordCollector() { + super(); + } + + /** Constructors for overriding instrumentation arguments only. */ + @VisibleForTesting + ScreenRecordCollector(Bundle args) { + super(args); + } + @Override public void onTestRunStart(DataRecord runData, Description description) { mDestDir = createAndEmptyDirectory(OUTPUT_DIR); + + try { + long scaleDown = 1; + switch (getArgsBundle().getString(QUALITY_ARG, "default")) { + case "high": + scaleDown = 1; + break; + + case "medium": + scaleDown = 2; + break; + + case "low": + scaleDown = 8; + break; + + default: + return; + } + + // Display metrics isn't the absolute size, so use "wm size". + String[] dims = + getDevice() + .executeShellCommand("wm size") + .substring("Physical size: ".length()) + .trim() + .split("x"); + int width = Integer.parseInt(dims[0]); + int height = Integer.parseInt(dims[1]); + mVideoDimensions = String.format("%dx%d", width / scaleDown, height / scaleDown); + Log.v(getTag(), String.format("Using video dimensions: %s", mVideoDimensions)); + } catch (Exception e) { + Log.e(getTag(), "Failed to query the device dimensions. Using default.", e); + } } @Override @@ -167,9 +220,15 @@ public class ScreenRecordCollector extends BaseMetricListener { // Make sure not to block on this background command in the main thread so // that the test continues to run, but block in this thread so it does not // trigger a new screen recording session before the prior one completes. + String dimensionsOpt = + mVideoDimensions == null + ? "" + : String.format("--size=%s", mVideoDimensions); getDevice() .executeShellCommand( - String.format("screenrecord %s", output.getAbsolutePath())); + String.format( + "screenrecord %s %s", + dimensionsOpt, output.getAbsolutePath())); } } catch (IOException e) { throw new RuntimeException("Caught exception while screen recording."); diff --git a/libraries/device-collectors/src/main/java/android/device/collectors/ShowmapSnapshotListener.java b/libraries/device-collectors/src/main/java/android/device/collectors/ShowmapSnapshotListener.java index e2fb8abb6..371ef6e4b 100644 --- a/libraries/device-collectors/src/main/java/android/device/collectors/ShowmapSnapshotListener.java +++ b/libraries/device-collectors/src/main/java/android/device/collectors/ShowmapSnapshotListener.java @@ -63,7 +63,8 @@ public class ShowmapSnapshotListener extends BaseCollectionListener<String> { // 10810272 5400 1585 3800 168 264 1168 0 0 TOTAL // Default to collect rss, pss and private dirty. - private String mMemoryMetricNameIndex = "rss:1,pss:2,privatedirty:6"; + // private dirty includes addition of swap by default. + private String mMemoryMetricNameIndex = "rss:1,pss:2,privatedirty:6:7"; public ShowmapSnapshotListener() { createHelperInstance(mShowmapSnapshotHelper); diff --git a/libraries/device-collectors/src/test/java/android/device/collectors/BaseMetricListenerInstrumentedTest.java b/libraries/device-collectors/src/test/java/android/device/collectors/BaseMetricListenerInstrumentedTest.java index eba850178..5e73d15ad 100644 --- a/libraries/device-collectors/src/test/java/android/device/collectors/BaseMetricListenerInstrumentedTest.java +++ b/libraries/device-collectors/src/test/java/android/device/collectors/BaseMetricListenerInstrumentedTest.java @@ -351,6 +351,101 @@ public class BaseMetricListenerInstrumentedTest { assertEquals(0, resultBundle.size()); } + @MetricOption(group = "testGroup") + @Test + public void testSetUpAndCleanUpWithTestCycle() throws Exception { + // We use this bundle to mimic device state. We modify it in setUp() and + // check that this is maintained throughout the test. We remove the + // modification during cleanUp() and check if the bundle has indeed + // become empty again. + Bundle data = new Bundle(); + final String arg = "arg"; + final String value = "value"; + + BaseMetricListener listener = + new BaseMetricListener() { + public static final String SETUP_ARG = "arg"; + private static final String SETUP_VALUE = "value"; + + @Override + protected void onSetUp() { + data.putString(arg, value); + } + + @Override + protected void onCleanUp() { + data.remove(arg); + } + + @Override + public void onTestRunStart(DataRecord runData, Description description) { + assertEquals(value, data.getString(arg)); + } + + @Override + public void onTestRunEnd(DataRecord runData, Result result) { + assertEquals(value, data.getString(arg)); + } + + @Override + public void onTestStart(DataRecord testData, Description description) { + assertEquals(value, data.getString(arg)); + } + + @Override + public void onTestEnd(DataRecord testData, Description description) { + assertEquals(value, data.getString(arg)); + } + }; + + Description runDescription = Description.createSuiteDescription("run"); + Description test1Description = Description.createTestDescription("class", "method1"); + Description test2Description = Description.createTestDescription("class", "method2"); + // Simulate a test cycle. + listener.testRunStarted(runDescription); + listener.testStarted(test1Description); + listener.testFinished(test1Description); + listener.testStarted(test2Description); + listener.testFinished(test2Description); + listener.testRunFinished(new Result()); + listener.instrumentationRunFinished(System.out, new Bundle(), new Result()); + + assertFalse(data.containsKey(arg)); + } + + @MetricOption(group = "testGroup") + @Test + public void testSetUpAndCleanUpWithCallbacks() throws Exception { + // We use this bundle to mimic device state. We modify it in setUp() and + // check that this is maintained throughout the test. We remove the + // modification during cleanUp() and check if the bundle has indeed + // become empty again. + Bundle data = new Bundle(); + final String arg = "arg"; + final String value = "value"; + + BaseMetricListener listener = + new BaseMetricListener() { + public static final String SETUP_ARG = "arg"; + private static final String SETUP_VALUE = "value"; + + @Override + protected void onSetUp() { + data.putString(arg, value); + } + + @Override + protected void onCleanUp() { + data.remove(arg); + } + }; + + listener.setUp(); + assertEquals(value, data.getString(arg)); + listener.cleanUp(); + assertFalse(data.containsKey(arg)); + } + /** * Test annotation that allows to instantiate {@link MetricOption} for testing purpose. */ diff --git a/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java b/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java index 664a2947d..ce1bfa55c 100644 --- a/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java +++ b/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java @@ -21,8 +21,10 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.endsWith; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.matches; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -85,8 +87,13 @@ public class ScreenRecordCollectorTest { } } - private ScreenRecordCollector initListener() throws IOException { - ScreenRecordCollector listener = spy(new ScreenRecordCollector()); + private ScreenRecordCollector initListener(Bundle b) throws IOException { + ScreenRecordCollector listener; + if (b != null) { + listener = spy(new ScreenRecordCollector(b)); + } else { + listener = spy(new ScreenRecordCollector()); + } listener.setInstrumentation(mInstrumentation); doReturn(mLogDir).when(listener).createAndEmptyDirectory(anyString()); doReturn(0L).when(listener).getTailBuffer(); @@ -102,7 +109,7 @@ public class ScreenRecordCollectorTest { */ @Test public void testScreenRecord() throws Exception { - mListener = initListener(); + mListener = initListener(null); // Verify output directories are created on test run start. mListener.testRunStarted(mRunDesc); @@ -158,7 +165,7 @@ public class ScreenRecordCollectorTest { /** Test that screen recording is properly done for multiple tests and labels iterations. */ @Test public void testScreenRecord_multipleTests() throws Exception { - mListener = initListener(); + mListener = initListener(null); // Run through a sequence of `NUM_TEST_CASE` failing tests. mListener.testRunStarted(mRunDesc); @@ -190,4 +197,87 @@ public class ScreenRecordCollectorTest { } } } + + /** Test that quality options (high) are respected by screen recordings. */ + @Test + public void testScreenRecord_qualityHigh() throws Exception { + Bundle args = new Bundle(); + args.putString(ScreenRecordCollector.QUALITY_ARG, "high"); + mListener = initListener(args); + doReturn("Physical size: 1080x720 ").when(mDevice).executeShellCommand("wm size"); + + mListener.testRunStarted(mRunDesc); + mListener.testStarted(mTestDesc); + + // Delay verification by 100 ms to ensure the thread was started. + SystemClock.sleep(100); + verify(mDevice).executeShellCommand(matches("screenrecord --size=1080x720 .*video.mp4")); + } + + /** Test that quality options (medium) are respected by screen recordings. */ + @Test + public void testScreenRecord_qualityMedium() throws Exception { + Bundle args = new Bundle(); + args.putString(ScreenRecordCollector.QUALITY_ARG, "medium"); + mListener = initListener(args); + doReturn("Physical size: 1080x720 ").when(mDevice).executeShellCommand("wm size"); + + mListener.testRunStarted(mRunDesc); + mListener.testStarted(mTestDesc); + + // Delay verification by 100 ms to ensure the thread was started. + SystemClock.sleep(100); + verify(mDevice).executeShellCommand(matches("screenrecord --size=540x360 .*video.mp4")); + } + + /** Test that quality options (low) are respected by screen recordings. */ + @Test + public void testScreenRecord_qualityLow() throws Exception { + Bundle args = new Bundle(); + args.putString(ScreenRecordCollector.QUALITY_ARG, "low"); + mListener = initListener(args); + doReturn("Physical size: 1080x720 ").when(mDevice).executeShellCommand("wm size"); + + mListener.testRunStarted(mRunDesc); + mListener.testStarted(mTestDesc); + + // Delay verification by 100 ms to ensure the thread was started. + SystemClock.sleep(100); + verify(mDevice).executeShellCommand(matches("screenrecord --size=135x90 .*video.mp4")); + } + + /** Test that quality options (invalid) defaults to 1x. */ + @Test + public void testScreenRecord_qualityUnknown() throws Exception { + Bundle args = new Bundle(); + args.putString(ScreenRecordCollector.QUALITY_ARG, "other"); + mListener = initListener(args); + + mListener.testRunStarted(mRunDesc); + mListener.testStarted(mTestDesc); + + // Delay verification by 100 ms to ensure the thread was started. + SystemClock.sleep(100); + verify(mDevice, never()).executeShellCommand(matches("screenrecord.*size.*video.mp4")); + verify(mDevice, atLeastOnce()) + .executeShellCommand(not(matches("screenrecord .*video.mp4"))); + } + + /** Test that unexpected wm size contents defaults to unspecified size/quality option. */ + @Test + public void testScreenRecord_dimensionsInvalid() throws Exception { + Bundle args = new Bundle(); + args.putString(ScreenRecordCollector.QUALITY_ARG, "high"); + mListener = initListener(args); + doReturn("Physical size: axb ").when(mDevice).executeShellCommand("wm size"); + + mListener.testRunStarted(mRunDesc); + mListener.testStarted(mTestDesc); + + // Delay verification by 100 ms to ensure the thread was started. + SystemClock.sleep(100); + verify(mDevice, never()).executeShellCommand(matches("screenrecord.*size.*video.mp4")); + verify(mDevice, atLeastOnce()) + .executeShellCommand(not(matches("screenrecord .*video.mp4"))); + } } diff --git a/libraries/health/rules/Android.bp b/libraries/health/rules/Android.bp index aa1101035..8f889a86b 100644 --- a/libraries/health/rules/Android.bp +++ b/libraries/health/rules/Android.bp @@ -30,6 +30,7 @@ java_library { "package-helper", "launcher-aosp-tapl", "flickerlib", + "statsd-helper", ], srcs: ["src/**/*.java"], } @@ -46,6 +47,7 @@ java_library { "guava", "memory-helper", "package-helper", + "statsd-helper", "launcher-aosp-tapl", ], srcs: ["src/**/*.java"], diff --git a/libraries/health/rules/src/android/platform/test/rule/CoolDownRule.java b/libraries/health/rules/src/android/platform/test/rule/CoolDownRule.java new file mode 100644 index 000000000..fe52efb17 --- /dev/null +++ b/libraries/health/rules/src/android/platform/test/rule/CoolDownRule.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2021 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 android.platform.test.rule; + +import android.os.RemoteException; +import android.os.SystemClock; +import android.util.Log; +import androidx.annotation.VisibleForTesting; + +import com.android.helpers.ThermalHelper; + +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; + +import org.junit.runner.Description; + +/** + * This rule will cool DUT phone before a test case. + * + * <p>The rule takes a temperature name from command-line argument + * "cooldown-device-temperature-name" to check temperature. The spaces in temperature name must be + * replaced with '#' and '#' should be replaced with '##'. The rule unescapes argument value string + * of temperature name accordingly. + */ +public class CoolDownRule extends TestWatcher { + + private static final String LOG_TAG = CoolDownRule.class.getSimpleName(); + + // Interval in seconds, to poll for device temperature; defaults to 30s + @VisibleForTesting static final String POLL_INTERVAL_OPTION = "cooldown-poll-interval"; + private long mPollIntervalSecs = 30; + + // Max wait time in seconds, for device cool down to target temperature; defaults to 20 minutes + @VisibleForTesting static final String MAX_WAIT_OPTION = "cooldown-max-wait"; + private long mMaxWaitSecs = 60 * 20; + + // If test should be aborted if device is still above expected temperature; defaults to false + @VisibleForTesting static final String ABORT_ON_TIMEOUT_OPTION = "cooldown-abort-on-timeout"; + private boolean mAbortOnTimeout = false; + + // Additional time to wait in seconds, after temperature has reached to target; defaults to 30s + @VisibleForTesting static final String POST_IDLE_WAIT_OPTION = "cooldown-post-idle-wait"; + private long mPostIdleWaitSecs = 30; + + @VisibleForTesting + static final String DEVICE_TEMPERATURE_NAME_OPTION = "cooldown-device-temperature-name"; + + private String mDeviceTemperatureName = ""; + + // Target Temperature that device should have; defaults to 35 degree Celsius + @VisibleForTesting + static final String TARGET_TEMPERATURE_OPTION = "cooldown-target-temperature"; + + private int mTargetTemperature = 35; + + private ThermalHelper mThermalHelper; + + @Override + protected void starting(Description description) { + mDeviceTemperatureName = + CoolDownRule.unescapeOptionStr( + getArguments().getString(DEVICE_TEMPERATURE_NAME_OPTION, "")); + if (mDeviceTemperatureName.isEmpty()) { + throw new IllegalArgumentException("Missed device temperature name."); + } + mPollIntervalSecs = Long.valueOf(getArguments().getString(POLL_INTERVAL_OPTION, "30")); + mMaxWaitSecs = Long.valueOf(getArguments().getString(MAX_WAIT_OPTION, "1200")); + mAbortOnTimeout = + Boolean.valueOf(getArguments().getString(ABORT_ON_TIMEOUT_OPTION, "false")); + mPostIdleWaitSecs = Long.valueOf(getArguments().getString(POST_IDLE_WAIT_OPTION, "30")); + mTargetTemperature = + Integer.valueOf(getArguments().getString(TARGET_TEMPERATURE_OPTION, "35")); + if (mTargetTemperature > (100) || mTargetTemperature <= 0) { + throw new IllegalArgumentException( + String.format( + "Invalid target target temperature: %d degree Celsius", + mTargetTemperature)); + } + mThermalHelper = initThermalHelper(); + + try { + // Turn off the screen if necessary. + final boolean screenOnOriginal = getUiDevice().isScreenOn(); + if (screenOnOriginal) { + getUiDevice().sleep(); + } + + waitTemperature(); + + // Turn on the screen if necessary. + if (screenOnOriginal && !getUiDevice().isScreenOn()) { + getUiDevice().wakeUp(); + } + } catch (RemoteException e) { + throw new RuntimeException("Could not cool down device in time.", e); + } + } + + @VisibleForTesting + ThermalHelper initThermalHelper() { + return new ThermalHelper(); + } + + private void waitTemperature() { + long start = System.currentTimeMillis(); + long maxWaitMs = mMaxWaitSecs * 1000; + long intervalMs = mPollIntervalSecs * 1000; + int deviceTemperature = getDeviceTemperature(mDeviceTemperatureName); + + while ((deviceTemperature > mTargetTemperature) && (elapsedMs(start) < maxWaitMs)) { + Log.i( + LOG_TAG, + String.format( + "Temperature is still high actual %d/expected %d", + deviceTemperature, mTargetTemperature)); + sleepMs(intervalMs); + deviceTemperature = getDeviceTemperature(mDeviceTemperatureName); + } + + if (deviceTemperature <= mTargetTemperature) { + Log.i( + LOG_TAG, + String.format( + "Total time elapsed to get to %dc : %ds", + mTargetTemperature, (System.currentTimeMillis() - start) / 1000)); + } else { + Log.w( + LOG_TAG, + String.format( + "Temperature is still high, actual %d/expected %d; waiting after %ds", + deviceTemperature, + mTargetTemperature, + (System.currentTimeMillis() - start) / 1000)); + if (mAbortOnTimeout) { + throw new IllegalStateException( + String.format( + "Temperature is still high after wait timeout; actual %d/expected" + + " %d", + deviceTemperature, mTargetTemperature)); + } + } + + // Extra idle time after reaching the target to stabilize the system + sleepMs(mPostIdleWaitSecs * 1000); + Log.i( + LOG_TAG, + String.format( + "Done waiting, total time elapsed: %ds", + (System.currentTimeMillis() - start) / 1000)); + } + + @VisibleForTesting + void sleepMs(long milliSeconds) { + SystemClock.sleep(milliSeconds); + } + + @VisibleForTesting + long elapsedMs(long start) { + return System.currentTimeMillis() - start; + } + + /** + * @param name : temperature name in need. + * @return Device temperature in unit of millidegree Celsius + */ + @VisibleForTesting + int getDeviceTemperature(String name) { + return (int) mThermalHelper.getTemperature(name); + } + + /** + * @param input : Option value string to be unescaped. Option value string should be escaped by + * replacing ' ' (space) with '#' and '#' with '##'. Not support to unescaped consecutive + * spaces like ' ' and space before '#' like ' #'. + * @return Unescaped string. + */ + @VisibleForTesting + static String unescapeOptionStr(String input) { + final StringBuilder result = new StringBuilder(); + final StringCharacterIterator iterator = new StringCharacterIterator(input); + final char escape_char = '#'; + final char space_char = ' '; + char character = iterator.current(); + boolean escapeFlag = false; + + while (character != CharacterIterator.DONE) { + if (character == space_char) { + throw new IllegalArgumentException( + "Non-escaped option value string (please replace ' ' to '#'; '#' to '##'): " + + input); + } else if (escapeFlag) { + if (character == escape_char) { + result.append(escape_char); + } else { + result.append(space_char); + result.append(character); + } + escapeFlag = false; + } else if (character == escape_char) { + escapeFlag = true; + } else { + result.append(character); + } + character = iterator.next(); + } + if (escapeFlag) { + result.append(space_char); + } + return result.toString(); + } +} diff --git a/libraries/health/rules/tests/src/android/platform/test/rule/CoolDownRuleTest.java b/libraries/health/rules/tests/src/android/platform/test/rule/CoolDownRuleTest.java new file mode 100644 index 000000000..3bb3104b3 --- /dev/null +++ b/libraries/health/rules/tests/src/android/platform/test/rule/CoolDownRuleTest.java @@ -0,0 +1,388 @@ +/* + * Copyright (C) 2021 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 android.platform.test.rule; + +import android.os.Bundle; +import android.os.RemoteException; +import androidx.test.uiautomator.UiDevice; + +import com.android.helpers.ThermalHelper; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.runner.Description; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.model.Statement; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** Unit test the logic for {@link CoolDownRule} */ +@RunWith(JUnit4.class) +public class CoolDownRuleTest { + private static final int TARGET_TEMPERATURE = 35; + private static final int POLL_INTERVAL = 987; + private static final int IDLE_WAIT = 123; + private static final String TEMPERATURE_NAME = "test temperature sensor"; + private static final String TEMPERATURE_NAME_ESCAPED = "test#temperature#sensor"; + private static final int OVERHEAT_COUNT = 3; + + private static final String OPS_SCREEN_ON = "screen On"; + private static final String OPS_SCREEN_OFF = "screen Off"; + private static final String OPS_TEST = "test"; + private static final String OPS_SLEEP_INTERVAL = "sleep 987000 milli seconds"; + private static final String OPS_SLEEP_IDLE = "sleep 123000 milli seconds"; + + private final ThermalHelper mThermalHelper = mock(ThermalHelper.class); + + /** Tests that this rule will complete cool down as expected steps. */ + @Test + public void testCoolDownNormal() throws Throwable { + boolean screenOn = true; + boolean abortOnTimeout = false; + int maxWait = (OVERHEAT_COUNT * POLL_INTERVAL) + 5; + TestableRule rule = getDefaultRule(screenOn, maxWait, abortOnTimeout); + + doAnswer(new TemperatureAnswer(TARGET_TEMPERATURE, OVERHEAT_COUNT)) + .when(mThermalHelper) + .getTemperature(TEMPERATURE_NAME); + rule.apply(rule.getTestStatement(), Description.createTestDescription("clzz", "mthd")) + .evaluate(); + assertThat(rule.getOperations()) + .containsExactly( + OPS_SCREEN_OFF, + "get device temperature degree: 46", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 41", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 37", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 33", + OPS_SLEEP_IDLE, + OPS_SCREEN_ON, + OPS_TEST) + .inOrder(); + } + + /** Tests that this rule will fail to cool down due to timeout as expected steps. */ + @Test + public void testCoolDownTimeout() throws Throwable { + boolean screenOn = true; + boolean abortOnTimeout = false; + int maxWait = (OVERHEAT_COUNT * POLL_INTERVAL) - 5; + TestableRule rule = getDefaultRule(screenOn, maxWait, abortOnTimeout); + + double cooldownOffset = -1.0; // heat up instead of cool down + doAnswer(new TemperatureAnswer(TARGET_TEMPERATURE, OVERHEAT_COUNT, cooldownOffset)) + .when(mThermalHelper) + .getTemperature(TEMPERATURE_NAME); + rule.apply(rule.getTestStatement(), Description.createTestDescription("clzz", "mthd")) + .evaluate(); + assertThat(rule.getOperations()) + .containsExactly( + OPS_SCREEN_OFF, + "get device temperature degree: 37", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 38", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 39", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 40", + OPS_SLEEP_IDLE, + OPS_SCREEN_ON, + OPS_TEST) + .inOrder(); + } + + /** + * Tests that this rule will fail to cool down due to timeout and throw exception to abort the + * test as expected steps. + */ + @Test + public void testCoolDownTimeoutAbort() throws Throwable { + boolean screenOn = true; + boolean abortOnTimeout = true; + int maxWait = (OVERHEAT_COUNT * POLL_INTERVAL) - 5; + TestableRule rule = getDefaultRule(screenOn, maxWait, abortOnTimeout); + + double cooldownOffset = -1.0; // heat up instead of cool down + doAnswer(new TemperatureAnswer(TARGET_TEMPERATURE, OVERHEAT_COUNT, cooldownOffset)) + .when(mThermalHelper) + .getTemperature(TEMPERATURE_NAME); + try { + rule.apply(rule.getTestStatement(), Description.createTestDescription("clzz", "mthd")) + .evaluate(); + fail("An exception should have been thrown."); + } catch (IllegalStateException e) { + assertThat(rule.getOperations()) + .containsExactly( + OPS_SCREEN_OFF, + "get device temperature degree: 37", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 38", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 39", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 40") + .inOrder(); + } + } + + /** + * Tests that this rule will complete cool down without turning off screen as expected steps. + */ + @Test + public void testCoolDownScreenOff() throws Throwable { + boolean screenOn = false; + boolean abortOnTimeout = false; + int maxWait = (OVERHEAT_COUNT * POLL_INTERVAL) + 5; + TestableRule rule = getDefaultRule(screenOn, maxWait, abortOnTimeout); + + doAnswer(new TemperatureAnswer(TARGET_TEMPERATURE, OVERHEAT_COUNT)) + .when(mThermalHelper) + .getTemperature(TEMPERATURE_NAME); + rule.apply(rule.getTestStatement(), Description.createTestDescription("clzz", "mthd")) + .evaluate(); + assertThat(rule.getOperations()) + .containsExactly( + "get device temperature degree: 46", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 41", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 37", + OPS_SLEEP_INTERVAL, + "get device temperature degree: 33", + OPS_SLEEP_IDLE, + OPS_TEST) + .inOrder(); + } + /** Tests to confirm option value strings will be escaped correctly. */ + @Test + public void testEscapedOptionStrs() throws Throwable { + Map<String, String> escape_test_cases = new HashMap<String, String>(); + escape_test_cases.put("", ""); + escape_test_cases.put("#", " "); + escape_test_cases.put("##", "#"); + escape_test_cases.put("prefix#", "prefix "); + escape_test_cases.put("prefix##", "prefix#"); + escape_test_cases.put("#postfix", " postfix"); + escape_test_cases.put("##postfix", "#postfix"); + escape_test_cases.put("prefix#postfix", "prefix postfix"); + escape_test_cases.put("prefix##postfix", "prefix#postfix"); + escape_test_cases.put("###", "# "); + escape_test_cases.put("####", "##"); + escape_test_cases.put("prefix###", "prefix# "); + escape_test_cases.put("prefix####", "prefix##"); + escape_test_cases.put("###postfix", "# postfix"); + escape_test_cases.put("####postfix", "##postfix"); + escape_test_cases.put("prefix###postfix", "prefix# postfix"); + escape_test_cases.put("prefix####postfix", "prefix##postfix"); + escape_test_cases.put("#####", "## "); + escape_test_cases.put("######", "###"); + for (String input : escape_test_cases.keySet()) { + String expected_output = escape_test_cases.get(input); + String actual_output = CoolDownRule.unescapeOptionStr(input); + assertThat(expected_output.equals(actual_output)).isTrue(); + } + } + /** Tests to detect unescaped option value strings. */ + @Test + public void testNonEscapeOptionStrs() throws Throwable { + String inputs[] = + new String[] { + " ", + "prefix postfix", + " #", + "# ", + "prefix #", + "# postfix", + "prefix #postfix", + "prefix# postfix", + " ##", + "## ", + "# #", + " prefix##", + "##postfix ", + "prefix ##postfix", + "prefix# #postfix", + "prefix## postfix", + " ###", + "# ##", + "## #", + "### ", + }; + + for (String input : inputs) { + assertThrows( + IllegalArgumentException.class, () -> CoolDownRule.unescapeOptionStr(input)); + } + } + + private TestableRule getDefaultRule(boolean screenOn, int maxWait, boolean abortOnTimeout) { + TestableRule rule = new TestableRule(screenOn, mThermalHelper); + rule.addArg(CoolDownRule.POLL_INTERVAL_OPTION, String.valueOf(POLL_INTERVAL)); + rule.addArg(CoolDownRule.MAX_WAIT_OPTION, String.valueOf(maxWait)); + rule.addArg(CoolDownRule.ABORT_ON_TIMEOUT_OPTION, String.valueOf(abortOnTimeout)); + rule.addArg(CoolDownRule.POST_IDLE_WAIT_OPTION, String.valueOf(IDLE_WAIT)); + rule.addArg(CoolDownRule.DEVICE_TEMPERATURE_NAME_OPTION, TEMPERATURE_NAME_ESCAPED); + rule.addArg(CoolDownRule.TARGET_TEMPERATURE_OPTION, String.valueOf(TARGET_TEMPERATURE)); + return rule; + } + + private static class TestableRule extends CoolDownRule { + private final UiDevice mUiDevice; + + private List<String> mOperations = new ArrayList<>(); + private Bundle mBundle = new Bundle(); + private boolean mIsScreenOn = true; + private long mTotalSleepMs = 0; + private final ThermalHelper mThermalHelper; + + private TestableRule() { + this(true, null); + } + + public TestableRule(boolean screenOn, ThermalHelper thermalHelper) { + mUiDevice = mock(UiDevice.class); + mIsScreenOn = screenOn; + mThermalHelper = thermalHelper; + } + + @Override + protected UiDevice getUiDevice() { + try { + when(mUiDevice.isScreenOn()).thenReturn(mIsScreenOn); + doAnswer( + invocation -> { + return setScreen(false); + }) + .when(mUiDevice) + .sleep(); + doAnswer( + invocation -> { + return setScreen(true); + }) + .when(mUiDevice) + .wakeUp(); + } catch (RemoteException e) { + throw new RuntimeException("Could not unlock device.", e); + } + return mUiDevice; + } + + @Override + ThermalHelper initThermalHelper() { + return mThermalHelper; + } + + @Override + protected Bundle getArguments() { + return mBundle; + } + + @Override + int getDeviceTemperature(String name) { + int value = super.getDeviceTemperature(name); + mOperations.add(String.format("get device temperature degree: %d", value)); + return value; + } + + @Override + protected void sleepMs(long milliSeconds) { + mOperations.add(String.format("sleep %d milli seconds", milliSeconds)); + mTotalSleepMs += milliSeconds; + } + + @Override + protected long elapsedMs(long start) { + long ms = super.elapsedMs(start); + return (mTotalSleepMs + ms); + } + + public List<String> getOperations() { + return mOperations; + } + + public void addArg(String key, String value) { + mBundle.putString(key, value); + } + + public Object setScreen(boolean screenOn) { + mIsScreenOn = screenOn; + mOperations.add(mIsScreenOn ? OPS_SCREEN_ON : OPS_SCREEN_OFF); + return null; + } + + public Statement getTestStatement() { + return new Statement() { + @Override + public void evaluate() throws Throwable { + mOperations.add(OPS_TEST); + } + }; + } + } + + private static class TemperatureAnswer implements Answer { + private static final double INIT_OFFSET = 2.0; + private static final double DEFAULT_COOLDOWN_OFFSET = 4.4; + + private final double targetTemperature; + private final double cooldownOffset; + private final int overHeatCount; + + private double temperature = 0.0; + + private TemperatureAnswer() { + this(36.0, 3, DEFAULT_COOLDOWN_OFFSET); + } + + public TemperatureAnswer(double targetTemperatureIn, int overHeatCount) { + this(targetTemperatureIn, overHeatCount, DEFAULT_COOLDOWN_OFFSET); + } + + public TemperatureAnswer( + double targetTemperatureIn, int overHeatCountIn, double cooldownOffsetIn) { + targetTemperature = targetTemperatureIn; + overHeatCount = overHeatCountIn; + cooldownOffset = cooldownOffsetIn; + + if (cooldownOffset > 0) { // cool down by turn + temperature = targetTemperature - INIT_OFFSET; + temperature += cooldownOffset * overHeatCount; + } else { // from warm to warmer + temperature = targetTemperature + INIT_OFFSET; + } + } + + @Override + public Double answer(InvocationOnMock invocation) { + double result = temperature; + temperature -= cooldownOffset; + return Double.valueOf(result); + } + } +} diff --git a/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Functional.java b/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Functional.java new file mode 100644 index 000000000..4043b375c --- /dev/null +++ b/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Functional.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 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 android.platform.test.microbenchmark; + +import org.junit.internal.AssumptionViolatedException; +import org.junit.internal.runners.statements.RunAfters; +import org.junit.internal.runners.statements.RunBefores; +import org.junit.runner.Description; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.Statement; +import org.junit.runners.model.TestClass; + +import java.util.List; + +/** + * Runner for functional tests that's compatible with annotations used in microbenchmark + * tests. @Before/@After are nested inside @NoMetricBefore/@NoMetricAfter. TODO(b/205019000): this + * class is seen as a temporary solution, and is supposed to be eventually replaced with a permanent + * one. + */ +public class Functional extends BlockJUnit4ClassRunner { + public Functional(Class<?> klass) throws InitializationError { + super(new TestClass(klass)); + } + + @Override + protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) { + statement = super.withBefores(method, target, statement); + + // Add @NoMetricBefore's + List<FrameworkMethod> befores = + getTestClass().getAnnotatedMethods(Microbenchmark.NoMetricBefore.class); + return befores.isEmpty() ? statement : new RunBefores(statement, befores, target); + } + + @Override + protected Statement withAfters(FrameworkMethod method, Object target, Statement statement) { + // Add @NoMetricAfter's + List<FrameworkMethod> afters = + getTestClass().getAnnotatedMethods(Microbenchmark.NoMetricAfter.class); + statement = afters.isEmpty() ? statement : new RunAfters(statement, afters, target); + + return super.withAfters(method, target, statement); + } + + @Override + protected Statement classBlock(RunNotifier notifier) { + final Statement statement = super.classBlock(notifier); + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + statement.evaluate(); + } catch (Throwable e) { + // We get here if class-level (static) @Before/@Afters or rules fail. + // To ensure a test output that looks correctly to TF, we need to properly + // notify 'notifier' about all test methods. + // We'll report that all tests methods failed with the error that comes from + // the class block. + final List<FrameworkMethod> children = getChildren(); + if (children.isEmpty()) { + // If there are no test methods, just rethrow. + throw e; + } + + for (FrameworkMethod testMethod : children) { + final Description description = describeChild(testMethod); + notifier.fireTestStarted(description); + if (e instanceof AssumptionViolatedException) { + notifier.fireTestAssumptionFailed(new Failure(description, e)); + } else { + notifier.fireTestFailure(new Failure(description, e)); + } + notifier.fireTestFinished(description); + } + } + } + }; + } +} diff --git a/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java b/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java index 7ad17de98..7c46a1225 100644 --- a/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java +++ b/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java @@ -53,26 +53,32 @@ import org.junit.runners.model.Statement; import org.junit.rules.RunRules; /** - * The {@code Microbenchmark} runner allows you to run test methods repeatedly and with {@link - * TightMethodRule}s in order to reliably measure a specific test method in isolation. Samples are - * soon to follow. + * The {@code Microbenchmark} runner allows you to run individual JUnit {@code @Test} methods + * repeatedly like a benchmark test in order to get more repeatable, reliable measurements, or to + * ensure it passes when run many times. This runner supports a number of customized features that + * enable better benchmarking and better integration with surrounding tools. + * + * <p>One iteration represents a single pass of a test method. The number of iterations and how + * those iterations get renamed are configurable with options listed at the top of the source code. + * Some custom annotations also exist to enable this runner to replicate JUnit's functionality with + * modified behaviors related to running repeated methods. These are documented separately below + * with the corresponding annotations, {@link @NoMetricBefore}, {@link @NoMetricAfter}, and + * {@link @TightMethodRule}. + * + * <p>Finally, this runner supports some power-specific testing features used to denoise (also + * documented below), and can be configured to terminate early if the battery drops too low or if + * any test fails. */ public class Microbenchmark extends BlockJUnit4ClassRunner { private static final String LOG_TAG = Microbenchmark.class.getSimpleName(); - @VisibleForTesting static final String ITERATION_SEP_OPTION = "iteration-separator"; - @VisibleForTesting static final String ITERATION_SEP_DEFAULT = "$"; - // A constant to indicate that the iteration number is not set. - @VisibleForTesting static final int ITERATION_NOT_SET = -1; - public static final String RENAME_ITERATION_OPTION = "rename-iterations"; private static final Statement EMPTY_STATEMENT = new Statement() { @Override public void evaluate() throws Throwable {} }; - @VisibleForTesting static final String MIN_BATTERY_LEVEL_OPTION = "min-battery"; - @VisibleForTesting static final String MAX_BATTERY_DRAIN_OPTION = "max-battery-drain"; + // Use these options to inject rules at runtime via the command line. For details, please see // documentation for DynamicRuleChain. @VisibleForTesting static final String DYNAMIC_OUTER_CLASS_RULES_OPTION = "outer-class-rules"; @@ -80,6 +86,18 @@ public class Microbenchmark extends BlockJUnit4ClassRunner { @VisibleForTesting static final String DYNAMIC_OUTER_TEST_RULES_OPTION = "outer-test-rules"; @VisibleForTesting static final String DYNAMIC_INNER_TEST_RULES_OPTION = "inner-test-rules"; + // Renames repeated test methods as <description><separator><iteration> (if set to true). + public static final String RENAME_ITERATION_OPTION = "rename-iterations"; + @VisibleForTesting static final String ITERATION_SEP_OPTION = "iteration-separator"; + @VisibleForTesting static final String ITERATION_SEP_DEFAULT = "$"; + + // Stop running tests after any failure is encountered (if set to true). + private static final String TERMINATE_ON_TEST_FAIL_OPTION = "terminate-on-test-fail"; + + // Don't start new iterations if the battery falls below this value (if set). + @VisibleForTesting static final String MIN_BATTERY_LEVEL_OPTION = "min-battery"; + // Don't start new iterations if the battery already fell more than this value (if set). + @VisibleForTesting static final String MAX_BATTERY_DRAIN_OPTION = "max-battery-drain"; // Options for aligning with the battery charge (coulomb) counter for power tests. We want to // start microbenchmarks just after the coulomb counter has decremented to account for the // counter being quantized. The counter most accurately reflects the true value just after it @@ -87,8 +105,6 @@ public class Microbenchmark extends BlockJUnit4ClassRunner { private static final String ALIGN_WITH_CHARGE_COUNTER_OPTION = "align-with-charge-counter"; private static final String COUNTER_DECREMENT_TIMEOUT_OPTION = "counter-decrement-timeout_ms"; - private static final String TERMINATE_ON_TEST_FAIL_OPTION = "terminate-on-test-fail"; - private final String mIterationSep; private final Bundle mArguments; private final boolean mRenameIterations; diff --git a/libraries/system-helpers/sysui-helper/src/android/system/helpers/OverviewHelper.java b/libraries/system-helpers/sysui-helper/src/android/system/helpers/OverviewHelper.java index 219e0a957..14c66de3b 100644 --- a/libraries/system-helpers/sysui-helper/src/android/system/helpers/OverviewHelper.java +++ b/libraries/system-helpers/sysui-helper/src/android/system/helpers/OverviewHelper.java @@ -171,7 +171,7 @@ public class OverviewHelper { scrollToTopOfRecents(recentsView); // click clear all UiObject2 clearAll = mDevice.wait(Until.findObject(By.text("CLEAR ALL")),TIMEOUT); - if (!clearAll.equals(null)) { + if (clearAll != null) { clearAll.click(); } Thread.sleep(TIMEOUT); @@ -244,4 +244,4 @@ public class OverviewHelper { .setPackage(recentsComponent.getPackageName()); return pm.resolveService(intent, 0) != null; } -}
\ No newline at end of file +} diff --git a/tests/automotive/functional/mediacenter/Android.bp b/tests/automotive/functional/mediacenter/Android.bp index ada76da2f..5e3b35cdc 100644 --- a/tests/automotive/functional/mediacenter/Android.bp +++ b/tests/automotive/functional/mediacenter/Android.bp @@ -22,6 +22,7 @@ android_test { static_libs: [ "androidx.test.runner", "androidx.test.rules", + "automotive-home-helper", "automotive-media-center-app-helper", "automotive-utility-helper", "app-helpers-auto-interfaces", diff --git a/tests/automotive/functional/mediacenter/src/android/platform/tests/OpenAppFromMediaCenterTest.java b/tests/automotive/functional/mediacenter/src/android/platform/tests/OpenAppFromMediaCenterTest.java new file mode 100644 index 000000000..ad183cfca --- /dev/null +++ b/tests/automotive/functional/mediacenter/src/android/platform/tests/OpenAppFromMediaCenterTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2021 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 android.platform.tests; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import android.platform.helpers.AutoUtility; +import android.platform.helpers.IAutoHomeHelper; +import android.platform.helpers.IAutoMediaHelper; +import android.platform.helpers.HelperAccessor; +import android.platform.helpers.HomeHelperImpl; +import android.platform.test.option.StringOption; +import androidx.test.runner.AndroidJUnit4; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class OpenAppFromMediaCenterTest { + private static final String BLUETOOTH_APP = "bluetooth-app"; + private static final String MEDIA_APPS = "media-apps"; + + private static final String DEFAULT_MEDIA_APP = "Bluetooth Audio"; + private static final String DEFAULT_LIST_OF_MEDIA_APPS = "Bluetooth Audio, Radio"; + + @ClassRule + public static StringOption mMediaDefaultApp = + new StringOption(BLUETOOTH_APP).setRequired(false); + @ClassRule + public static StringOption mMediaApps = new StringOption(MEDIA_APPS).setRequired(false); + + private HelperAccessor<IAutoMediaHelper> mMediaCenterHelper; + private HelperAccessor<IAutoHomeHelper> mAutoHomeHelper; + + public OpenAppFromMediaCenterTest() { + mMediaCenterHelper = new HelperAccessor<>(IAutoMediaHelper.class); + mAutoHomeHelper = new HelperAccessor<>(IAutoHomeHelper.class); + } + + @BeforeClass + public static void exitSuw() { + AutoUtility.exitSuw(); + } + + @Test + public void testOpenMediaAppFromMediaWidget() { + // Use preinstalled "Bluetooth Audio" app + mAutoHomeHelper.get().openMediaWidget(); + assertTrue("Not a media app", + mMediaCenterHelper.get().getMediaAppTitle().equals(getDefaultMediaAppName())); + } + + @Test + public void testMediaAppPresentInMediaGrid() { + mAutoHomeHelper.get().openMediaWidget(); + mMediaCenterHelper.get().openMediaAppMenuItems(); + assertTrue("Incorrect Media apps in Grid", + mMediaCenterHelper.get().areMediaAppsPresent(getExpectedMediaAppNames())); + } + + private String getDefaultMediaAppName() { + String mediaAppName = DEFAULT_MEDIA_APP; + if (mMediaDefaultApp != null + && mMediaDefaultApp.get() != null && !mMediaDefaultApp.get().isEmpty()) { + mediaAppName = mMediaDefaultApp.get(); + } + return mediaAppName; + } + + private List<String> getExpectedMediaAppNames() { + String mediaAppNames = DEFAULT_LIST_OF_MEDIA_APPS; + if (mMediaApps != null && mMediaApps.get() != null && !mMediaApps.get().isEmpty()) { + // Get list of media apps from String options if passed. + mediaAppNames = mMediaApps.get(); + } + String[] mediaAppNamesList = mediaAppNames.trim().split("\\s*,\\s*"); + return Arrays.asList(mediaAppNamesList); + } +} diff --git a/tests/automotive/health/evs/tests/Android.bp b/tests/automotive/functional/multiuser/Android.bp index 544ba268e..c97679f12 100644 --- a/tests/automotive/health/evs/tests/Android.bp +++ b/tests/automotive/functional/multiuser/Android.bp @@ -17,23 +17,30 @@ package { } android_test { - name: "AndroidAutomotiveEvsScenarioTests", + name: "AndroidAutomotiveMultiuserTests", min_sdk_version: "24", static_libs: [ "androidx.test.runner", "androidx.test.rules", - "automotive-settings-scenarios", - "automotive-evs-scenarios", + "automotive-multiuser-scenarios", + "automotive-utility-helper", "automotive-health-test-rules", "automotive-settings-app-helper", + "app-helpers-common-interfaces", "app-helpers-auto-interfaces", "ub-uiautomator", "collector-device-lib-platform", "common-platform-scenarios", "common-platform-scenario-tests", "microbenchmark-device-lib", + "platform-test-rules", "platform-test-options", + "multi-user-helper", + "microbenchmark-device-lib", + "longevity-device-lib", ], srcs: ["src/**/*.java"], + certificate: "platform", test_suites: ["catbox"], + privileged: true, } diff --git a/tests/automotive/functional/multiuser/AndroidManifest.xml b/tests/automotive/functional/multiuser/AndroidManifest.xml new file mode 100644 index 000000000..3a5447104 --- /dev/null +++ b/tests/automotive/functional/multiuser/AndroidManifest.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2021 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="android.platform.tests" > + <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" /> + <uses-permission android:name="android.permission.DUMP" /> + <uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"/> + <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> + <uses-permission android:name="android.Manifest.permission.MANAGE_USERS" /> + <uses-permission android:name="android.permission.MANAGE_USERS" /> + <uses-permission android:name="android.permission.CREATE_USERS" /> + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> + + <application> + <uses-library android:name="android.test.runner"/> + </application> + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.platform.tests" + android:label="Android Automotive Multiuser Functional Tests" /> +</manifest>
\ No newline at end of file diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/AddUserQuickSettings.java b/tests/automotive/functional/multiuser/src/android/platform/tests/AddUserQuickSettings.java index a6505a4f0..637c76f76 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/AddUserQuickSettings.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/AddUserQuickSettings.java @@ -14,16 +14,17 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertTrue; import android.content.pm.UserInfo; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; +import android.platform.scenario.multiuser.MultiUserConstants; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.BeforeClass; @@ -32,19 +33,17 @@ import org.junit.runner.RunWith; /** * This test will create user through API and delete the same user from UI - * - * <p>It should be running under user 0, otherwise instrumentation may be killed after user - * switched. + * <p> Set system property to run MU test: adb shell setprop fw.stop_bg_users_on_switch 0 */ @RunWith(AndroidJUnit4.class) public class AddUserQuickSettings { private final MultiUserHelper mMultiUserHelper = MultiUserHelper.getInstance(); - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; public AddUserQuickSettings() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -62,11 +61,11 @@ public class AddUserQuickSettings { public void testAddUser() throws Exception { // create new user quick settings UserInfo initialUser = mMultiUserHelper.getCurrentForegroundUserInfo(); - mProfilesHelper.get().addProfileQuickSettings(initialUser.name); + mUsersHelper.get().addUserQuickSettings(initialUser.name); // switched to new user UserInfo newUser = mMultiUserHelper.getCurrentForegroundUserInfo(); // switch from new user to initial user - mProfilesHelper.get().switchProfile(newUser.name, initialUser.name); + mUsersHelper.get().switchUser(newUser.name, initialUser.name); // verify new user is seen in list of users assertTrue(mMultiUserHelper.getUserByName(newUser.name) != null); // remove new user diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/AddUserSettings.java b/tests/automotive/functional/multiuser/src/android/platform/tests/AddUserSettings.java index bbb75b2ef..5e6e1205e 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/AddUserSettings.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/AddUserSettings.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertTrue; @@ -22,9 +22,10 @@ import android.content.pm.UserInfo; import android.platform.helpers.AutoConfigConstants; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; +import android.platform.scenario.multiuser.MultiUserConstants; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; @@ -34,19 +35,17 @@ import org.junit.runner.RunWith; /** * This test will create user through API and delete the same user from UI - * - * <p>It should be running under user 0, otherwise instrumentation may be killed after user - * switched. + * <p> Set system property to run MU test: adb shell setprop fw.stop_bg_users_on_switch 0 */ @RunWith(AndroidJUnit4.class) public class AddUserSettings { private final MultiUserHelper mMultiUserHelper = MultiUserHelper.getInstance(); - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; public AddUserSettings() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -69,11 +68,11 @@ public class AddUserSettings { public void testAddUser() throws Exception { // create new user UserInfo initialUser = mMultiUserHelper.getCurrentForegroundUserInfo(); - mProfilesHelper.get().addProfile(); + mUsersHelper.get().addUser(); // switched to new user UserInfo newUser = mMultiUserHelper.getCurrentForegroundUserInfo(); // switch from new user to initial user - mProfilesHelper.get().switchProfile(newUser.name, initialUser.name); + mUsersHelper.get().switchUser(newUser.name, initialUser.name); // verify new user is seen in list of users assertTrue(mMultiUserHelper.getUserByName(newUser.name) != null); // remove new user diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteAdminUser.java b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteAdminUser.java index 0b48dd355..f73cb554e 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteAdminUser.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteAdminUser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertFalse; @@ -22,9 +22,10 @@ import android.os.SystemClock; import android.platform.helpers.AutoConfigConstants; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; +import android.platform.scenario.multiuser.MultiUserConstants; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.BeforeClass; @@ -33,9 +34,6 @@ import org.junit.runner.RunWith; /** * This test will create user through API and delete the same user from UI - * - * <p>It should be running under user 0, otherwise instrumentation may be killed after user - * switched. */ @RunWith(AndroidJUnit4.class) public class DeleteAdminUser { @@ -43,12 +41,12 @@ public class DeleteAdminUser { private static final String userName = MultiUserConstants.SECONDARY_USER_NAME; private static final int WAIT_TIME = 10000; private final MultiUserHelper mMultiUserHelper = MultiUserHelper.getInstance(); - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; private int mTargetUserId; public DeleteAdminUser() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -69,10 +67,10 @@ public class DeleteAdminUser { SystemClock.sleep(WAIT_TIME); // make the new user admin and delete new user mSettingHelper.get().openSetting(AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS); - mProfilesHelper.get().makeUserAdmin(userName); + mUsersHelper.get().makeUserAdmin(userName); mSettingHelper.get().openSetting(AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS); - mProfilesHelper.get().deleteProfile(userName); + mUsersHelper.get().deleteUser(userName); // verify new user was deleted - assertFalse(mProfilesHelper.get().isProfilePresent(userName)); + assertFalse(mUsersHelper.get().isUserPresent(userName)); } } diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteCurrentNonAdminUser.java b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteCurrentNonAdminUser.java index a359cc2ad..a0111b875 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteCurrentNonAdminUser.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteCurrentNonAdminUser.java @@ -14,17 +14,19 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertTrue; +import android.os.SystemClock; import android.content.pm.UserInfo; import android.platform.helpers.AutoConfigConstants; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; +import android.platform.scenario.multiuser.MultiUserConstants; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; @@ -34,19 +36,20 @@ import org.junit.runner.RunWith; /** * This test will create user through API and delete the same user from UI - * - * <p>It should be running under user 0, otherwise instrumentation may be killed after user - * switched. + * <p> Set system property to run MU test: adb shell setprop fw.stop_bg_users_on_switch 0 */ @RunWith(AndroidJUnit4.class) public class DeleteCurrentNonAdminUser { + private static final String userName = MultiUserConstants.SECONDARY_USER_NAME; + private static final int WAIT_TIME = 10000; private final MultiUserHelper mMultiUserHelper = MultiUserHelper.getInstance(); - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; + private int mTargetUserId; public DeleteCurrentNonAdminUser() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -55,11 +58,6 @@ public class DeleteCurrentNonAdminUser { AutoUtility.exitSuw(); } - @Before - public void openAccountsFacet() { - mSettingHelper.get().openSetting(AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS); - } - @After public void goBackToHomeScreen() { mSettingHelper.get().goBackToSettingsScreen(); @@ -67,16 +65,20 @@ public class DeleteCurrentNonAdminUser { @Test public void testRemoveUserSelf() throws Exception { - // add new user UserInfo initialUser = mMultiUserHelper.getCurrentForegroundUserInfo(); - mProfilesHelper.get().addProfile(); - // switched to new user and user deleted self + // add new user + mTargetUserId = mMultiUserHelper.createUser(userName, false); + SystemClock.sleep(WAIT_TIME); + // switch to new user + mMultiUserHelper.switchAndWaitForStable( + mTargetUserId, MultiUserConstants.WAIT_FOR_IDLE_TIME_MS); UserInfo newUser = mMultiUserHelper.getCurrentForegroundUserInfo(); + // user deleted self mSettingHelper.get().openSetting(AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS); - mProfilesHelper.get().deleteCurrentProfile(); + mUsersHelper.get().deleteCurrentUser(); // goes to guest user, switch back to initial user - UserInfo guestUser = mMultiUserHelper.getCurrentForegroundUserInfo(); - mProfilesHelper.get().switchProfile(guestUser.name, initialUser.name); + mMultiUserHelper.switchAndWaitForStable( + initialUser.id, MultiUserConstants.WAIT_FOR_IDLE_TIME_MS); // verify that user is deleted assertTrue(mMultiUserHelper.getUserByName(newUser.name) == null); } diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteGuestNotAllowed.java b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteGuestNotAllowed.java index 03ecfbcc6..71ea34388 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteGuestNotAllowed.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteGuestNotAllowed.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertFalse; @@ -22,9 +22,10 @@ import android.content.pm.UserInfo; import android.platform.helpers.AutoConfigConstants; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; +import android.platform.scenario.multiuser.MultiUserConstants; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; @@ -34,19 +35,16 @@ import org.junit.runner.RunWith; /** * This test will create user through API and delete the same user from UI - * - * <p>It should be running under user 0, otherwise instrumentation may be killed after user - * switched. */ @RunWith(AndroidJUnit4.class) public class DeleteGuestNotAllowed { private static final String guestUser = MultiUserConstants.GUEST_NAME; - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; public DeleteGuestNotAllowed() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -68,6 +66,6 @@ public class DeleteGuestNotAllowed { @Test public void testDeleteGuestNotAllowed() throws Exception { // verify that guest user cannot be seen and deleted from list of profiles - assertFalse(mProfilesHelper.get().isProfilePresent(guestUser)); + assertFalse(mUsersHelper.get().isUserPresent(guestUser)); } } diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteGuestSelfNotAllowed.java b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteGuestSelfNotAllowed.java index 5413fda8d..b31cbaa5a 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteGuestSelfNotAllowed.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteGuestSelfNotAllowed.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; @@ -23,9 +23,10 @@ import android.content.pm.UserInfo; import android.platform.helpers.AutoConfigConstants; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; +import android.platform.scenario.multiuser.MultiUserConstants; import android.util.Log; import androidx.test.runner.AndroidJUnit4; import org.junit.After; @@ -35,20 +36,18 @@ import org.junit.runner.RunWith; /** * This test will create user through API and delete the same user from UI - * - * <p>It should be running under user 0, otherwise instrumentation may be killed after user - * switched. + * <p> Set system property to run MU test: adb shell setprop fw.stop_bg_users_on_switch 0 */ @RunWith(AndroidJUnit4.class) public class DeleteGuestSelfNotAllowed { private static final String guestUser = MultiUserConstants.GUEST_NAME; private final MultiUserHelper mMultiUserHelper = MultiUserHelper.getInstance(); - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; public DeleteGuestSelfNotAllowed() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -66,14 +65,14 @@ public class DeleteGuestSelfNotAllowed { public void testDeleteGuestNotAllowed() throws Exception { UserInfo previousUser = mMultiUserHelper.getCurrentForegroundUserInfo(); // switch to Guest and verify the user switch - mProfilesHelper.get().switchProfile(previousUser.name, guestUser); + mUsersHelper.get().switchUser(previousUser.name, guestUser); UserInfo currentUser = mMultiUserHelper.getCurrentForegroundUserInfo(); assertTrue(currentUser.name.equals(guestUser)); boolean IsDeleteAllowed = true; // try to delete self - runtime exception encountered try { mSettingHelper.get().openSetting(AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS); - mProfilesHelper.get().deleteCurrentProfile(); + mUsersHelper.get().deleteCurrentUser(); } catch (RuntimeException err) { Log.v( "DeleteGuestSelfNotAllowed", @@ -82,6 +81,6 @@ public class DeleteGuestSelfNotAllowed { } assertFalse(IsDeleteAllowed); // switch to initial user before terminating the test - mProfilesHelper.get().switchProfile(currentUser.name, previousUser.name); + mUsersHelper.get().switchUser(currentUser.name, previousUser.name); } } diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteCurrentLastAdminUser.java b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteLastAdminUser.java index 41affbe9e..9d1fe9800 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteCurrentLastAdminUser.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteLastAdminUser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertTrue; @@ -22,7 +22,7 @@ import android.content.pm.UserInfo; import android.platform.helpers.AutoConfigConstants; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; import androidx.test.runner.AndroidJUnit4; @@ -39,14 +39,14 @@ import org.junit.runner.RunWith; * switched. */ @RunWith(AndroidJUnit4.class) -public class DeleteCurrentLastAdminUser { +public class DeleteLastAdminUser { private final MultiUserHelper mMultiUserHelper = MultiUserHelper.getInstance(); - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; - public DeleteCurrentLastAdminUser() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + public DeleteLastAdminUser() { + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -70,9 +70,11 @@ public class DeleteCurrentLastAdminUser { // add new user UserInfo initialUser = mMultiUserHelper.getCurrentForegroundUserInfo(); // user deleted self - mProfilesHelper.get().deleteCurrentProfile(); + mUsersHelper.get().deleteCurrentUser(); UserInfo newUser = mMultiUserHelper.getCurrentForegroundUserInfo(); // verify that user is deleted assertTrue((initialUser.id != newUser.id) && (initialUser.name.equals(newUser.name))); } + } + diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteNonAdminUser.java b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteNonAdminUser.java index ddfc2cc73..8dab462ca 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/DeleteNonAdminUser.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/DeleteNonAdminUser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertFalse; @@ -22,9 +22,10 @@ import android.os.SystemClock; import android.platform.helpers.AutoConfigConstants; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; +import android.platform.scenario.multiuser.MultiUserConstants; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.BeforeClass; @@ -33,9 +34,6 @@ import org.junit.runner.RunWith; /** * This test will create user through API and delete the same user from UI - * - * <p>It should be running under user 0, otherwise instrumentation may be killed after user - * switched. */ @RunWith(AndroidJUnit4.class) public class DeleteNonAdminUser { @@ -43,12 +41,12 @@ public class DeleteNonAdminUser { private static final String userName = MultiUserConstants.SECONDARY_USER_NAME; private static final int WAIT_TIME = 10000; private final MultiUserHelper mMultiUserHelper = MultiUserHelper.getInstance(); - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; private int mTargetUserId; public DeleteNonAdminUser() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -69,8 +67,8 @@ public class DeleteNonAdminUser { SystemClock.sleep(WAIT_TIME); // make the new user admin and delete new user mSettingHelper.get().openSetting(AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS); - mProfilesHelper.get().deleteProfile(userName); + mUsersHelper.get().deleteUser(userName); // verify new user was deleted - assertFalse(mProfilesHelper.get().isProfilePresent(userName)); + assertFalse(mUsersHelper.get().isUserPresent(userName)); } } diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/SwitchToGuestFromNonAdmin.java b/tests/automotive/functional/multiuser/src/android/platform/tests/SwitchToGuestFromNonAdmin.java index 539be6d5a..f0fab9f08 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/SwitchToGuestFromNonAdmin.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/SwitchToGuestFromNonAdmin.java @@ -14,17 +14,19 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertTrue; +import android.os.SystemClock; import android.content.pm.UserInfo; import android.platform.helpers.AutoConfigConstants; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; +import android.platform.scenario.multiuser.MultiUserConstants; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; @@ -34,20 +36,21 @@ import org.junit.runner.RunWith; /** * This test will create user through API and delete the same user from UI - * - * <p>It should be running under user 0, otherwise instrumentation may be killed after user - * switched. + * <p> Set system property to run MU test: adb shell setprop fw.stop_bg_users_on_switch 0 */ @RunWith(AndroidJUnit4.class) public class SwitchToGuestFromNonAdmin { + private static final String userName = MultiUserConstants.SECONDARY_USER_NAME; private static final String guestUser = MultiUserConstants.GUEST_NAME; + private static final int WAIT_TIME = 10000; private final MultiUserHelper mMultiUserHelper = MultiUserHelper.getInstance(); - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; + private int mTargetUserId; public SwitchToGuestFromNonAdmin() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -56,11 +59,6 @@ public class SwitchToGuestFromNonAdmin { AutoUtility.exitSuw(); } - @Before - public void openAccountsFacet() { - mSettingHelper.get().openSetting(AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS); - } - @After public void goBackToHomeScreen() { mSettingHelper.get().goBackToSettingsScreen(); @@ -68,18 +66,22 @@ public class SwitchToGuestFromNonAdmin { @Test public void testSwitchToGuest() throws Exception { - // add new user UserInfo initialUser = mMultiUserHelper.getCurrentForegroundUserInfo(); - mProfilesHelper.get().addProfile(); - // switched to new user account + // add new user + mTargetUserId = mMultiUserHelper.createUser(userName, false); + SystemClock.sleep(WAIT_TIME); + // switch to new user + mMultiUserHelper.switchAndWaitForStable( + mTargetUserId, MultiUserConstants.WAIT_FOR_IDLE_TIME_MS); UserInfo newUser = mMultiUserHelper.getCurrentForegroundUserInfo(); // switch to guest from new user - mProfilesHelper.get().switchProfile(newUser.name, guestUser); + mUsersHelper.get().switchUser(newUser.name, guestUser); // verify the user switch UserInfo currentUser = mMultiUserHelper.getCurrentForegroundUserInfo(); assertTrue(currentUser.name.equals(guestUser)); // switch to initial user and delete new user before terminating the test - mProfilesHelper.get().switchProfile(currentUser.name, initialUser.name); + mMultiUserHelper.switchAndWaitForStable( + initialUser.id, MultiUserConstants.WAIT_FOR_IDLE_TIME_MS); mMultiUserHelper.removeUser(newUser); } } diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/SwitchUserQuickSettings.java b/tests/automotive/functional/multiuser/src/android/platform/tests/SwitchUserQuickSettings.java index 0dfdc3dd9..179aed489 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/ui/SwitchUserQuickSettings.java +++ b/tests/automotive/functional/multiuser/src/android/platform/tests/SwitchUserQuickSettings.java @@ -14,16 +14,17 @@ * limitations under the License. */ -package android.platform.scenario.multiuser; +package android.platform.tests; import static junit.framework.Assert.assertTrue; import android.content.pm.UserInfo; import android.platform.helpers.AutoUtility; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoProfileHelper; +import android.platform.helpers.IAutoUserHelper; import android.platform.helpers.IAutoSettingHelper; import android.platform.helpers.MultiUserHelper; +import android.platform.scenario.multiuser.MultiUserConstants; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.BeforeClass; @@ -32,20 +33,18 @@ import org.junit.runner.RunWith; /** * This test will create user through API and delete the same user from UI - * - * <p>It should be running under user 0, otherwise instrumentation may be killed after user - * switched. + * <p> Set system property to run MU test: adb shell setprop fw.stop_bg_users_on_switch 0 */ @RunWith(AndroidJUnit4.class) public class SwitchUserQuickSettings { private static final String guestUser = MultiUserConstants.GUEST_NAME; private final MultiUserHelper mMultiUserHelper = MultiUserHelper.getInstance(); - private HelperAccessor<IAutoProfileHelper> mProfilesHelper; + private HelperAccessor<IAutoUserHelper> mUsersHelper; private HelperAccessor<IAutoSettingHelper> mSettingHelper; public SwitchUserQuickSettings() { - mProfilesHelper = new HelperAccessor<>(IAutoProfileHelper.class); + mUsersHelper = new HelperAccessor<>(IAutoUserHelper.class); mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); } @@ -63,11 +62,11 @@ public class SwitchUserQuickSettings { public void testSwitchUser() throws Exception { UserInfo previousUser = mMultiUserHelper.getCurrentForegroundUserInfo(); // switch to Guest - mProfilesHelper.get().switchProfile(previousUser.name, guestUser); + mUsersHelper.get().switchUser(previousUser.name, guestUser); UserInfo currentUser = mMultiUserHelper.getCurrentForegroundUserInfo(); // verify the user switch assertTrue(currentUser.name.equals(guestUser)); // switch to initial user before terminating the test - mProfilesHelper.get().switchProfile(currentUser.name, previousUser.name); + mUsersHelper.get().switchUser(currentUser.name, previousUser.name); } } diff --git a/tests/automotive/functional/settings/src/android/platform/tests/AccountSettingTest.java b/tests/automotive/functional/settings/src/android/platform/tests/AccountSettingTest.java deleted file mode 100644 index ed0608b09..000000000 --- a/tests/automotive/functional/settings/src/android/platform/tests/AccountSettingTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.tests; - -import android.platform.helpers.AutoConfigConstants; -import android.platform.helpers.AutoUtility; -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoAccountsHelper; -import android.platform.helpers.IAutoSettingHelper; -import android.platform.test.option.StringOption; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.BeforeClass; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -@RunWith(AndroidJUnit4.class) -public class AccountSettingTest { - private static final String ACCOUNT_EMAIL = "account-email"; - private static final String ACCOUNT_PASSWORD = "account-password"; - - @ClassRule - public static StringOption mAccountEmail = new StringOption(ACCOUNT_EMAIL).setRequired(true); - - @ClassRule - public static StringOption mAccountPassword = - new StringOption(ACCOUNT_PASSWORD).setRequired(true); - - private HelperAccessor<IAutoAccountsHelper> mAccountsHelper; - private HelperAccessor<IAutoSettingHelper> mSettingHelper; - - public AccountSettingTest() { - mAccountsHelper = new HelperAccessor<>(IAutoAccountsHelper.class); - mSettingHelper = new HelperAccessor<>(IAutoSettingHelper.class); - } - - @BeforeClass - public static void exitSuw() { - AutoUtility.exitSuw(); - } - - @Before - public void openAccountsFacet() { - mSettingHelper.get().openSetting(AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS); - } - - @After - public void goBackToHomeScreen() { - mSettingHelper.get().goBackToSettingsScreen(); - } - - @Test - public void testAddRemoveAccount() { - mAccountsHelper.get().addAccount(mAccountEmail.get(), mAccountPassword.get()); - mSettingHelper.get().openSetting(AutoConfigConstants.PROFILE_ACCOUNT_SETTINGS); - assertTrue(mAccountsHelper.get().doesEmailExist(mAccountEmail.get())); - mAccountsHelper.get().removeAccount(mAccountEmail.get()); - assertFalse(mAccountsHelper.get().doesEmailExist(mAccountEmail.get())); - } -} diff --git a/tests/automotive/health/appgrid/Android.bp b/tests/automotive/health/appgrid/Android.bp index f1b22d78b..06288ce96 100644 --- a/tests/automotive/health/appgrid/Android.bp +++ b/tests/automotive/health/appgrid/Android.bp @@ -22,7 +22,7 @@ java_library_static { srcs: [ "src/**/*.java" ], libs: [ "androidx.test.runner", - "automotive-settings-app-helper", + "automotive-app-grid-helper", "app-helpers-auto-interfaces", "common-platform-scenarios", "platform-test-options", diff --git a/tests/automotive/health/appgrid/src/android/platform/scenario/appgrid/Scroll.java b/tests/automotive/health/appgrid/src/android/platform/scenario/appgrid/Scroll.java index 4f25dc0b0..8f255b55e 100644 --- a/tests/automotive/health/appgrid/src/android/platform/scenario/appgrid/Scroll.java +++ b/tests/automotive/health/appgrid/src/android/platform/scenario/appgrid/Scroll.java @@ -32,7 +32,7 @@ public class Scroll { @Test public void testScrollDownAndUp() { - sHelper.get().scrollDownOnePage(500); - sHelper.get().scrollUpOnePage(500); + sHelper.get().scrollDownOnePage(); + sHelper.get().scrollUpOnePage(); } } diff --git a/tests/automotive/health/appgrid/tests/Android.bp b/tests/automotive/health/appgrid/tests/Android.bp index b801a7280..ae5a377e4 100644 --- a/tests/automotive/health/appgrid/tests/Android.bp +++ b/tests/automotive/health/appgrid/tests/Android.bp @@ -22,10 +22,9 @@ android_test { static_libs: [ "androidx.test.runner", "androidx.test.rules", - "automotive-settings-scenarios", "automotive-app-grid-scenarios", "automotive-health-test-rules", - "automotive-settings-app-helper", + "automotive-app-grid-helper", "app-helpers-auto-interfaces", "ub-uiautomator", "collector-device-lib-platform", diff --git a/tests/automotive/health/autogeneric/Android.bp b/tests/automotive/health/autogeneric/Android.bp deleted file mode 100644 index 84aa4580f..000000000 --- a/tests/automotive/health/autogeneric/Android.bp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2021 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 { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -java_library_static { - name: "automotive-generic-scenarios", - min_sdk_version: "24", - srcs: [ "src/**/*.java" ], - libs: [ - "androidx.test.runner", - "automotive-settings-app-helper", - "app-helpers-auto-interfaces", - "common-platform-scenarios", - "platform-test-options", - "platform-test-rules", - "ub-uiautomator", - ], -} diff --git a/tests/automotive/health/autogeneric/src/android/platform/scenario/autogeneric/OpenApp.java b/tests/automotive/health/autogeneric/src/android/platform/scenario/autogeneric/OpenApp.java deleted file mode 100644 index d4c61872d..000000000 --- a/tests/automotive/health/autogeneric/src/android/platform/scenario/autogeneric/OpenApp.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.autogeneric; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGenericAppHelper; -import android.platform.test.option.StringOption; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Open an app by specifying either launch activity or package. */ -@Scenario -@RunWith(JUnit4.class) -public class OpenApp { - @ClassRule - public static StringOption mPackageOption = new StringOption("pkg").setRequired(false); - - @ClassRule - public static StringOption mLaunchActivityOption = - new StringOption("launch-activity").setRequired(false); - - static HelperAccessor<IAutoGenericAppHelper> sHelper = - new HelperAccessor<>(IAutoGenericAppHelper.class); - - public OpenApp() { - if (mLaunchActivityOption.get() != null) { - sHelper.get().setLaunchActivity(mLaunchActivityOption.get()); - } else if (mPackageOption.get() != null) { - sHelper.get().setPackage(mPackageOption.get()); - } else { - throw new IllegalStateException("Neither launch activity nor package is set."); - } - } - - @Test - public void testOpen() { - sHelper.get().open(); - } -} diff --git a/tests/automotive/health/autogeneric/tests/Android.bp b/tests/automotive/health/autogeneric/tests/Android.bp deleted file mode 100644 index 0679eae9e..000000000 --- a/tests/automotive/health/autogeneric/tests/Android.bp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2021 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 { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -android_test { - name: "AndroidAutomotiveGenericScenarioTests", - min_sdk_version: "24", - static_libs: [ - "androidx.test.runner", - "androidx.test.rules", - "automotive-settings-scenarios", - "automotive-generic-scenarios", - "automotive-health-test-rules", - "automotive-settings-app-helper", - "app-helpers-auto-interfaces", - "ub-uiautomator", - "collector-device-lib-platform", - "common-platform-scenarios", - "common-platform-scenario-tests", - "microbenchmark-device-lib", - "platform-test-options", - ], - srcs: ["src/**/*.java"], - test_suites: ["catbox"], -} diff --git a/tests/automotive/health/autogeneric/tests/AndroidManifest.xml b/tests/automotive/health/autogeneric/tests/AndroidManifest.xml deleted file mode 100644 index a60b7b1e1..000000000 --- a/tests/automotive/health/autogeneric/tests/AndroidManifest.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2021 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="android.platform.test.scenario.autogeneric" > - <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" /> - <uses-permission android:name="android.permission.DUMP" /> - <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> - <uses-permission android:name="android.permission.MANAGE_USERS" /> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> - - <application> - <uses-library android:name="android.test.runner"/> - </application> - <instrumentation - android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.platform.test.scenario.autogeneric" - android:label="Android Automotive Generic Scenario-Based Tests" /> -</manifest>
\ No newline at end of file diff --git a/tests/automotive/health/dial/Android.bp b/tests/automotive/health/dial/Android.bp index d4a61dad8..2b573e142 100644 --- a/tests/automotive/health/dial/Android.bp +++ b/tests/automotive/health/dial/Android.bp @@ -22,7 +22,7 @@ java_library_static { srcs: [ "src/**/*.java" ], libs: [ "androidx.test.runner", - "automotive-settings-app-helper", + "automotive-dial-app-helper", "app-helpers-auto-interfaces", "common-platform-scenarios", "platform-test-options", diff --git a/tests/automotive/health/dial/src/android/platform/scenario/dial/ScrollContactList.java b/tests/automotive/health/dial/src/android/platform/scenario/dial/ScrollContactList.java index 522460cb4..18522d035 100644 --- a/tests/automotive/health/dial/src/android/platform/scenario/dial/ScrollContactList.java +++ b/tests/automotive/health/dial/src/android/platform/scenario/dial/ScrollContactList.java @@ -16,7 +16,6 @@ package android.platform.test.scenario.dial; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGenericAppHelper; import android.platform.test.scenario.annotation.Scenario; import android.platform.helpers.IAutoDialHelper; @@ -28,24 +27,14 @@ import org.junit.runners.JUnit4; @Scenario @RunWith(JUnit4.class) public class ScrollContactList { - private static final String DIALER_PACKAGE = "com.android.car.dialer"; - - static HelperAccessor<IAutoGenericAppHelper> sAutoGenericHelper = - new HelperAccessor<>(IAutoGenericAppHelper.class); - - static { - sAutoGenericHelper.get().setPackage(DIALER_PACKAGE); - sAutoGenericHelper.get().setScrollableMargin(0, 200, 0, 200); - } - static HelperAccessor<IAutoDialHelper> sHelper = new HelperAccessor<>(IAutoDialHelper.class); @Test public void testScrollDownAndUp() { sHelper.get().openContacts(); - // test scroll down by one page in 500ms. - sAutoGenericHelper.get().scrollDownOnePage(500); - // test scroll up by one page in 500ms. - sAutoGenericHelper.get().scrollUpOnePage(500); + // test scroll down by one page. + sHelper.get().scrollDownOnePage(); + // test scroll up by one page. + sHelper.get().scrollUpOnePage(); } } diff --git a/tests/automotive/health/dial/tests/Android.bp b/tests/automotive/health/dial/tests/Android.bp index 2cf31afce..497f8656f 100644 --- a/tests/automotive/health/dial/tests/Android.bp +++ b/tests/automotive/health/dial/tests/Android.bp @@ -22,10 +22,9 @@ android_test { static_libs: [ "androidx.test.runner", "androidx.test.rules", - "automotive-settings-scenarios", "automotive-dial-scenarios", "automotive-health-test-rules", - "automotive-settings-app-helper", + "automotive-dial-app-helper", "app-helpers-auto-interfaces", "ub-uiautomator", "collector-device-lib-platform", diff --git a/tests/automotive/health/evs/src/android/platform/scenario/evs/OpenApp.java b/tests/automotive/health/evs/src/android/platform/scenario/evs/OpenApp.java deleted file mode 100644 index 35b2512b6..000000000 --- a/tests/automotive/health/evs/src/android/platform/scenario/evs/OpenApp.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.evs; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoCarEvsServiceHelper; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@Scenario -@RunWith(JUnit4.class) -public class OpenApp { - - static HelperAccessor<IAutoCarEvsServiceHelper> sHelper = - new HelperAccessor<>(IAutoCarEvsServiceHelper.class); - - @Test - public void testOpen() { - sHelper.get().startEvsPreview(); - } -} diff --git a/tests/automotive/health/evs/tests/AndroidManifest.xml b/tests/automotive/health/evs/tests/AndroidManifest.xml deleted file mode 100644 index 4aa072262..000000000 --- a/tests/automotive/health/evs/tests/AndroidManifest.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2021 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="android.platform.test.scenario.evs" > - <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" /> - <uses-permission android:name="android.permission.DUMP" /> - <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> - <uses-permission android:name="android.permission.MANAGE_USERS" /> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> - - <application> - <uses-library android:name="android.test.runner"/> - </application> - <instrumentation - android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.platform.test.scenario.evs" - android:label="Android Automotive Evs Scenario-Based Tests" /> -</manifest>
\ No newline at end of file diff --git a/tests/automotive/health/evs/tests/src/android/platform/scenario/evs/OpenAppMicrobenchmark.java b/tests/automotive/health/evs/tests/src/android/platform/scenario/evs/OpenAppMicrobenchmark.java deleted file mode 100644 index 8e02aa6bf..000000000 --- a/tests/automotive/health/evs/tests/src/android/platform/scenario/evs/OpenAppMicrobenchmark.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.evs; - -import android.platform.test.scenario.AppStartupRunRule; -import android.platform.test.microbenchmark.Microbenchmark; - -import org.junit.Rule; -import org.junit.runner.RunWith; - -@RunWith(Microbenchmark.class) -public class OpenAppMicrobenchmark extends OpenApp { - - @Rule public AppStartupRunRule mAppStartupRunRule = new AppStartupRunRule<>(sHelper.get()); -} diff --git a/tests/automotive/health/googleplay/Android.bp b/tests/automotive/health/googleplay/Android.bp deleted file mode 100644 index 9c1f12e77..000000000 --- a/tests/automotive/health/googleplay/Android.bp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2021 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 { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -java_library_static { - name: "automotive-google-play-scenarios", - min_sdk_version: "24", - srcs: [ "src/**/*.java" ], - libs: [ - "androidx.test.runner", - "automotive-settings-app-helper", - "app-helpers-auto-interfaces", - "common-platform-scenarios", - "platform-test-options", - "platform-test-rules", - "ub-uiautomator", - ], -} diff --git a/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/InstallApp.java b/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/InstallApp.java deleted file mode 100644 index 2f993699a..000000000 --- a/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/InstallApp.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.googleplay; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGooglePlayHelper; -import android.platform.test.scenario.annotation.Scenario; - -import androidx.test.InstrumentationRegistry; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * This is test scenario to install app from Google Play Store. It assumes the Play Store app is - * already open - */ -@Scenario -@RunWith(JUnit4.class) -public class InstallApp { - // The argument keys are accessible to other class in the same package - static final String APP_NAME_PARAM = "app_name_on_play_store"; - static final String DEFAULT_APP_NAME = "NPR One"; - - private static HelperAccessor<IAutoGooglePlayHelper> sHelper = - new HelperAccessor<>(IAutoGooglePlayHelper.class); - - private String mAppName; - - public InstallApp() { - mAppName = - InstrumentationRegistry.getArguments().getString(APP_NAME_PARAM, DEFAULT_APP_NAME); - } - - @Test - public void testSearchAndInstall() { - sHelper.get().searchAndClick(mAppName); - sHelper.get().installApp(); - } -} diff --git a/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/OpenApp.java b/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/OpenApp.java deleted file mode 100644 index 8b2eb53fd..000000000 --- a/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/OpenApp.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.googleplay; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGooglePlayHelper; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Opens the Googleplay application and exits after. */ -@Scenario -@RunWith(JUnit4.class) -public class OpenApp { - static HelperAccessor<IAutoGooglePlayHelper> sHelper = - new HelperAccessor<>(IAutoGooglePlayHelper.class); - - @Test - public void testOpen() { - sHelper.get().open(); - } -} diff --git a/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/OpenAppOnPlayStore.java b/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/OpenAppOnPlayStore.java deleted file mode 100644 index 6321b8be2..000000000 --- a/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/OpenAppOnPlayStore.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.googleplay; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGooglePlayHelper; -import android.platform.helpers.exceptions.UnknownUiException; -import android.platform.test.scenario.annotation.Scenario; - -import androidx.test.InstrumentationRegistry; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * This is a test to search and open an App on Play Store. It assumes the App is already installed, - * otherwise the test will throw exception. - */ -@Scenario -@RunWith(JUnit4.class) -public class OpenAppOnPlayStore { - - private static HelperAccessor<IAutoGooglePlayHelper> sHelper = - new HelperAccessor<>(IAutoGooglePlayHelper.class); - - private static String mAppName; - - public OpenAppOnPlayStore() { - mAppName = - InstrumentationRegistry.getArguments() - .getString(InstallApp.APP_NAME_PARAM, InstallApp.DEFAULT_APP_NAME); - } - - @Test - public void openApp() { - try { - sHelper.get().openApp(); - } catch (UnknownUiException e) { - // If app can not be opened directly, try search for the app first then open it. - sHelper.get().searchAndClick(mAppName); - sHelper.get().openApp(); - } - } -} diff --git a/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/Scroll.java b/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/Scroll.java deleted file mode 100644 index b92977ee4..000000000 --- a/tests/automotive/health/googleplay/src/android/platform/scenario/googleplay/Scroll.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.googleplay; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGooglePlayHelper; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Scroll down and up in Google play. */ -@Scenario -@RunWith(JUnit4.class) -public class Scroll { - static HelperAccessor<IAutoGooglePlayHelper> sHelper = - new HelperAccessor<>(IAutoGooglePlayHelper.class); - - @Test - public void testScrollDownAndUp() { - sHelper.get().scrollDownOnePage(500); - sHelper.get().scrollUpOnePage(500); - } -} diff --git a/tests/automotive/health/googleplay/tests/Android.bp b/tests/automotive/health/googleplay/tests/Android.bp deleted file mode 100644 index 116ef3930..000000000 --- a/tests/automotive/health/googleplay/tests/Android.bp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2021 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 { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -android_test { - name: "AndroidAutomotiveGooglePlayScenarioTests", - min_sdk_version: "24", - static_libs: [ - "androidx.test.runner", - "androidx.test.rules", - "automotive-settings-scenarios", - "automotive-google-play-scenarios", - "automotive-health-test-rules", - "automotive-settings-app-helper", - "app-helpers-auto-interfaces", - "ub-uiautomator", - "collector-device-lib-platform", - "common-platform-scenarios", - "common-platform-scenario-tests", - "microbenchmark-device-lib", - "platform-test-options", - ], - srcs: ["src/**/*.java"], - test_suites: ["catbox"], -} diff --git a/tests/automotive/health/googleplay/tests/AndroidManifest.xml b/tests/automotive/health/googleplay/tests/AndroidManifest.xml deleted file mode 100644 index 2b5419f3b..000000000 --- a/tests/automotive/health/googleplay/tests/AndroidManifest.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2021 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="android.platform.test.scenario.googleplay" > - <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" /> - <uses-permission android:name="android.permission.DUMP" /> - <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> - <uses-permission android:name="android.permission.MANAGE_USERS" /> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> - - <application> - <uses-library android:name="android.test.runner"/> - </application> - <instrumentation - android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.platform.test.scenario.googleplay" - android:label="Android Automotive Google Play Scenario-Based Tests" /> -</manifest>
\ No newline at end of file diff --git a/tests/automotive/health/googleplay/tests/src/android/platform/scenario/googleplay/OpenAppMicrobenchmark.java b/tests/automotive/health/googleplay/tests/src/android/platform/scenario/googleplay/OpenAppMicrobenchmark.java deleted file mode 100644 index ee7b99380..000000000 --- a/tests/automotive/health/googleplay/tests/src/android/platform/scenario/googleplay/OpenAppMicrobenchmark.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.googleplay; - -import android.platform.test.scenario.AppStartupRunRule; -import android.platform.test.microbenchmark.Microbenchmark; - -import org.junit.Rule; -import org.junit.runner.RunWith; - -@RunWith(Microbenchmark.class) -public class OpenAppMicrobenchmark extends OpenApp { - - @Rule public AppStartupRunRule mAppStartupRunRule = new AppStartupRunRule<>(sHelper.get()); -} diff --git a/tests/automotive/health/googleplay/tests/src/android/platform/scenario/googleplay/ScrollMicrobenchmark.java b/tests/automotive/health/googleplay/tests/src/android/platform/scenario/googleplay/ScrollMicrobenchmark.java deleted file mode 100644 index c1a8d65bc..000000000 --- a/tests/automotive/health/googleplay/tests/src/android/platform/scenario/googleplay/ScrollMicrobenchmark.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.googleplay; - -import android.platform.test.microbenchmark.Microbenchmark; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; - -@RunWith(Microbenchmark.class) -public class ScrollMicrobenchmark extends Scroll { - @BeforeClass - public static void openApp() { - sHelper.get().open(); - sHelper.get().searchApp("youtube"); - } - - @AfterClass - public static void closeApp() { - sHelper.get().exit(); - } -} diff --git a/tests/automotive/health/mediacenter/Android.bp b/tests/automotive/health/mediacenter/Android.bp index cb19f10d1..14ff9f7b3 100644 --- a/tests/automotive/health/mediacenter/Android.bp +++ b/tests/automotive/health/mediacenter/Android.bp @@ -22,7 +22,7 @@ java_library_static { srcs: [ "src/**/*.java" ], libs: [ "androidx.test.runner", - "automotive-settings-app-helper", + "automotive-media-center-app-helper", "app-helpers-auto-interfaces", "common-platform-scenarios", "platform-test-options", diff --git a/tests/automotive/health/radio/src/android/platform/scenario/radio/OpenApp.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/OpenApp.java index 84f184a73..7d338a65d 100644 --- a/tests/automotive/health/radio/src/android/platform/scenario/radio/OpenApp.java +++ b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/OpenApp.java @@ -13,21 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.platform.test.scenario.radio; + +package android.platform.test.scenario.mediacenter; import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoRadioHelper; +import android.platform.helpers.IAutoMediaHelper; import android.platform.test.scenario.annotation.Scenario; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Opens the Radio application and exits after. */ +/** Opens the Settings application and exits after. */ @Scenario @RunWith(JUnit4.class) public class OpenApp { - static HelperAccessor<IAutoRadioHelper> sHelper = new HelperAccessor<>(IAutoRadioHelper.class); + static HelperAccessor<IAutoMediaHelper> sHelper = new HelperAccessor<>(IAutoMediaHelper.class); @Test public void testOpen() { diff --git a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/bluetooth/OpenMedia.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/bluetooth/OpenMedia.java deleted file mode 100644 index 176879a7c..000000000 --- a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/bluetooth/OpenMedia.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.bluetooth; - -import android.platform.test.scenario.annotation.Scenario; -import android.support.test.uiautomator.UiDevice; -import androidx.test.InstrumentationRegistry; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.io.IOException; - -/** Opens Bluetooth application */ -@Scenario -@RunWith(JUnit4.class) -public class OpenMedia { - @Test - public void testOpen() throws IOException { - UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - .executeShellCommand( - "am start -a android.car.intent.action.MEDIA_TEMPLATE -e " - + "android.car.intent.extra.MEDIA_COMPONENT " - + "com.android.bluetooth" - + "/com.android.bluetooth.avrcpcontroller" - + ".BluetoothMediaBrowseService"); - } -} diff --git a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/bluetooth/PlayMedia.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/bluetooth/PlayMedia.java deleted file mode 100644 index 5fe911c7e..000000000 --- a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/bluetooth/PlayMedia.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.bluetooth; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoMediaHelper; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Scenario to Play Media via Bluetooth. */ -@Scenario -@RunWith(JUnit4.class) -public class PlayMedia { - - private static HelperAccessor<IAutoMediaHelper> sHelper = - new HelperAccessor<>(IAutoMediaHelper.class); - - @Test - public void testPlay() { - sHelper.get().playMedia(); - } -} diff --git a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/OpenGoogleBooks.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/OpenGoogleBooks.java deleted file mode 100644 index 41ef2a41e..000000000 --- a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/OpenGoogleBooks.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.googleplaybooks; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoMediaCenterHelper; -import android.platform.test.scenario.annotation.Scenario; -import android.support.test.uiautomator.UiDevice; -import androidx.test.InstrumentationRegistry; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.io.IOException; - -/** Opens the Google Books and plays an audio book */ -@Scenario -@RunWith(JUnit4.class) -public class OpenGoogleBooks { - static HelperAccessor<IAutoMediaCenterHelper> sMediaCenterHelper = - new HelperAccessor<>(IAutoMediaCenterHelper.class); - - @Test - public void testOpen() throws IOException { - UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - .executeShellCommand( - "am start -a android.car.intent.action.MEDIA_TEMPLATE -e " - + "android.car.intent.extra.MEDIA_COMPONENT " - + "com.google.android.apps.books" - + "/com.google.android.apps.play.books.audio" - + ".BooksMediaBrowseService"); - } -} diff --git a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/PlayBooks.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/PlayBooks.java deleted file mode 100644 index c8e0c6454..000000000 --- a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/PlayBooks.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.googleplaybooks; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoMediaCenterHelper; -import android.platform.test.scenario.annotation.Scenario; -import androidx.test.InstrumentationRegistry; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.io.IOException; - -/** Plays an audio book assuming Google Play Books is open */ -@Scenario -@RunWith(JUnit4.class) -public class PlayBooks { - - private String mNameOftheSong; - static HelperAccessor<IAutoMediaCenterHelper> sMediaCenterHelper = - new HelperAccessor<>(IAutoMediaCenterHelper.class); - - @Test - public void testOpen() throws IOException { - mNameOftheSong = - InstrumentationRegistry.getArguments() - .getString("song_name", "Once Gone (a Riley Paige Mystery--Book #1)"); - sMediaCenterHelper.get().selectMediaTrack("Library", mNameOftheSong); - } -} diff --git a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/Scroll.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/Scroll.java deleted file mode 100644 index 961ddd8a6..000000000 --- a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/Scroll.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.googleplaybooks; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGenericAppHelper; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Scroll down and up in Google play Books' content list. */ -@Scenario -@RunWith(JUnit4.class) -public class Scroll { - private static final String MEDIA_CENTER_PACKAGE = "com.android.car.media"; - - static HelperAccessor<IAutoGenericAppHelper> sHelper = - new HelperAccessor<>(IAutoGenericAppHelper.class); - - static { - sHelper.get().setPackage(MEDIA_CENTER_PACKAGE); - // Media center has some UI components overlays the scrollable region at both the top and - // bottom section, and hence a large margin is required. - sHelper.get().setScrollableMargin(0, 200, 0, 200); - } - - @Test - public void testScrollDownAndUp() { - sHelper.get().scrollDownOnePage(500); - sHelper.get().scrollUpOnePage(500); - } -} diff --git a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/SwitchPlayBack.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/SwitchPlayBack.java deleted file mode 100644 index 52361915b..000000000 --- a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/googleplaybooks/SwitchPlayBack.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.googleplaybooks; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoMediaCenterMinimizeControlBarHelper; -import android.platform.helpers.IAutoMediaCenterNowPlayingHelper; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Maximize and minimize playback screen in Google Play Books. */ -@Scenario -@RunWith(JUnit4.class) -public class SwitchPlayBack { - private static final String MEDIA_CENTER_PACKAGE = "com.android.car.media"; - - private static HelperAccessor<IAutoMediaCenterMinimizeControlBarHelper> sMinPlaybackHelper = - new HelperAccessor<>(IAutoMediaCenterMinimizeControlBarHelper.class); - private static HelperAccessor<IAutoMediaCenterNowPlayingHelper> sMaxPlaybackHelper = - new HelperAccessor<>(IAutoMediaCenterNowPlayingHelper.class); - - @Test - public void testScrollDownAndUp() { - sMinPlaybackHelper.get().maximizeNowPlaying(); - sMaxPlaybackHelper.get().minimizeNowPlaying(); - } -} diff --git a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/testmedia/OpenApp.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/testmedia/OpenApp.java deleted file mode 100644 index fd641720b..000000000 --- a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/testmedia/OpenApp.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.testmedia; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGenericAppHelper; -import android.platform.helpers.IAutoMediaCenterHelper; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** Opens the Test Media App application by launching media center. */ -@Scenario -@RunWith(JUnit4.class) -public class OpenApp { - - private static final String MEDIA_CENTER_PACKAGE = "com.android.car.media"; - private static final String MEDIA_TEMPLATE = "android.car.intent.action.MEDIA_TEMPLATE"; - private static final Map<String, String> TEST_MEDIA_APP_EXTRA_ARGS = - Stream.of( - new Object[][] { - { - "android.car.intent.extra.MEDIA_COMPONENT", - "com.android.car.media.testmediaapp/com.android.car.media.testmediaapp.TmaBrowser" - }, - }) - .collect(Collectors.toMap(data -> (String) data[0], data -> (String) data[1])); - - static HelperAccessor<IAutoGenericAppHelper> sAutoGenericrHelper = - new HelperAccessor<>(IAutoGenericAppHelper.class); - - static HelperAccessor<IAutoMediaCenterHelper> sMediaCenterHelper = - new HelperAccessor<>(IAutoMediaCenterHelper.class); - - static { - sAutoGenericrHelper.get().setPackage(MEDIA_CENTER_PACKAGE); - sAutoGenericrHelper.get().setLaunchAction(MEDIA_TEMPLATE, TEST_MEDIA_APP_EXTRA_ARGS); - } - - @Test - public void Open() { - sAutoGenericrHelper.get().open(); - } -} diff --git a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/testmedia/Scroll.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/testmedia/Scroll.java deleted file mode 100644 index 31e77b262..000000000 --- a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/testmedia/Scroll.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.testmedia; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGenericAppHelper; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Scroll down and up in Google play Books' content list. */ -@Scenario -@RunWith(JUnit4.class) -public class Scroll { - private static final String MEDIA_CENTER_PACKAGE = "com.android.car.media"; - - static HelperAccessor<IAutoGenericAppHelper> sAutoGenericHelper = - new HelperAccessor<>(IAutoGenericAppHelper.class); - - static { - sAutoGenericHelper.get().setPackage(MEDIA_CENTER_PACKAGE); - // Media center has some UI components overlays the scrollable region at both the top and - // bottom section, and hence a large margin is required. - sAutoGenericHelper.get().setScrollableMargin(0, 200, 0, 200); - } - - @Test - public void testScrollDownAndUp() { - sAutoGenericHelper.get().scrollDownOnePage(2500); - sAutoGenericHelper.get().scrollUpOnePage(2500); - } -} diff --git a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/testmedia/SwitchPlayback.java b/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/testmedia/SwitchPlayback.java deleted file mode 100644 index 3c9108d28..000000000 --- a/tests/automotive/health/mediacenter/src/android/platform/scenario/mediacenter/testmedia/SwitchPlayback.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.testmedia; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoMediaCenterMinimizeControlBarHelper; -import android.platform.helpers.IAutoMediaCenterNowPlayingHelper; -import android.platform.test.scenario.annotation.Scenario; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Maximize and minimize playback screen in Test Media App. */ -@Scenario -@RunWith(JUnit4.class) -public class SwitchPlayback { - - static HelperAccessor<IAutoMediaCenterMinimizeControlBarHelper> sMinPlaybackHelper = - new HelperAccessor<>(IAutoMediaCenterMinimizeControlBarHelper.class); - - static HelperAccessor<IAutoMediaCenterNowPlayingHelper> sMaxPlaybackHelper = - new HelperAccessor<>(IAutoMediaCenterNowPlayingHelper.class); - - @Test - public void testSwitchPlayback() { - sMaxPlaybackHelper.get().minimizeNowPlaying(); - sMinPlaybackHelper.get().maximizeNowPlaying(); - } -} diff --git a/tests/automotive/health/mediacenter/tests/Android.bp b/tests/automotive/health/mediacenter/tests/Android.bp index 824d85403..e9ddf15d1 100644 --- a/tests/automotive/health/mediacenter/tests/Android.bp +++ b/tests/automotive/health/mediacenter/tests/Android.bp @@ -22,10 +22,9 @@ android_test { static_libs: [ "androidx.test.runner", "androidx.test.rules", - "automotive-settings-scenarios", "automotive-media-center-scenarios", "automotive-health-test-rules", - "automotive-settings-app-helper", + "automotive-media-center-app-helper", "app-helpers-auto-interfaces", "ub-uiautomator", "collector-device-lib-platform", diff --git a/tests/automotive/health/autogeneric/tests/src/android/platform/scenario/autogeneric/OpenAppMicrobenchmark.java b/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/OpenAppMicrobenchmark.java index d77422e97..ab680a5b8 100644 --- a/tests/automotive/health/autogeneric/tests/src/android/platform/scenario/autogeneric/OpenAppMicrobenchmark.java +++ b/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/OpenAppMicrobenchmark.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.platform.test.scenario.autogeneric; +package android.platform.test.scenario.mediacenter; import android.platform.test.scenario.AppStartupRunRule; import android.platform.test.microbenchmark.Microbenchmark; diff --git a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/googleplaybooks/ScrollMicrobenchmark.java b/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/googleplaybooks/ScrollMicrobenchmark.java deleted file mode 100644 index d7158252a..000000000 --- a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/googleplaybooks/ScrollMicrobenchmark.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.googleplaybooks; - -import android.platform.test.microbenchmark.Microbenchmark; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; - -@RunWith(Microbenchmark.class) -public class ScrollMicrobenchmark extends Scroll { - @BeforeClass - public static void openApp() { - sHelper.get().open(); - } - - @AfterClass - public static void closeApp() { - sHelper.get().exit(); - } -} diff --git a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/googleplaybooks/SwitchPlayBackMicrobenchmark.java b/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/googleplaybooks/SwitchPlayBackMicrobenchmark.java deleted file mode 100644 index 9134d3609..000000000 --- a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/googleplaybooks/SwitchPlayBackMicrobenchmark.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.googleplaybooks; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGenericAppHelper; -import android.platform.test.microbenchmark.Microbenchmark; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; - -@RunWith(Microbenchmark.class) -public class SwitchPlayBackMicrobenchmark extends SwitchPlayBack { - private static final String MEDIA_CENTER_PACKAGE = "com.android.car.media"; - - private static HelperAccessor<IAutoGenericAppHelper> sHelper = - new HelperAccessor<>(IAutoGenericAppHelper.class); - - static { - sHelper.get().setPackage(MEDIA_CENTER_PACKAGE); - } - - @BeforeClass - public static void openApp() { - sHelper.get().open(); - } - - @AfterClass - public static void closeApp() { - sHelper.get().exit(); - } -} diff --git a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/testmedia/OpenMediaCenterMicrobenchmark.java b/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/testmedia/OpenMediaCenterMicrobenchmark.java deleted file mode 100644 index 5a30ac7f2..000000000 --- a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/testmedia/OpenMediaCenterMicrobenchmark.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.testmedia; - -import android.platform.test.microbenchmark.Microbenchmark; -import android.platform.test.scenario.AppStartupRunRule; - -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.runner.RunWith; - -@RunWith(Microbenchmark.class) -public class OpenMediaCenterMicrobenchmark extends OpenApp { - - @Rule - public AppStartupRunRule mAppStartupRunRule = - new AppStartupRunRule<>(sAutoGenericrHelper.get()); - - @BeforeClass - public static void setup() { - sAutoGenericrHelper.get().open(); - sMediaCenterHelper.get().dismissInitialDialogs(); - } -} diff --git a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/testmedia/ScrollMicrobenchmark.java b/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/testmedia/ScrollMicrobenchmark.java deleted file mode 100644 index 2e6b3386f..000000000 --- a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/testmedia/ScrollMicrobenchmark.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.testmedia; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGenericAppHelper; -import android.platform.helpers.IAutoMediaCenterHelper; -import android.platform.test.microbenchmark.Microbenchmark; - -import org.junit.BeforeClass; -import org.junit.runner.RunWith; - -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@RunWith(Microbenchmark.class) -public class ScrollMicrobenchmark extends Scroll { - - private static final String MEDIA_CENTER_PACKAGE = "com.android.car.media"; - private static final String MEDIA_TEMPLATE = "android.car.intent.action.MEDIA_TEMPLATE"; - private static final Map<String, String> TEST_MEDIA_APP_EXTRA_ARGS = - Stream.of( - new Object[][] { - { - "android.car.intent.extra.MEDIA_COMPONENT", - "com.android.car.media.testmediaapp/com.android.car.media.testmediaapp.TmaBrowser" - }, - }) - .collect(Collectors.toMap(data -> (String) data[0], data -> (String) data[1])); - - static HelperAccessor<IAutoGenericAppHelper> sAutoGenericrHelper = - new HelperAccessor<>(IAutoGenericAppHelper.class); - - static HelperAccessor<IAutoMediaCenterHelper> sMediaCenterHelper = - new HelperAccessor<>(IAutoMediaCenterHelper.class); - - static { - sAutoGenericrHelper.get().setPackage(MEDIA_CENTER_PACKAGE); - sAutoGenericrHelper.get().setLaunchAction(MEDIA_TEMPLATE, TEST_MEDIA_APP_EXTRA_ARGS); - } - - @BeforeClass - public static void openApp() { - sAutoGenericrHelper.get().open(); - sMediaCenterHelper.get().dismissInitialDialogs(); - } -} diff --git a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/testmedia/SwitchPlaybackMicrobenchmark.java b/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/testmedia/SwitchPlaybackMicrobenchmark.java deleted file mode 100644 index d7ee8ac55..000000000 --- a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/testmedia/SwitchPlaybackMicrobenchmark.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.mediacenter.testmedia; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGenericAppHelper; -import android.platform.helpers.IAutoMediaCenterHelper; -import android.platform.test.microbenchmark.Microbenchmark; - -import org.junit.BeforeClass; -import org.junit.runner.RunWith; - -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@RunWith(Microbenchmark.class) -public class SwitchPlaybackMicrobenchmark extends SwitchPlayback { - - private static final String MEDIA_CENTER_PACKAGE = "com.android.car.media"; - private static final String MEDIA_TEMPLATE = "android.car.intent.action.MEDIA_TEMPLATE"; - private static final String SONG = "A normal 1H song"; - private static final Map<String, String> TEST_MEDIA_APP_EXTRA_ARGS = - Stream.of( - new Object[][] { - { - "android.car.intent.extra.MEDIA_COMPONENT", - "com.android.car.media.testmediaapp/com.android.car.media.testmediaapp.TmaBrowser" - }, - }) - .collect(Collectors.toMap(data -> (String) data[0], data -> (String) data[1])); - - static HelperAccessor<IAutoGenericAppHelper> sAutoGenericrHelper = - new HelperAccessor<>(IAutoGenericAppHelper.class); - - static HelperAccessor<IAutoMediaCenterHelper> sMediaCenterHelper = - new HelperAccessor<>(IAutoMediaCenterHelper.class); - - static { - sAutoGenericrHelper.get().setPackage(MEDIA_CENTER_PACKAGE); - sAutoGenericrHelper.get().setLaunchAction(MEDIA_TEMPLATE, TEST_MEDIA_APP_EXTRA_ARGS); - } - - @BeforeClass - public static void openApp() { - sAutoGenericrHelper.get().open(); - sMediaCenterHelper.get().dismissInitialDialogs(); - sMediaCenterHelper.get().selectMediaTrack(SONG); - } -} diff --git a/tests/automotive/health/multiuser/Android.bp b/tests/automotive/health/multiuser/Android.bp index cc68c1bca..1ad35f171 100644 --- a/tests/automotive/health/multiuser/Android.bp +++ b/tests/automotive/health/multiuser/Android.bp @@ -25,7 +25,6 @@ java_library_static { "androidx.test.rules", "automotive-settings-app-helper", "automotive-utility-helper", - "automotive-settings-scenarios", "app-helpers-auto-interfaces", "app-helpers-common-interfaces", "common-platform-scenarios", diff --git a/tests/automotive/health/multiuser/src/android/platform/scenario/multiuser/nonui/MultiUserConstants.java b/tests/automotive/health/multiuser/src/android/platform/scenario/multiuser/nonui/MultiUserConstants.java index a85733a3d..4d90ca2b2 100644 --- a/tests/automotive/health/multiuser/src/android/platform/scenario/multiuser/nonui/MultiUserConstants.java +++ b/tests/automotive/health/multiuser/src/android/platform/scenario/multiuser/nonui/MultiUserConstants.java @@ -19,19 +19,21 @@ package android.platform.scenario.multiuser; import android.platform.helpers.MultiUserHelper; import androidx.test.InstrumentationRegistry; -class MultiUserConstants { +public final class MultiUserConstants { // Shouldn't be too optimistic for the MU latency. The time to wait for system idle will be // 2 x (worst-case number) to make sure regression not affecting test itself. - static final long WAIT_FOR_IDLE_TIME_MS = 40000; + public static final long WAIT_FOR_IDLE_TIME_MS = 40000; // Default initial user does not change throughout the test process - static final int DEFAULT_INITIAL_USER = MultiUserHelper.getInstance().getInitialUser(); - - static final String INCLUDE_CREATION_TIME_KEY = "include_creation_time"; - static final boolean INCLUDE_CREATION_TIME = + public static final int DEFAULT_INITIAL_USER = MultiUserHelper.getInstance().getInitialUser(); + public static final String INCLUDE_CREATION_TIME_KEY = "include_creation_time"; + public static final boolean INCLUDE_CREATION_TIME = Boolean.valueOf( InstrumentationRegistry.getArguments().getString(INCLUDE_CREATION_TIME_KEY, "false")); + public static final String GUEST_NAME = "Guest"; + public static final String SECONDARY_USER_NAME = "SecondaryUser"; - static final String GUEST_NAME = "Guest"; - static final String SECONDARY_USER_NAME = "SecondaryUser"; + private MultiUserConstants() { + throw new RuntimeException("Class cannot be instantiated"); + } } diff --git a/tests/automotive/health/multiuser/tests/Android.bp b/tests/automotive/health/multiuser/tests/Android.bp index c5ea95c36..8409848fc 100644 --- a/tests/automotive/health/multiuser/tests/Android.bp +++ b/tests/automotive/health/multiuser/tests/Android.bp @@ -23,7 +23,6 @@ android_test { "androidx.test.runner", "androidx.test.rules", "automotive-multiuser-scenarios", - "automotive-settings-scenarios", "automotive-utility-helper", "automotive-health-test-rules", "automotive-settings-app-helper", diff --git a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/nonui/SwitchToNewSecondaryUserBenchmark.java b/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/nonui/SwitchToNewSecondaryUserBenchmark.java index 7ce42b6d0..434242b4d 100644 --- a/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/nonui/SwitchToNewSecondaryUserBenchmark.java +++ b/tests/automotive/health/multiuser/tests/src/android/platform/scenario/multiuser/nonui/SwitchToNewSecondaryUserBenchmark.java @@ -17,7 +17,17 @@ package android.platform.scenario.multiuser; import android.platform.test.microbenchmark.Microbenchmark; +import android.platform.test.microbenchmark.Microbenchmark.TightMethodRule; +import android.platform.test.rule.StopwatchRule; +import android.platform.test.scenario.SleepAtTestFinishRule; +import org.junit.Rule; import org.junit.runner.RunWith; @RunWith(Microbenchmark.class) -public class SwitchToNewSecondaryUserBenchmark extends SwitchToNewSecondaryUser {} +public class SwitchToNewSecondaryUserBenchmark extends SwitchToNewSecondaryUser { + @Rule + public SleepAtTestFinishRule sleepRule = + new SleepAtTestFinishRule(MultiUserConstants.WAIT_FOR_IDLE_TIME_MS); + + @TightMethodRule public StopwatchRule stopwatchRule = new StopwatchRule(); +} diff --git a/tests/automotive/health/notification/Android.bp b/tests/automotive/health/notification/Android.bp index 3acfb21b1..6d4a89962 100644 --- a/tests/automotive/health/notification/Android.bp +++ b/tests/automotive/health/notification/Android.bp @@ -22,7 +22,7 @@ java_library_static { srcs: [ "src/**/*.java" ], libs: [ "androidx.test.runner", - "automotive-settings-app-helper", + "automotive-notifications-app-helper", "app-helpers-auto-interfaces", "common-platform-scenarios", "platform-test-options", diff --git a/tests/automotive/health/notification/src/android/platform/scenario/notification/Scroll.java b/tests/automotive/health/notification/src/android/platform/scenario/notification/Scroll.java index 9c98602c3..79a26db22 100644 --- a/tests/automotive/health/notification/src/android/platform/scenario/notification/Scroll.java +++ b/tests/automotive/health/notification/src/android/platform/scenario/notification/Scroll.java @@ -17,10 +17,9 @@ package android.platform.test.scenario.notification; import android.platform.helpers.HelperAccessor; import android.platform.helpers.IAutoNotificationHelper; +import android.platform.helpers.IAutoNotificationMockingHelper; import android.platform.test.scenario.annotation.Scenario; -import android.platform.test.rule.NotificationPressureRule; -import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -32,10 +31,8 @@ public class Scroll { static HelperAccessor<IAutoNotificationHelper> sHelper = new HelperAccessor<>(IAutoNotificationHelper.class); - // Populate notification before scrolling. - @ClassRule - public static NotificationPressureRule NotificationPressureRule = - new NotificationPressureRule(5); + static HelperAccessor<IAutoNotificationMockingHelper> sNotificationsMockingHelper = + new HelperAccessor<>(IAutoNotificationMockingHelper.class); @Test public void testScrollUpAndDown() { diff --git a/tests/automotive/health/notification/tests/Android.bp b/tests/automotive/health/notification/tests/Android.bp index 8c7f26668..f041ebc9c 100644 --- a/tests/automotive/health/notification/tests/Android.bp +++ b/tests/automotive/health/notification/tests/Android.bp @@ -24,7 +24,7 @@ android_test { "androidx.test.rules", "automotive-notification-scenarios", "automotive-health-test-rules", - "automotive-settings-app-helper", + "automotive-notifications-app-helper", "app-helpers-auto-interfaces", "ub-uiautomator", "collector-device-lib-platform", diff --git a/tests/automotive/health/notification/tests/src/android/platform/scenario/notification/ScrollMicrobenchmark.java b/tests/automotive/health/notification/tests/src/android/platform/scenario/notification/ScrollMicrobenchmark.java index 94124c87b..db1e7237e 100644 --- a/tests/automotive/health/notification/tests/src/android/platform/scenario/notification/ScrollMicrobenchmark.java +++ b/tests/automotive/health/notification/tests/src/android/platform/scenario/notification/ScrollMicrobenchmark.java @@ -25,11 +25,17 @@ import org.junit.runner.RunWith; public class ScrollMicrobenchmark extends Scroll { @BeforeClass public static void openApp() { + // Populate Notifications + sNotificationsMockingHelper.get().postNotifications(5); + // Open Notifications sHelper.get().open(); } @AfterClass public static void closeApp() { + // Clear All Notifications + sNotificationsMockingHelper.get().clearAllNotification(); + // Exit Notifications sHelper.get().exit(); } } diff --git a/tests/automotive/health/radio/src/android/platform/scenario/radio/TuneAndPlay.java b/tests/automotive/health/radio/src/android/platform/scenario/radio/TuneAndPlay.java deleted file mode 100644 index 7bf813808..000000000 --- a/tests/automotive/health/radio/src/android/platform/scenario/radio/TuneAndPlay.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.radio; - -import static org.junit.Assume.assumeTrue; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoRadioHelper; -import android.platform.test.scenario.annotation.Scenario; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.Until; -import androidx.test.InstrumentationRegistry; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** This scenario will tune and play an FM station, assuming radio app is open. */ -@Scenario -@RunWith(JUnit4.class) -public class TuneAndPlay { - - private static final long OPEN_RADIO_TIMEOUT_MS = 10000; - private static HelperAccessor<IAutoRadioHelper> sHelper = - new HelperAccessor<>(IAutoRadioHelper.class); - - @Before - public void checkApp() { - // TODO: Remove the checking logic and use default helper open() method after migrating to Q - UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); - String pkgName = sHelper.get().getPackage(); - assumeTrue(device.wait(Until.hasObject(By.pkg(pkgName).depth(0)), OPEN_RADIO_TIMEOUT_MS)); - } - - @Test - public void testTuneAndPlay() { - sHelper.get().setStation("FM", 92.3); - sHelper.get().playRadio(); - } -} diff --git a/tests/automotive/health/radio/tests/Android.bp b/tests/automotive/health/radio/tests/Android.bp deleted file mode 100644 index 668017d84..000000000 --- a/tests/automotive/health/radio/tests/Android.bp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2021 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 { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -android_test { - name: "AndroidAutomotiveRadioScenarioTests", - min_sdk_version: "24", - static_libs: [ - "androidx.test.runner", - "androidx.test.rules", - "automotive-radio-scenarios", - "automotive-health-test-rules", - "automotive-settings-app-helper", - "app-helpers-auto-interfaces", - "ub-uiautomator", - "collector-device-lib-platform", - "common-platform-scenarios", - "common-platform-scenario-tests", - "microbenchmark-device-lib", - "platform-test-options", - ], - srcs: ["src/**/*.java"], - test_suites: ["catbox"], -} diff --git a/tests/automotive/health/radio/tests/AndroidManifest.xml b/tests/automotive/health/radio/tests/AndroidManifest.xml deleted file mode 100644 index 3dcbfdb0b..000000000 --- a/tests/automotive/health/radio/tests/AndroidManifest.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2021 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="android.platform.test.scenario.radio" > - <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" /> - <uses-permission android:name="android.permission.DUMP" /> - <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> - <uses-permission android:name="android.permission.MANAGE_USERS" /> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> - - <application> - <uses-library android:name="android.test.runner"/> - </application> - <instrumentation - android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.platform.test.scenario.radio" - android:label="Android Automotive Radio Scenario-Based Tests" /> -</manifest>
\ No newline at end of file diff --git a/tests/automotive/health/radio/tests/src/android/platform/scenario/radio/OpenAppMicrobenchmark.java b/tests/automotive/health/radio/tests/src/android/platform/scenario/radio/OpenAppMicrobenchmark.java deleted file mode 100644 index b00e07113..000000000 --- a/tests/automotive/health/radio/tests/src/android/platform/scenario/radio/OpenAppMicrobenchmark.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2021 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 android.platform.test.scenario.radio; - -import android.platform.helpers.HelperAccessor; -import android.platform.helpers.IAutoGenericAppHelper; -import android.platform.test.scenario.AppStartupRunRule; -import android.platform.test.microbenchmark.Microbenchmark; - -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.runner.RunWith; - -@RunWith(Microbenchmark.class) -public class OpenAppMicrobenchmark extends OpenApp { - @Rule public AppStartupRunRule mAppStartupRunRule = new AppStartupRunRule<>(sHelper.get()); - - private static final String RADIO_PACKAGE = "com.android.car.radio"; - private static final String MEDIA_TEMPLATE = "android.car.intent.action.MEDIA_TEMPLATE"; - private static final Map<String, String> RADIO_SERVICE_EXTRA_ARGS = - Stream.of( - new Object[][] { - { - "android.car.intent.extra.MEDIA_COMPONENT", - "com.android.car.radio/com.android.car.radio.service.RadioAppService" - }, - }) - .collect(Collectors.toMap(data -> (String) data[0], data -> (String) data[1])); - - static HelperAccessor<IAutoGenericAppHelper> sRadioServiceHelper = - new HelperAccessor<>(IAutoGenericAppHelper.class); - - static { - sRadioServiceHelper.get().setPackage(RADIO_PACKAGE); - sRadioServiceHelper.get().setLaunchAction(MEDIA_TEMPLATE, RADIO_SERVICE_EXTRA_ARGS); - } - - @BeforeClass - public static void setUp() { - // Open radio via com.android.car.radio.service.RadioAppService once otherwise the - // foreground app could be stuck at some other media apps(e.g. Bluetooth). - sRadioServiceHelper.get().open(); - } -} diff --git a/tests/codecoverage/hosttest/Android.bp b/tests/codecoverage/hosttest/Android.bp new file mode 100644 index 000000000..584c710be --- /dev/null +++ b/tests/codecoverage/hosttest/Android.bp @@ -0,0 +1,19 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +java_test_host { + name: "CoverageSmokeTest", + + srcs: ["src/**/*.java"], + test_suites: ["general-tests"], + + libs: [ + "tradefed", + "junit", + ], + + data: [ + ":CoverageInstrumentationSampleTest", + ], +} diff --git a/tests/codecoverage/hosttest/AndroidTest.xml b/tests/codecoverage/hosttest/AndroidTest.xml new file mode 100644 index 000000000..7d1e95a75 --- /dev/null +++ b/tests/codecoverage/hosttest/AndroidTest.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration description="run coverage smoke test"> + <option name="test-tag" value="CoverageSmokeTest" /> + <option name="test-suite-tag" value="coverage-smoke-test-postsubmit" /> + <test class="com.android.tradefed.testtype.HostTest" > + <option name="class" value="android.platform.test.coverage.CoverageSmokeTest" /> + </test> +</configuration> diff --git a/tests/codecoverage/hosttest/src/android/platform/test/CoverageSmokeTest.java b/tests/codecoverage/hosttest/src/android/platform/test/CoverageSmokeTest.java new file mode 100644 index 000000000..03dff36da --- /dev/null +++ b/tests/codecoverage/hosttest/src/android/platform/test/CoverageSmokeTest.java @@ -0,0 +1,89 @@ +package android.platform.test.coverage; + +import static com.google.common.base.Verify.verifyNotNull; +import static com.google.common.truth.Truth.assertThat; + +import com.android.tradefed.build.IBuildInfo; +import com.android.tradefed.device.DeviceNotAvailableException; +import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; +import com.android.tradefed.result.TestRunResult; +import com.android.tradefed.targetprep.TargetSetupError; +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; +import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; +import com.android.tradefed.testtype.junit4.DeviceTestRunOptions; +import com.android.tradefed.util.AdbRootElevator; +import com.android.tradefed.util.FileUtil; +import com.google.common.collect.ImmutableMap; + +import java.io.File; +import java.io.InputStream; +import java.io.IOException; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; + +import org.jacoco.core.analysis.Analyzer; +import org.jacoco.core.analysis.CoverageBuilder; +import org.jacoco.core.analysis.IBundleCoverage; +import org.jacoco.core.tools.ExecFileLoader; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Runs an instrumentation test and verifies the coverage report. */ +@RunWith(DeviceJUnit4ClassRunner.class) +public final class CoverageSmokeTest extends BaseHostJUnit4Test { + + private static final String COVERAGE_MEASUREMENT_KEY = "coverageFilePath"; + private static final String INNER_JAR_PATH = + "out/target/common/obj/APPS/CoverageInstrumentationSampleTest_intermediates/jacoco-report-classes.jar"; + + @Before + public void runCoverageDeviceTests() throws DeviceNotAvailableException, TargetSetupError { + installPackage("CoverageInstrumentationSampleTest.apk"); + DeviceTestRunOptions options = + new DeviceTestRunOptions("android.platform.test.coverage") + .setTestClassName( + "android.platform.test.coverage.CoverageInstrumentationTest") + .setTestMethodName("testCoveredMethod") + .setDisableHiddenApiCheck(true) + .addInstrumentationArg("coverage", "true"); + runDeviceTests(options); + } + + @Test + public void instrumentationTest_generatesJavaCoverage() + throws DeviceNotAvailableException, IOException { + TestRunResult testRunResult = getLastDeviceRunResults(); + Metric devicePathMetric = testRunResult.getRunProtoMetrics().get(COVERAGE_MEASUREMENT_KEY); + String testCoveragePath = devicePathMetric.getMeasurements().getSingleString(); + ExecFileLoader execFileLoader = new ExecFileLoader(); + File coverageFile = null; + try (AdbRootElevator adbRoot = new AdbRootElevator(getDevice())) { + coverageFile = getDevice().pullFile(testCoveragePath); + execFileLoader.load(coverageFile); + } catch (DeviceNotAvailableException | IOException e) { + throw new RuntimeException(e); + } finally { + FileUtil.deleteFile(coverageFile); + } + CoverageBuilder builder = new CoverageBuilder(); + Analyzer analyzer = new Analyzer(execFileLoader.getExecutionDataStore(), builder); + IBuildInfo buildInfo = getBuild(); + File jacocoAllClassesJar = + verifyNotNull( + buildInfo.getFile("jacoco-report-classes-all.jar"), + "Could not get jacoco-report-classes-all.jar from the build."); + URI uri = URI.create("jar:file:" + jacocoAllClassesJar.getPath()); + try (FileSystem zip = FileSystems.newFileSystem(uri, ImmutableMap.of())) { + try (InputStream in = Files.newInputStream(zip.getPath(INNER_JAR_PATH))) { + analyzer.analyzeAll(in, "jacoco-report-classes.jar"); + } + } + IBundleCoverage coverage = builder.getBundle("JaCoCo Coverage Report"); + + assertThat(coverage).isNotNull(); + assertThat(coverage.getPackages()).isNotEmpty(); + } +} diff --git a/tests/codecoverage/instrumentation/Android.bp b/tests/codecoverage/instrumentation/Android.bp new file mode 100644 index 000000000..99e13d082 --- /dev/null +++ b/tests/codecoverage/instrumentation/Android.bp @@ -0,0 +1,16 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_test { + name: "CoverageInstrumentationSampleTest", + + srcs: ["src/**/*.java"], + sdk_version: "current", + min_sdk_version: "21", + + static_libs: ["androidx.test.runner"], + certificate: "platform", + + test_suites: ["device-tests"], +} diff --git a/tests/codecoverage/instrumentation/AndroidManifest.xml b/tests/codecoverage/instrumentation/AndroidManifest.xml new file mode 100644 index 000000000..69b0807d0 --- /dev/null +++ b/tests/codecoverage/instrumentation/AndroidManifest.xml @@ -0,0 +1,10 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android.platform.test.coverage" > + + <application/> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.platform.test.coverage" + android:label="Coverage smoke test"/> + +</manifest> diff --git a/tests/codecoverage/instrumentation/AndroidTest.xml b/tests/codecoverage/instrumentation/AndroidTest.xml new file mode 100644 index 000000000..eaeb45409 --- /dev/null +++ b/tests/codecoverage/instrumentation/AndroidTest.xml @@ -0,0 +1,14 @@ +<configuration description="Runs sample instrumentation test."> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-instrumentation" /> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="CoverageInstrumentationSampleTest.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct" /> + <option name="test-tag" value="SampleInstrumentationTest" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="android.platform.test.coverage" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + </test> +</configuration> diff --git a/tests/codecoverage/instrumentation/src/android/platform/test/CoverageInstrumentationTest.java b/tests/codecoverage/instrumentation/src/android/platform/test/CoverageInstrumentationTest.java new file mode 100644 index 000000000..b4d92a161 --- /dev/null +++ b/tests/codecoverage/instrumentation/src/android/platform/test/CoverageInstrumentationTest.java @@ -0,0 +1,22 @@ +package android.platform.test.coverage; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class CoverageInstrumentationTest { + + private Example mExample; + + @Before + public void setUp() { + mExample = new Example(); + } + + @Test + public void testCoveredMethod() { + mExample.coveredMethod(); + } +} diff --git a/tests/codecoverage/instrumentation/src/android/platform/test/Example.java b/tests/codecoverage/instrumentation/src/android/platform/test/Example.java new file mode 100644 index 000000000..ecda37737 --- /dev/null +++ b/tests/codecoverage/instrumentation/src/android/platform/test/Example.java @@ -0,0 +1,9 @@ +package android.platform.test.coverage; + +/** A minimal class used to produce coverage information. */ +public class Example { + + public void coveredMethod() {} + + public void notCoveredMethod() {} +} diff --git a/tests/example/mobly/Android.bp b/tests/example/mobly/Android.bp index a38a4601f..b9623726e 100644 --- a/tests/example/mobly/Android.bp +++ b/tests/example/mobly/Android.bp @@ -24,5 +24,5 @@ python_test_host { test_options: { unit_test: false, }, - data: ["config.yaml"], + data: ["mobly-hello-world-test_config.yaml"], } diff --git a/tests/example/mobly/AndroidTest.xml b/tests/example/mobly/AndroidTest.xml index b455cfde1..c005741a8 100644 --- a/tests/example/mobly/AndroidTest.xml +++ b/tests/example/mobly/AndroidTest.xml @@ -20,7 +20,7 @@ </target_preparer> <test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest"> <option name="mobly-par-file-name" value="mobly-hello-world-test" /> - <option name="mobly-config-file-name" value="config.yaml" /> + <option name="mobly-config-file-name" value="mobly-hello-world-test_config.yaml" /> <option name="mobly-test-timeout" value="1800000" /> </test> </configuration> diff --git a/tests/example/mobly/config.yaml b/tests/example/mobly/mobly-hello-world-test_config.yaml index daf65770d..daf65770d 100644 --- a/tests/example/mobly/config.yaml +++ b/tests/example/mobly/mobly-hello-world-test_config.yaml diff --git a/tests/functional/devicehealthchecks/assets/bug_map b/tests/functional/devicehealthchecks/assets/bug_map index f8e614a7b..fe49257bb 100644 --- a/tests/functional/devicehealthchecks/assets/bug_map +++ b/tests/functional/devicehealthchecks/assets/bug_map @@ -4,6 +4,9 @@ system_app_anr com.google.android.apps.dreamliner/.dnd.DockConditionProviderServ system_app_anr act=android.hardware.usb.action.USB_STATE[\S\s]*cmp=com.google.android.projection.gearhead[\s\S]*ConnectivityEventHandlerImpl\$ConnectivityEventBroadcastReceiver 130956983 system_app_anr com.google.android.euicc[\s\S]*executing\sservice\scom.google.android.euicc/com.android.euicc.service.EuiccServiceImpl 174479972 system_app_anr com.google.android.apps.wellbeing*.*ContextManagerRestartBroadcastReceiver_Receiver[\s\S]*cf_x86_64_phone 166183732 +system_app_anr executing\sservice\scom.google.android.as/com.google.android.apps.miphone.aiai.echo.notificationintelligence.scheduler.impl.NotificationJobService 192300119 +system_app_anr executing\sservice\scom.google.android.as/com.google.android.apps.miphone.aiai.echo.scheduler.EchoJobService 192300119 +system_app_anr executing\sservice\scom.google.android.as/com.google.android.apps.miphone.aiai.actions.service.ActionRankingDataTtlService 192300119 system_app_crash -1\|android\|26\|null\|1000 155073214 system_app_crash -1\|android\|32\|null\|1000 155073214 system_app_crash android.database.sqlite.SQLiteCloseable.acquireReference 159658068 diff --git a/tests/functional/overviewtests/src/com/android/overview/functional/OverviewHelper.java b/tests/functional/overviewtests/src/com/android/overview/functional/OverviewHelper.java index 8f4fd12c8..c7db8217b 100644 --- a/tests/functional/overviewtests/src/com/android/overview/functional/OverviewHelper.java +++ b/tests/functional/overviewtests/src/com/android/overview/functional/OverviewHelper.java @@ -16,29 +16,18 @@ package android.overview.functional; -import java.io.File; -import java.io.IOException; import android.app.Instrumentation; -import android.app.UiAutomation; import android.content.Intent; import android.content.pm.PackageManager; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; -import android.os.PowerManager; -import android.os.RemoteException; import android.os.SystemClock; -import android.support.test.launcherhelper.ILauncherStrategy; -import android.support.test.launcherhelper.LauncherStrategyFactory; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiObject2; -import android.support.test.uiautomator.UiObjectNotFoundException; import android.support.test.uiautomator.Until; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.MediumTest; -import android.util.Log; import org.junit.Assert; public class OverviewHelper { @@ -133,7 +122,7 @@ public class OverviewHelper { scrollToTopOfRecents(recentsView); // click clear all UiObject2 clearAll = mDevice.wait(Until.findObject(By.text("CLEAR ALL")),TIMEOUT); - if (!clearAll.equals(null)) { + if (clearAll != null) { clearAll.click(); } Thread.sleep(TIMEOUT); |