diff options
author | SzuWei Lin <szuweilin@google.com> | 2022-01-06 13:49:06 +0800 |
---|---|---|
committer | SzuWei Lin <szuweilin@google.com> | 2022-01-06 13:49:06 +0800 |
commit | 915c3b5e58ff4b5a68884c108fdc3744dc94a1e5 (patch) | |
tree | 9f2956fe766705b9adf8add71a49aee419fe3c12 | |
parent | 07bc05d319d6f211d0ee109d61a6634776441b85 (diff) | |
parent | fbc839552a2a7d95845980834956ca8f72139975 (diff) | |
download | platform_testing-android12-gsi.tar.gz |
Merge branch android12-platform-releaseandroid12-gsi
Change-Id: I942b4175ac80558d96feb5e1cb8b697206e3b429
106 files changed, 2537 insertions, 1936 deletions
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/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/compatibility-common-util/Android.bp b/libraries/compatibility-common-util/Android.bp index bc40510fc..714a681c7 100644 --- a/libraries/compatibility-common-util/Android.bp +++ b/libraries/compatibility-common-util/Android.bp @@ -26,6 +26,7 @@ java_library_static { static_libs: [ "guava", "junit", + "platform-test-annotations", ], } diff --git a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/BusinessLogicExecutor.java b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/BusinessLogicExecutor.java index b137801d6..8905fce3a 100644 --- a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/BusinessLogicExecutor.java +++ b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/BusinessLogicExecutor.java @@ -140,10 +140,14 @@ public abstract class BusinessLogicExecutor { } String className = method.substring(0, index); Class cls = Class.forName(className); - Object obj = cls.getDeclaredConstructor().newInstance(); + Object obj = null; if (getTestObject() != null && cls.isAssignableFrom(getTestObject().getClass())) { // The given method is a member of the test class, use the known test class instance obj = getTestObject(); + } else { + // Only instantiate a new object if we don't already have one. + // Otherwise the class could have been an interface which isn't instantiatable. + obj = cls.getDeclaredConstructor().newInstance(); } ResolvedMethod rm = getResolvedMethod(cls, method.substring(index + 1), args); return rm.invoke(obj); diff --git a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/BusinessLogicMapStore.java b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/BusinessLogicMapStore.java new file mode 100644 index 000000000..d208d392d --- /dev/null +++ b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/BusinessLogicMapStore.java @@ -0,0 +1,58 @@ +/* + * 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.compatibility.common.util; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** Business-Logic GCL-accessible utility for key-value stores. */ +public class BusinessLogicMapStore { + + private static Map<String, Map<String, String>> maps = new HashMap<>(); + + public boolean hasMap(String mapName) { + return maps.containsKey(mapName); + } + + public void putMap(String mapName, String separator, String... keyValuePairs) { + Map<String, String> map = maps.get(mapName); + if (map == null) { + map = new HashMap<>(); + maps.put(mapName, map); + } + + for (String keyValuePair : keyValuePairs) { + String[] tmp = keyValuePair.split(separator, 2); + if (tmp.length != 2) { + throw new IllegalArgumentException( + "Can't split key-value pair for \"" + keyValuePair + "\""); + } + String key = tmp[0]; + String value = tmp[1]; + map.put(key, value); + } + } + + public static Map<String, String> getMap(String mapName) { + Map<String, String> map = maps.get(mapName); + if (map == null) { + return null; + } + return Collections.unmodifiableMap(map); + } +} diff --git a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/googleplaybooks/ScrollMicrobenchmark.java b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/DescriptionProvider.java index d7158252a..2c58fd7a3 100644 --- a/tests/automotive/health/mediacenter/tests/src/android/platform/scenario/mediacenter/googleplaybooks/ScrollMicrobenchmark.java +++ b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/DescriptionProvider.java @@ -13,23 +13,22 @@ * 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; +package com.android.compatibility.common.util; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; -@RunWith(Microbenchmark.class) -public class ScrollMicrobenchmark extends Scroll { - @BeforeClass - public static void openApp() { - sHelper.get().open(); +/** Provide a way for tests to get their description while running. */ +public class DescriptionProvider extends TestWatcher { + private volatile Description description; + + @Override + protected void starting(Description description) { + this.description = description; } - @AfterClass - public static void closeApp() { - sHelper.get().exit(); + public Description getDescription() { + return description; } } diff --git a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/MultiLog.java b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/MultiLog.java new file mode 100644 index 000000000..3a63bd4a4 --- /dev/null +++ b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/MultiLog.java @@ -0,0 +1,54 @@ +/* + * 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.compatibility.common.util; + +/** Provide an interface for logging on host+device-common code. */ +public interface MultiLog { + + /** + * Log information with whichever logging mechanism is available to the instance. This varies + * from host-side to device-side, so implementations are left to subclasses. + * Host: MultiLogHost + * Device: MultiLogDevice + * See {@link String.format(String, Object...)} for parameter information. + */ + public void logInfo(String logTag, String format, Object... args); + + /** + * Log debugging information to the host or device logs (depending on implementation). + * See {@link String.format(String, Object...)} for parameter information. + * Host: MultiLogHost + * Device: MultiLogDevice + */ + public void logDebug(String logTag, String format, Object... args); + + /** + * Log warnings to the host or device logs (depending on implementation). + * See {@link String.format(String, Object...)} for parameter information. + * Host: MultiLogHost + * Device: MultiLogDevice + */ + public void logWarn(String logTag, String format, Object... args); + + /** + * Log errors to the host or device logs (depending on implementation). + * See {@link String.format(String, Object...)} for parameter information. + * Host: MultiLogHost + * Device: MultiLogDevice + */ + public void logError(String logTag, String format, Object... args); +} diff --git a/libraries/compatibility-common-util/src/com/android/sts/OWNERS b/libraries/compatibility-common-util/src/com/android/sts/OWNERS new file mode 100644 index 000000000..d029d2098 --- /dev/null +++ b/libraries/compatibility-common-util/src/com/android/sts/OWNERS @@ -0,0 +1,2 @@ +# STS Owners +cdombroski@google.com diff --git a/libraries/compatibility-common-util/src/com/android/sts/common/util/SplUtils.java b/libraries/compatibility-common-util/src/com/android/sts/common/util/SplUtils.java new file mode 100644 index 000000000..4144fff76 --- /dev/null +++ b/libraries/compatibility-common-util/src/com/android/sts/common/util/SplUtils.java @@ -0,0 +1,40 @@ +/* + * 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.sts.common.util; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +/** Tools for Security Patch Levels and LocalDates representing them. */ +public final class SplUtils { + private static final ZoneId UTC_ZONE_ID = ZoneId.of("UTC"); + private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + public static LocalDate localDateFromMillis(long millis) { + return Instant.ofEpochMilli(millis).atZone(UTC_ZONE_ID).toLocalDate(); + } + + public static LocalDate localDateFromSplString(String spl) { + return LocalDate.parse(spl, formatter); + } + + public static String format(LocalDate date) { + return date.format(formatter); + } +} diff --git a/libraries/compatibility-common-util/src/com/android/sts/common/util/StsLogic.java b/libraries/compatibility-common-util/src/com/android/sts/common/util/StsLogic.java new file mode 100644 index 000000000..1dec855c2 --- /dev/null +++ b/libraries/compatibility-common-util/src/com/android/sts/common/util/StsLogic.java @@ -0,0 +1,165 @@ +/* + * 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.sts.common.util; + +import static org.junit.Assume.*; + +import android.platform.test.annotations.AsbSecurityTest; + +import com.android.compatibility.common.util.BusinessLogicMapStore; +import com.android.compatibility.common.util.MultiLog; + +import org.junit.runner.Description; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** Common STS extra business logic for host-side and device-side to implement. */ +public interface StsLogic extends MultiLog { + + static final String LOG_TAG = StsLogic.class.getSimpleName(); + + // keep in sync with google3: + // //wireless/android/partner/apbs/*/config/xtsbgusinesslogic/sts_business_logic.gcl + List<String> STS_EXTRA_BUSINESS_LOGIC_FULL = Arrays.asList(new String[]{ + "uploadSpl", + "uploadModificationTime", + }); + List<String> STS_EXTRA_BUSINESS_LOGIC_INCREMENTAL = Arrays.asList(new String[]{ + "uploadSpl", + "uploadModificationTime", + "incremental", + }); + + Description getTestDescription(); + + LocalDate getDeviceSpl(); + + default long[] getCveBugIds() { + AsbSecurityTest annotation = getTestDescription().getAnnotation(AsbSecurityTest.class); + if (annotation == null) { + return null; + } + return annotation.cveBugId(); + } + + default LocalDate getMinTestSpl() { + Map<String, String> map = BusinessLogicMapStore.getMap("security_bulletins"); + if (map == null) { + throw new IllegalArgumentException("Could not find the security bulletin map"); + } + LocalDate minSpl = null; + for (long cveBugId : getCveBugIds()) { + String splString = map.get(Long.toString(cveBugId)); + if (splString == null) { + // This bug id wasn't found in the map. + // This is a new test or the bug was removed from the bulletin and this is an old + // binary. Neither is a critical issue and the test will run in these cases. + // New test: developer should be able to write the test without getting blocked. + // Removed bug + old binary: test will run. + logInfo(LOG_TAG, "could not find the CVE bug %d in the spl map", cveBugId); + continue; + } + LocalDate spl = SplUtils.localDateFromSplString(splString); + if (minSpl == null) { + minSpl = spl; + } else if (spl.isBefore(minSpl)) { + minSpl = spl; + } + } + return minSpl; + } + + default LocalDate getMinModificationDate() { + Map<String, String> map = BusinessLogicMapStore.getMap("sts_modification_times"); + if (map == null) { + throw new IllegalArgumentException("Could not find the modification date map"); + } + LocalDate minModificationDate = null; + for (long cveBugId : getCveBugIds()) { + String modificationMillisString = map.get(Long.toString(cveBugId)); + if (modificationMillisString == null) { + logInfo(LOG_TAG, + "Could not find the CVE bug %d in the modification date map", cveBugId); + continue; + } + LocalDate modificationDate = + SplUtils.localDateFromMillis(Long.parseLong(modificationMillisString)); + if (minModificationDate == null) { + minModificationDate = modificationDate; + } else if (modificationDate.isBefore(minModificationDate)) { + minModificationDate = modificationDate; + } + } + return minModificationDate; + } + + default boolean shouldSkipIncremental() { + logDebug(LOG_TAG, "filtering by incremental"); + + long[] bugIds = getCveBugIds(); + if (bugIds == null) { + // There were no @AsbSecurityTest annotations + logInfo(LOG_TAG, "not an ASB test"); + return false; + } + + // check if test spl is older than the past 6 months from the device spl + LocalDate deviceSpl = getDeviceSpl(); + LocalDate incrementalCutoffSpl = deviceSpl.plusMonths(-6); + + LocalDate minTestModifiedDate = getMinModificationDate(); + if (minTestModifiedDate == null) { + // could not get the modification date - run the test + if (Arrays.stream(bugIds).min().getAsLong() < 157905780) { + // skip if the bug id is older than ~ June 2020 + // otherwise the test will run due to missing data + logDebug(LOG_TAG, "no data for this old test"); + return true; + } + return false; + } + if (minTestModifiedDate.isAfter(incrementalCutoffSpl)) { + logDebug(LOG_TAG, "the test was recently modified"); + return false; + } + + LocalDate minTestSpl = getMinTestSpl(); + if (minTestSpl == null) { + // could not get the test spl - run the test + logWarn(LOG_TAG, "could not get the test SPL"); + return false; + } + if (minTestSpl.isAfter(incrementalCutoffSpl)) { + logDebug(LOG_TAG, "the test has a recent SPL"); + return false; + } + + logDebug(LOG_TAG, "test should skip"); + return true; + } + + default boolean shouldSkipSpl() { + return true; + } + + default void skip(String message) { + assumeTrue(message, false); + } +} 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/health/rules/Android.bp b/libraries/health/rules/Android.bp index c72e8a8e1..7236494bd 100644 --- a/libraries/health/rules/Android.bp +++ b/libraries/health/rules/Android.bp @@ -28,6 +28,7 @@ java_library { "package-helper", "launcher-aosp-tapl", "flickerlib", + "statsd-helper", ], srcs: ["src/**/*.java"], } @@ -42,6 +43,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/src/android/platform/test/rule/DynamicRuleChain.java b/libraries/health/rules/src/android/platform/test/rule/DynamicRuleChain.java new file mode 100644 index 000000000..44733e427 --- /dev/null +++ b/libraries/health/rules/src/android/platform/test/rule/DynamicRuleChain.java @@ -0,0 +1,152 @@ +/* + * 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.util.Log; + +import androidx.annotation.VisibleForTesting; +import androidx.test.InstrumentationRegistry; + +import org.junit.rules.TestRule; +import org.junit.runners.model.Statement; +import org.junit.runner.Description; + +import java.lang.reflect.Constructor; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * A rule that loads other ({@link TestRule}s) at runtime. + * + * <p>Rules are supplied as a comma-separated list. If the rule is in the {@code + * android.platform.test.rule} package (and not in its sub-packages), it can be passed via their + * simple class name; otherwise, its fully-qualified class name must be used. + * + * <p>Each passed-in rule wraps around the subsequent rule; this fits the mental model of JUnit's + * {@code RuleChain}. For example, if {@code "rule1,rule2,rule3"} are passed in, {@code rule1} will + * wrap around {@code rule2} and {@code rule2} will wrap around {@code rule3}; {@code rule3} will be + * applied closest to the test method. + */ +public class DynamicRuleChain implements TestRule { + private static final String LOG_TAG = DynamicRuleChain.class.getSimpleName(); + + @VisibleForTesting static final String DEFAULT_RULES_OPTION = "dynamic-rules"; + + @VisibleForTesting static final String RULES_PACKAGE = "android.platform.test.rule"; + + private String mRulesOptionName = DEFAULT_RULES_OPTION; + private Bundle mArgs; + + public DynamicRuleChain() { + this(InstrumentationRegistry.getArguments()); + } + + public DynamicRuleChain(Bundle args) { + mArgs = args; + } + + public DynamicRuleChain(String rulesOptionName, Bundle args) { + this(args); + if (rulesOptionName == null || rulesOptionName.isEmpty()) { + throw new IllegalArgumentException( + "Rules option name override must not be null or empty."); + } + mRulesOptionName = rulesOptionName; + } + + @Override + public Statement apply(final Statement base, final Description description) { + List<String> ruleNames = Arrays.asList(mArgs.getString(mRulesOptionName, "").split(",")); + // The inner rules need to be applied first, so reverse the class names first. + Collections.reverse(ruleNames); + // Instantiate rules and apply them one-by-one. + // JUnit's RunRules is not used here because its ordering of rules is not clearly defined. + Statement statement = base; + for (String ruleName : ruleNames) { + if (ruleName.isEmpty()) { + continue; + } + TestRule rule = null; + // We could use a regex here, but this is simpler and should work just as well. + if (ruleName.contains(".")) { + Log.i( + LOG_TAG, + String.format( + "Attempting to dynamically load rule with fully qualified name %s.", + ruleName)); + try { + rule = loadRuleByFullyQualifiedName(ruleName); + } catch (Exception e) { + throw new IllegalArgumentException( + String.format( + "Failed to dynamically load rule with fully qualified name %s.", + ruleName), + e); + } + } else { + String fullName = String.format("%s.%s", RULES_PACKAGE, ruleName); + Log.i( + LOG_TAG, + String.format( + "Attempting to dynamically load rule with simple class name %s" + + " (fully qualified name: %s).", + ruleName, fullName)); + try { + rule = loadRuleByFullyQualifiedName(fullName); + } catch (Exception e) { + throw new IllegalArgumentException( + String.format( + "Failed to dynamically load rule with simple class name %s.", + ruleName), + e); + } + } + statement = rule.apply(statement, description); + } + return statement; + } + + private TestRule loadRuleByFullyQualifiedName(String name) throws Exception { + // Load the rule class using reflection. + Class<?> loadedClass = null; + try { + loadedClass = DynamicRuleChain.class.getClassLoader().loadClass(name); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException( + String.format("Could not find class with fully qualified name %s.", name)); + } + // Ensure that the class found is a TestRule. + if (loadedClass == null || (!TestRule.class.isAssignableFrom(loadedClass))) { + throw new IllegalArgumentException( + String.format("Class %s is not a TestRule.", loadedClass)); + } + + // Use the default constructor to create a rule instance. + try { + Constructor<?> constructor = loadedClass.getConstructor(); + // Cast is safe as we have vetted that loadedClass is a TestRule. + return (TestRule) constructor.newInstance(); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException( + String.format( + "Rule %s cannot be instantiated with an empty constructor", + loadedClass), + e); + } + } +} 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/rules/tests/src/android/platform/test/rule/DynamicRuleChainTest.java b/libraries/health/rules/tests/src/android/platform/test/rule/DynamicRuleChainTest.java new file mode 100644 index 000000000..a866451d4 --- /dev/null +++ b/libraries/health/rules/tests/src/android/platform/test/rule/DynamicRuleChainTest.java @@ -0,0 +1,207 @@ +/* + * 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 static com.google.common.truth.Truth.assertThat; + +import android.os.Bundle; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.Description; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.model.Statement; + +import java.util.ArrayList; +import java.util.List; + +/** Unit tests for {@link DynamicRuleChain}. */ +@RunWith(JUnit4.class) +public class DynamicRuleChainTest { + private static final Description DESCRIPTION = + Description.createTestDescription("class", "method"); + + // A static variable is used so that the rules in this test can modify its state while being + // static (and thus able to be created via an empty constructor). This route is taken as the + // rules themselves are not directly observable due to being created via reflection from + // DynamicRuleChain. + private static final List<String> sLogs = new ArrayList<String>(); + + private static final Statement mStatement = + new Statement() { + @Override + public void evaluate() { + sLogs.add("Test execution"); + } + }; + + @Rule public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void setUp() { + // Clear the logs between tests. + sLogs.clear(); + } + + @Test + public void testAppliesRuleBySimpleClassNameForRulesInKnownPackage() throws Throwable { + DynamicRuleChain chain = createWithRuleNames("DynamicRuleChainTest$Rule1"); + Statement applied = chain.apply(mStatement, DESCRIPTION); + applied.evaluate(); + assertThat(sLogs).containsExactly("Rule1 starting", "Test execution", "Rule1 finished"); + } + + @Test + public void testAppliesRuleByFullyQualifiedClassName() throws Throwable { + DynamicRuleChain chain = + createWithRuleNames("android.platform.test.rule.DynamicRuleChainTest$Rule1"); + Statement applied = chain.apply(mStatement, DESCRIPTION); + applied.evaluate(); + assertThat(sLogs).containsExactly("Rule1 starting", "Test execution", "Rule1 finished"); + } + + @Test + public void testThrowsOnNonexistentSimpleClassName() throws Throwable { + String badName = "NotARuleRule"; + expectedException.expectMessage( + String.format( + "Failed to dynamically load rule with simple class name %s.", badName)); + DynamicRuleChain chain = createWithRuleNames(badName); + chain.apply(mStatement, DESCRIPTION); + } + + @Test + public void testThrowsOnNonexistentFullyQualifiedClassName() throws Throwable { + String badName = "not.a.rule.Rule"; + expectedException.expectMessage( + String.format( + "Failed to dynamically load rule with fully qualified name %s.", badName)); + DynamicRuleChain chain = createWithRuleNames(badName); + chain.apply(mStatement, DESCRIPTION); + } + + @Test + public void testMultipleRulesAreAppliedInCorrectOrder() throws Throwable { + DynamicRuleChain chain = + createWithRuleNames( + "DynamicRuleChainTest$Rule2", + "android.platform.test.rule.DynamicRuleChainTest$Rule1"); + Statement applied = chain.apply(mStatement, DESCRIPTION); + applied.evaluate(); + // Rule2's logs should be outside, and Rule1's logs should be inside. + assertThat(sLogs) + .containsExactly( + "Rule2 starting", + "Rule1 starting", + "Test execution", + "Rule1 finished", + "Rule2 finished"); + } + + @Test + public void testInvalidRuleNameInMultipleRulesAlsoThrows() throws Throwable { + String badName = "not.a.rule.Rule"; + expectedException.expectMessage( + String.format( + "Failed to dynamically load rule with fully qualified name %s.", badName)); + DynamicRuleChain chain = + createWithRuleNames( + badName, "android.platform.test.rule.DynamicRuleChainTest$Rule1"); + chain.apply(mStatement, DESCRIPTION); + } + + @Test + public void testSupportsDuplicateSimpleRuleNames() throws Throwable { + DynamicRuleChain chain = + createWithRuleNames( + "DynamicRuleChainTest$Rule2", + "android.platform.test.rule.DynamicRuleChainTest$Rule1", + "DynamicRuleChainTest$Rule2"); + Statement applied = chain.apply(mStatement, DESCRIPTION); + applied.evaluate(); + // Rule2's logs should be outside, and Rule1's logs should be inside. + assertThat(sLogs) + .containsExactly( + "Rule2 starting", + "Rule1 starting", + "Rule2 starting", + "Test execution", + "Rule2 finished", + "Rule1 finished", + "Rule2 finished"); + } + + @Test + public void testSupportsDuplicateFullyQualifiedRuleNames() throws Throwable { + DynamicRuleChain chain = + createWithRuleNames( + "android.platform.test.rule.DynamicRuleChainTest$Rule1", + "DynamicRuleChainTest$Rule2", + "android.platform.test.rule.DynamicRuleChainTest$Rule1"); + Statement applied = chain.apply(mStatement, DESCRIPTION); + applied.evaluate(); + // Rule2's logs should be outside, and Rule1's logs should be inside. + assertThat(sLogs) + .containsExactly( + "Rule1 starting", + "Rule2 starting", + "Rule1 starting", + "Test execution", + "Rule1 finished", + "Rule2 finished", + "Rule1 finished"); + } + + private DynamicRuleChain createWithRuleNames(String... ruleNames) { + Bundle args = new Bundle(); + args.putString(DynamicRuleChain.DEFAULT_RULES_OPTION, String.join(",", ruleNames)); + return new DynamicRuleChain(args); + } + + private DynamicRuleChain createWithRulesOptionNameAndRuleNames( + String rulesOptionName, String... ruleNames) { + Bundle args = new Bundle(); + args.putString(rulesOptionName, String.join(",", ruleNames)); + return new DynamicRuleChain(rulesOptionName, args); + } + + public static class Rule1 extends TestWatcher { + @Override + public void starting(Description description) { + sLogs.add("Rule1 starting"); + } + + @Override + public void finished(Description description) { + sLogs.add("Rule1 finished"); + } + } + + public static class Rule2 extends TestWatcher { + @Override + public void starting(Description description) { + sLogs.add("Rule2 starting"); + } + + @Override + public void finished(Description description) { + sLogs.add("Rule2 finished"); + } + } +} 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 e82fd3e18..7ad17de98 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 @@ -23,6 +23,7 @@ import android.os.BatteryManager; import android.os.Bundle; import android.os.SystemClock; import android.platform.test.composer.Iterate; +import android.platform.test.rule.DynamicRuleChain; import android.platform.test.rule.TracePointRule; import android.util.Log; import androidx.annotation.VisibleForTesting; @@ -32,6 +33,7 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -71,6 +73,12 @@ public class Microbenchmark extends BlockJUnit4ClassRunner { }; @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"; + @VisibleForTesting static final String DYNAMIC_INNER_CLASS_RULES_OPTION = "inner-class-rules"; + @VisibleForTesting static final String DYNAMIC_OUTER_TEST_RULES_OPTION = "outer-test-rules"; + @VisibleForTesting static final String DYNAMIC_INNER_TEST_RULES_OPTION = "inner-test-rules"; // 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 @@ -275,7 +283,11 @@ public class Microbenchmark extends BlockJUnit4ClassRunner { /** Re-implement the private rules wrapper from {@link BlockJUnit4ClassRunner} in JUnit 4.12. */ private Statement withRules(FrameworkMethod method, Object target, Statement statement) { Statement result = statement; - List<TestRule> testRules = getTestRules(target); + List<TestRule> testRules = new ArrayList<>(); + // Inner dynamic rules should be included first because RunRules applies rules inside-out. + testRules.add(new DynamicRuleChain(DYNAMIC_INNER_TEST_RULES_OPTION, mArguments)); + testRules.addAll(getTestRules(target)); + testRules.add(new DynamicRuleChain(DYNAMIC_OUTER_TEST_RULES_OPTION, mArguments)); // Apply legacy MethodRules, if they don't overlap with TestRules. for (org.junit.rules.MethodRule each : rules(target)) { if (!testRules.contains(each)) { @@ -283,13 +295,22 @@ public class Microbenchmark extends BlockJUnit4ClassRunner { } } // Apply modern, method-level TestRules in outer statements. - result = - testRules.isEmpty() - ? statement - : new RunRules(result, testRules, describeChild(method)); + result = new RunRules(result, testRules, describeChild(method)); return result; } + /** Add {@link DynamicRuleChain} to existing class rules. */ + @Override + protected List<TestRule> classRules() { + List<TestRule> classRules = new ArrayList<>(); + // Inner dynamic class rules should be included first because RunRules applies rules inside + // -out. + classRules.add(new DynamicRuleChain(DYNAMIC_INNER_CLASS_RULES_OPTION, mArguments)); + classRules.addAll(super.classRules()); + classRules.add(new DynamicRuleChain(DYNAMIC_OUTER_CLASS_RULES_OPTION, mArguments)); + return classRules; + } + /** * Combine the {@code #runChild}, {@code #methodBlock}, and final {@code #runLeaf} methods to * implement the specific {@code Microbenchmark} test behavior. In particular, (1) keep track of diff --git a/libraries/health/runners/microbenchmark/tests/src/android/platform/test/microbenchmark/MicrobenchmarkTest.java b/libraries/health/runners/microbenchmark/tests/src/android/platform/test/microbenchmark/MicrobenchmarkTest.java index 8d4cd822a..fa8e64a24 100644 --- a/libraries/health/runners/microbenchmark/tests/src/android/platform/test/microbenchmark/MicrobenchmarkTest.java +++ b/libraries/health/runners/microbenchmark/tests/src/android/platform/test/microbenchmark/MicrobenchmarkTest.java @@ -25,10 +25,13 @@ import static org.mockito.Mockito.verify; import android.os.Bundle; import android.os.SystemClock; import android.platform.test.microbenchmark.Microbenchmark.TerminateEarlyException; +import android.platform.test.rule.TestWatcher; import android.platform.test.rule.TracePointRule; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.Description; @@ -51,6 +54,15 @@ import java.util.List; */ @RunWith(JUnit4.class) public final class MicrobenchmarkTest { + // Static logs are needed to validate dynamic rules, which are instantiated reflectively and + // cannot access non-static variables. + private static List<String> sLogs = new ArrayList<>(); + + @Before + public void setUp() { + sLogs.clear(); + } + /** * Tests that iterations are respected for microbenchmark tests. */ @@ -407,6 +419,106 @@ public final class MicrobenchmarkTest { .inOrder(); } + /** Test dynamic test rule injection. */ + @Test + public void testDynamicTestRuleInjection() throws InitializationError { + Bundle args = new Bundle(); + args.putString("iterations", "2"); + args.putString("rename-iterations", "false"); + args.putString("terminate-on-test-fail", "false"); + args.putString( + Microbenchmark.DYNAMIC_INNER_TEST_RULES_OPTION, LoggingRule1.class.getName()); + args.putString( + Microbenchmark.DYNAMIC_OUTER_TEST_RULES_OPTION, LoggingRule2.class.getName()); + LoggingMicrobenchmark loggingRunner = + new LoggingMicrobenchmark(LoggingTestWithRules.class, args); + loggingRunner.setOperationLog(sLogs); + new JUnitCore().run(loggingRunner); + assertThat(sLogs) + .containsExactly( + "hardcoded class rule starting", + "logging rule 2 starting", + "hardcoded test rule starting", + "logging rule 1 starting", + "before", + "tight before", + "begin: testMethod(" + + "android.platform.test.microbenchmark.MicrobenchmarkTest" + + "$LoggingTestWithRules)", + "test", + "end", + "tight after", + "after", + "logging rule 1 finished", + "hardcoded test rule finished", + "logging rule 2 finished", + "logging rule 2 starting", + "hardcoded test rule starting", + "logging rule 1 starting", + "before", + "tight before", + "begin: testMethod(" + + "android.platform.test.microbenchmark.MicrobenchmarkTest" + + "$LoggingTestWithRules)", + "test", + "end", + "tight after", + "after", + "logging rule 1 finished", + "hardcoded test rule finished", + "logging rule 2 finished", + "hardcoded class rule finished") + .inOrder(); + } + + /** Test dynamic class rule injection. */ + @Test + public void testDynamicClassRuleInjection() throws InitializationError { + Bundle args = new Bundle(); + args.putString("iterations", "2"); + args.putString("rename-iterations", "false"); + args.putString("terminate-on-test-fail", "false"); + args.putString( + Microbenchmark.DYNAMIC_INNER_CLASS_RULES_OPTION, LoggingRule1.class.getName()); + args.putString( + Microbenchmark.DYNAMIC_OUTER_CLASS_RULES_OPTION, LoggingRule2.class.getName()); + LoggingMicrobenchmark loggingRunner = + new LoggingMicrobenchmark(LoggingTestWithRules.class, args); + loggingRunner.setOperationLog(sLogs); + new JUnitCore().run(loggingRunner); + assertThat(sLogs) + .containsExactly( + "logging rule 2 starting", + "hardcoded class rule starting", + "logging rule 1 starting", + "hardcoded test rule starting", + "before", + "tight before", + "begin: testMethod(" + + "android.platform.test.microbenchmark.MicrobenchmarkTest" + + "$LoggingTestWithRules)", + "test", + "end", + "tight after", + "after", + "hardcoded test rule finished", + "hardcoded test rule starting", + "before", + "tight before", + "begin: testMethod(" + + "android.platform.test.microbenchmark.MicrobenchmarkTest" + + "$LoggingTestWithRules)", + "test", + "end", + "tight after", + "after", + "hardcoded test rule finished", + "logging rule 1 finished", + "hardcoded class rule finished", + "logging rule 2 finished") + .inOrder(); + } + /** * An extensions of the {@link Microbenchmark} runner that logs the start and end of collecting * traces. It also passes the operation log to the provided test {@code Class}, if it is a @@ -503,10 +615,64 @@ public final class MicrobenchmarkTest { } } + public static class LoggingTestWithRules extends LoggingTest { + @ClassRule + public static TestRule hardCodedClassRule = + new TestWatcher() { + @Override + public void starting(Description description) { + sLogs.add("hardcoded class rule starting"); + } + + @Override + public void finished(Description description) { + sLogs.add("hardcoded class rule finished"); + } + }; + + @Rule + public TestRule hardCodedRule = + new TestWatcher() { + @Override + public void starting(Description description) { + sLogs.add("hardcoded test rule starting"); + } + + @Override + public void finished(Description description) { + sLogs.add("hardcoded test rule finished"); + } + }; + } + public static class LoggingFailedTest extends LoggingTest { @Test public void testMethod() { throw new RuntimeException("I failed."); } } + + public static class LoggingRule1 extends TestWatcher { + @Override + public void starting(Description description) { + sLogs.add("logging rule 1 starting"); + } + + @Override + public void finished(Description description) { + sLogs.add("logging rule 1 finished"); + } + } + + public static class LoggingRule2 extends TestWatcher { + @Override + public void starting(Description description) { + sLogs.add("logging rule 2 starting"); + } + + @Override + public void finished(Description description) { + sLogs.add("logging rule 2 finished"); + } + } } 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/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/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 |