upload android base code part6

This commit is contained in:
August 2018-08-08 17:48:24 +08:00
parent 421e214c7d
commit 4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions

View file

@ -0,0 +1,30 @@
#
# Copyright (C) 2016 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.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sysui-helper
LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator \
android-support-test \
activity-helper \
commands-helper \
device-helper \
legacy-android-test \
app-helpers-common \
LOCAL_SRC_FILES := $(call all-java-files-under, src)
include $(BUILD_STATIC_JAVA_LIBRARY)

View file

@ -0,0 +1,66 @@
/*
* Copyright (C) 2016 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.system.helpers;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.Until;
import junit.framework.Assert;
/**
* Implement common helper methods for Hotseat.
*/
public class HotseatHelper {
private static final int TIMEOUT = 3000;
private UiDevice mDevice = null;
private PackageManager mPkgManger = null;
private Context mContext = null;
public static HotseatHelper sInstance = null;
private HotseatHelper() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mContext = InstrumentationRegistry.getTargetContext();
}
public static HotseatHelper getInstance() {
if (sInstance == null) {
sInstance = new HotseatHelper();
}
return sInstance;
}
/**
* Launch app from hotseat
* @param textAppName
* @param appPackage
*/
public void launchAppFromHotseat(String textAppName, String appPackage) {
mDevice.pressHome();
UiObject2 appOnHotseat = mDevice.findObject(By.clazz("android.widget.TextView")
.desc(textAppName));
Assert.assertNotNull(textAppName + " app couldn't be found on hotseat", appOnHotseat);
appOnHotseat.click();
UiObject2 appLoaded = mDevice.wait(Until.findObject(By.pkg(appPackage)), TIMEOUT * 2);
Assert.assertNotNull(textAppName + "app did not load on tapping from hotseat", appLoaded);
}
}

View file

@ -0,0 +1,446 @@
/*
* Copyright (C) 2016 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.system.helpers;
import android.app.Instrumentation;
import android.app.KeyguardManager;
import android.content.Context;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.system.helpers.ActivityHelper;
import android.system.helpers.DeviceHelper;
import android.graphics.Point;
import android.graphics.Rect;
import junit.framework.Assert;
import java.io.IOException;
/**
* Implement common helper methods for Lockscreen.
*/
public class LockscreenHelper {
private static final String LOG_TAG = LockscreenHelper.class.getSimpleName();
public static final int SHORT_TIMEOUT = 200;
public static final int LONG_TIMEOUT = 2000;
public static final String EDIT_TEXT_CLASS_NAME = "android.widget.EditText";
public static final String CAMERA2_PACKAGE = "com.android.camera2";
public static final String CAMERA_PACKAGE = "com.google.android.GoogleCamera";
public static final String MODE_PIN = "PIN";
public static final String MODE_PASSWORD = "Password";
public static final String MODE_PATTERN = "Pattern";
private static final int SWIPE_MARGIN = 5;
private static final int SWIPE_MARGIN_BOTTOM = 100;
private static final int DEFAULT_FLING_STEPS = 5;
private static final int DEFAULT_SCROLL_STEPS = 15;
private static final String PIN_ENTRY = "com.android.systemui:id/pinEntry";
private static final String SET_PIN_COMMAND = "locksettings set-pin %s";
private static final String SET_PASSWORD_COMMAND = "locksettings set-password %s";
private static final String SET_PATTERN_COMMAND = "locksettings set-pattern %s";
private static final String CLEAR_COMMAND = "locksettings clear --old %s";
private static final String HOTSEAT = "hotseat";
private static LockscreenHelper sInstance = null;
private Context mContext = null;
private UiDevice mDevice = null;
private final ActivityHelper mActivityHelper;
private final CommandsHelper mCommandsHelper;
private final DeviceHelper mDeviceHelper;
private boolean mIsRyuDevice = false;
public LockscreenHelper() {
mContext = InstrumentationRegistry.getTargetContext();
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mActivityHelper = ActivityHelper.getInstance();
mCommandsHelper = CommandsHelper.getInstance(InstrumentationRegistry.getInstrumentation());
mDeviceHelper = DeviceHelper.getInstance();
mIsRyuDevice = mDeviceHelper.isRyuDevice();
}
public static LockscreenHelper getInstance() {
if (sInstance == null) {
sInstance = new LockscreenHelper();
}
return sInstance;
}
public String getLauncherPackage() {
return mDevice.getLauncherPackageName();
}
/**
* Launch Camera on LockScreen
* @return true/false
*/
public boolean launchCameraOnLockScreen() {
String CameraPackage = mIsRyuDevice ? CAMERA2_PACKAGE : CAMERA_PACKAGE;
int w = mDevice.getDisplayWidth();
int h = mDevice.getDisplayHeight();
// Load camera on LockScreen and take a photo
mDevice.drag((w - 25), (h - 25), (int) (w * 0.5), (int) (w * 0.5), 40);
mDevice.waitForIdle();
return mDevice.wait(Until.hasObject(
By.res(CameraPackage, "activity_root_view")),
LONG_TIMEOUT * 2);
}
/**
* Sets the screen lock pin or password
* @param pwd text of Password or Pin for lockscreen
* @param mode indicate if its password or PIN
* @throws InterruptedException
*/
public void setScreenLock(String pwd, String mode, boolean mIsNexusDevice)
throws InterruptedException {
enterScreenLockOnce(pwd, mode, mIsNexusDevice);
Thread.sleep(LONG_TIMEOUT);
// Re-enter password on confirmation screen
UiObject2 pinField = mDevice.wait(Until.findObject(By.clazz(EDIT_TEXT_CLASS_NAME)),
LONG_TIMEOUT);
pinField.setText(pwd);
Thread.sleep(LONG_TIMEOUT);
mDevice.wait(Until.findObject(By.text("OK")), LONG_TIMEOUT).click();
}
/**
* Enters the screen lock once on the setting screen
* @param pwd text of Password or Pin for lockscreen
* @param mode indicate if its password or PIN
* @throws InterruptedException
*/
public void enterScreenLockOnce(String pwd, String mode, boolean mIsNexusDevice) {
mDevice.wait(Until.findObject(By.text(mode)), LONG_TIMEOUT * 2).click();
// set up Secure start-up page
if (!mIsNexusDevice) {
mDevice.wait(Until.findObject(By.text("No thanks")), LONG_TIMEOUT).click();
}
UiObject2 pinField = mDevice.wait(Until.findObject(By.clazz(EDIT_TEXT_CLASS_NAME)),
LONG_TIMEOUT);
pinField.setText(pwd);
// enter and verify password
mDevice.pressEnter();
}
/*
* Enters non matching passcodes on both setting screens.
* Note: this will fail if you enter matching passcodes.
*/
public void enterNonMatchingPasscodes(String firstPasscode, String secondPasscode,
String mode, boolean mIsNexusDevice) throws Exception {
enterScreenLockOnce(firstPasscode, mode, mIsNexusDevice);
Thread.sleep(LONG_TIMEOUT);
UiObject2 pinField = mDevice.wait(Until.findObject(By.clazz(EDIT_TEXT_CLASS_NAME)),
LONG_TIMEOUT);
pinField.setText(secondPasscode);
mDevice.pressEnter();
Thread.sleep(LONG_TIMEOUT);
// Verify that error is thrown.
UiObject2 dontMatchMessage = mDevice.wait(Until.findObject
(By.textContains("dont match")), LONG_TIMEOUT);
Assert.assertNotNull("Error message for passcode confirmation not visible",
dontMatchMessage);
}
/**
* check if Emergency Call page exists
* @throws InterruptedException
*/
public void checkEmergencyCallOnLockScreen() throws InterruptedException {
mDevice.pressMenu();
mDevice.wait(Until.findObject(By.text("EMERGENCY")), LONG_TIMEOUT).click();
Thread.sleep(LONG_TIMEOUT);
UiObject2 dialButton = mDevice.wait(Until.findObject(By.desc("dial")),
LONG_TIMEOUT);
Assert.assertNotNull("Can't reach emergency call page", dialButton);
mDevice.pressBack();
Thread.sleep(LONG_TIMEOUT);
}
/**
* remove Screen Lock
* @throws InterruptedException
*/
public void removeScreenLock(String pwd)
throws InterruptedException {
navigateToScreenLock();
UiObject2 pinField = mDevice.wait(Until.findObject(By.clazz(EDIT_TEXT_CLASS_NAME)),
LONG_TIMEOUT);
pinField.setText(pwd);
mDevice.pressEnter();
mDevice.wait(Until.findObject(By.text("Swipe")), LONG_TIMEOUT).click();
mDevice.waitForIdle();
mDevice.wait(Until.findObject(By.text("YES, REMOVE")), LONG_TIMEOUT).click();
}
/**
* Enter a screen password or PIN.
* Pattern not supported, please use
* unlockDeviceWithPattern(String) below.
* Method assumes the device is on lockscreen.
* with keyguard exposed. It will wake
* up the device, swipe up to reveal the keyguard,
* and enter the password or pin and hit enter.
* @throws InterruptedException, IOException
*/
public void unlockScreen(String pwd)
throws InterruptedException, IOException {
// Press menu key (82 is the code for the menu key)
String command = String.format(" %s %s %s", "input", "keyevent", "82");
mDevice.executeShellCommand(command);
Thread.sleep(SHORT_TIMEOUT);
Thread.sleep(SHORT_TIMEOUT);
// enter password to unlock screen
command = String.format(" %s %s %s", "input", "text", pwd);
mDevice.executeShellCommand(command);
mDevice.waitForIdle();
Thread.sleep(SHORT_TIMEOUT);
mDevice.pressEnter();
}
/**
* navigate to screen lock setting page
* @throws InterruptedException
*/
public void navigateToScreenLock()
throws InterruptedException {
mActivityHelper.launchIntent(Settings.ACTION_SECURITY_SETTINGS);
mDevice.wait(Until.findObject(By.text("Screen lock")), LONG_TIMEOUT).click();
}
/**
* check if Lock Screen is enabled
*/
public boolean isLockScreenEnabled() {
KeyguardManager km = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
return km.isKeyguardSecure();
}
/**
* Sets a screen lock via shell.
*/
public void setScreenLockViaShell(String passcode, String mode) throws Exception {
switch (mode) {
case MODE_PIN:
mCommandsHelper.executeShellCommand(String.format(SET_PIN_COMMAND, passcode));
break;
case MODE_PASSWORD:
mCommandsHelper.executeShellCommand(String.format(SET_PASSWORD_COMMAND, passcode));
break;
case MODE_PATTERN:
mCommandsHelper.executeShellCommand(String.format(SET_PATTERN_COMMAND, passcode));
break;
default:
throw new IllegalArgumentException("Unsupported mode: " + mode);
}
}
/**
* Removes the screen lock via shell.
*/
public void removeScreenLockViaShell(String pwd) throws Exception {
mCommandsHelper.executeShellCommand(String.format(CLEAR_COMMAND, pwd));
}
/**
* swipe up to unlock the screen
*/
public void unlockScreenSwipeUp() throws Exception {
mDevice.wakeUp();
mDevice.waitForIdle();
mDevice.swipe(mDevice.getDisplayWidth() / 2,
mDevice.getDisplayHeight() - SWIPE_MARGIN,
mDevice.getDisplayWidth() / 2,
SWIPE_MARGIN,
DEFAULT_SCROLL_STEPS);
mDevice.waitForIdle();
}
/*
* Takes in the correct code (pin or password), the attempted
* code (pin or password), the mode for the code (whether pin or password)
* and whether or not they are expected to match.
* Asserts that the device has been successfully unlocked (or not).
*/
public void setAndEnterLockscreenCode(String actualCode, String attemptedCode,
String mode, boolean shouldMatch) throws Exception {
setScreenLockViaShell(actualCode, mode);
Thread.sleep(LONG_TIMEOUT);
enterLockscreenCode(actualCode, attemptedCode, mode, shouldMatch);
}
public void enterLockscreenCode(String actualCode, String attemptedCode,
String mode, boolean shouldMatch) throws Exception {
mDevice.pressHome();
mDeviceHelper.sleepAndWakeUpDevice();
unlockScreen(attemptedCode);
checkForHotseatOnHome(shouldMatch);
removeScreenLockViaShell(actualCode);
Thread.sleep(LONG_TIMEOUT);
mDevice.pressHome();
}
/*
* Takes in the correct pattern, the attempted pattern,
* and whether or not they are expected to match.
* Asserts that the device has been successfully unlocked (or not).
*/
public void setAndEnterLockscreenPattern(String actualPattern,
String attemptedPattern, boolean shouldMatch) throws Exception {
setScreenLockViaShell
(actualPattern, LockscreenHelper.MODE_PATTERN);
unlockDeviceWithPattern(attemptedPattern);
checkForHotseatOnHome(shouldMatch);
removeScreenLockViaShell(actualPattern);
Thread.sleep(LONG_TIMEOUT);
mDevice.pressHome();
}
public void checkForHotseatOnHome(boolean deviceUnlocked) throws Exception {
mDevice.pressHome();
Thread.sleep(LONG_TIMEOUT);
UiObject2 hotseat = mDevice.findObject(By.res(getLauncherPackage(), HOTSEAT));
if (deviceUnlocked) {
Assert.assertNotNull("Device not unlocked correctly", hotseat);
}
else {
Assert.assertNull("Device should not be unlocked", hotseat);
}
}
/*
* The pattern below is always invalid as you need at least
* four dots for a valid lock. That action of changing
* directions while dragging is unsupported by
* uiautomator.
*/
public void enterInvalidPattern() throws Exception {
// Get coordinates for left top dot
UiObject2 lockPattern = mDevice.wait(Until.findObject
(By.res("com.android.systemui:id/lockPatternView")),
LONG_TIMEOUT);
// Get coordinates for left side dots
int xCoordinate =(int) (lockPattern.getVisibleBounds().left +
lockPattern.getVisibleBounds().left*0.16);
int y1Coordinate = (int) (lockPattern.getVisibleBounds().top +
lockPattern.getVisibleBounds().top*0.16);
int y2Coordinate = (int) (lockPattern.getVisibleBounds().bottom -
lockPattern.getVisibleBounds().bottom*0.16);
// Drag coordinates from one point to another
mDevice.swipe(xCoordinate, y1Coordinate, xCoordinate, y2Coordinate, 2);
}
/* Valid pattern unlock attempt
* Takes in a contiguous string as input
* 1 2 3
* 4 5 6
* 7 8 9
* with each number representing a dot. Eg: "1236"
*/
public void unlockDeviceWithPattern(String unlockPattern) throws Exception {
mDeviceHelper.sleepAndWakeUpDevice();
unlockScreenSwipeUp();
Point[] coordinateArray = new Point[unlockPattern.length()];
for (int i=0; i < unlockPattern.length(); i++) {
coordinateArray[i] = calculateCoordinatesForPatternDot(unlockPattern.charAt(i),
"com.android.systemui:id/lockPatternView");
}
// Note: 50 controls the speed of the pattern drawing.
mDevice.swipe(coordinateArray, 50);
Thread.sleep(SHORT_TIMEOUT);
}
/* Pattern lock setting attempt
* Takes in a contiguous string as input
* 1 2 3
* 4 5 6
* 7 8 9
* with each number representing a dot. Eg: "1236"
*/
public void enterPatternLockOnceForSettingLock(String unlockPattern)
throws InterruptedException {
Point[] coordinateArray = new Point[unlockPattern.length()];
for (int i=0; i < unlockPattern.length(); i++) {
coordinateArray[i] = calculateCoordinatesForPatternDot(unlockPattern.charAt(i),
"com.android.settings:id/lockPattern");
}
// Note: 50 controls the speed of the pattern drawing.
mDevice.swipe(coordinateArray, 50);
Thread.sleep(SHORT_TIMEOUT);
}
/* Pattern lock setting - this enters and reconfirms pattern to set
* using the UI.
* Takes in a contiguous string as input
* 1 2 3
* 4 5 6
* 7 8 9
* with each number representing a dot. Eg: "1236"
*/
public void setPatternLockSettingLock(String unlockPattern) throws Exception {
// Enter the same pattern twice, once on the initial set
// screen and once on the confirmation screen.
for (int i=0; i<2; i++) {
enterPatternLockOnceForSettingLock(unlockPattern);
mDevice.pressEnter();
}
mDevice.wait(Until.findObject(By.text("DONE")), LONG_TIMEOUT).click();
}
/* Returns screen coordinates for each pattern dot
* for the current device
* Represented as follows by chars
* 1 2 3
* 4 5 6
* 7 8 9
* this is consistent with the set-pattern command
* to avoid confusion.
*/
private Point calculateCoordinatesForPatternDot(char dotNumber, String lockPatternResId) {
UiObject2 lockPattern = mDevice.wait(Until.findObject
(By.res(lockPatternResId)), LONG_TIMEOUT);
// Calculate x coordinate
int xCoordinate = 0;
int deltaX = (int) ((lockPattern.getVisibleBounds().right -
lockPattern.getVisibleBounds().left)*0.16);
if (dotNumber == '1' || dotNumber == '4' || dotNumber == '7') {
xCoordinate = lockPattern.getVisibleBounds().left + deltaX;
}
else if (dotNumber == '2' || dotNumber == '5' || dotNumber == '8') {
xCoordinate = lockPattern.getVisibleCenter().x;
}
else if (dotNumber == '3' || dotNumber == '6' || dotNumber == '9') {
xCoordinate = lockPattern.getVisibleBounds().right - deltaX;
}
// Calculate y coordinate
int yCoordinate = 0;
int deltaY = (int) ((lockPattern.getVisibleBounds().bottom -
lockPattern.getVisibleBounds().top)*0.16);
if (dotNumber == '1' || dotNumber == '2' || dotNumber == '3') {
yCoordinate = lockPattern.getVisibleBounds().top + deltaY;
}
else if (dotNumber == '4' || dotNumber == '5' || dotNumber == '6') {
yCoordinate = lockPattern.getVisibleCenter().y;
}
else if (dotNumber == '7' || dotNumber == '8' || dotNumber == '9') {
yCoordinate = lockPattern.getVisibleBounds().bottom - deltaY;
}
return new Point(xCoordinate, yCoordinate);
}
}

View file

@ -0,0 +1,171 @@
/*
* Copyright (C) 2016 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.system.helpers;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.Direction;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* Implement common helper methods for Notification.
*/
public class NotificationHelper {
private static final String LOG_TAG = NotificationHelper.class.getSimpleName();
public static final int SHORT_TIMEOUT = 200;
public static final int LONG_TIMEOUT = 2000;
private static NotificationHelper sInstance = null;
private Context mContext = null;
private UiDevice mDevice = null;
public NotificationHelper() {
mContext = InstrumentationRegistry.getTargetContext();
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
}
public static NotificationHelper getInstance() {
if (sInstance == null) {
sInstance = new NotificationHelper();
}
return sInstance;
}
/**
* check if notification exists
* @param id notification id
* @param mNotificationManager NotificationManager
* @return true/false
* @throws Exception
*/
public boolean checkNotificationExistence(int id, NotificationManager mNotificationManager)
throws Exception {
boolean isFound = false;
for (int tries = 3; tries-- > 0;) {
isFound = false;
StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
for (StatusBarNotification sbn : sbns) {
if (sbn.getId() == id) {
isFound = true;
break;
}
}
if (isFound) {
break;
}
Thread.sleep(SHORT_TIMEOUT);
}
Log.i(LOG_TAG, "checkNotificationExistence..." + isFound);
return isFound;
}
/**
* send out a group of notifications
* @param lists notification list for a group of notifications which includes two child
* notifications and one summary notification
* @param groupKey the group key of group notification
* @param mNotificationManager NotificationManager
* @throws Exception
*/
public void sendBundlingNotifications(List<Integer> lists, String groupKey,
NotificationManager mNotificationManager) throws Exception {
Notification childNotification = new Notification.Builder(mContext)
.setContentTitle(lists.get(1).toString())
.setSmallIcon(android.R.drawable.stat_notify_chat)
.setContentText("test1")
.setWhen(System.currentTimeMillis())
.setGroup(groupKey)
.build();
mNotificationManager.notify(lists.get(1),
childNotification);
childNotification = new Notification.Builder(mContext)
.setContentTitle(lists.get(2).toString())
.setContentText("test2")
.setSmallIcon(android.R.drawable.stat_notify_chat)
.setWhen(System.currentTimeMillis())
.setGroup(groupKey)
.build();
mNotificationManager.notify(lists.get(2),
childNotification);
Notification notification = new Notification.Builder(mContext)
.setContentTitle(lists.get(0).toString())
.setSubText(groupKey)
.setSmallIcon(android.R.drawable.stat_notify_chat)
.setGroup(groupKey)
.setGroupSummary(true)
.build();
mNotificationManager.notify(lists.get(0),
notification);
}
/**
* send out a notification with inline reply
* @param notificationId An identifier for this notification
* @param title notification title
* @param inLineReply inline reply text
* @param mNotificationManager NotificationManager
*/
public void sendNotificationsWithInLineReply(int notificationId, String title,
String inLineReply,PendingIntent pendingIntent, NotificationManager mNotificationManager) {
Notification.Action action = new Notification.Action.Builder(
android.R.drawable.stat_notify_chat, "Reply",
pendingIntent).addRemoteInput(new RemoteInput.Builder(inLineReply)
.setLabel("Quick reply").build())
.build();
Notification.Builder n = new Notification.Builder(mContext)
.setContentTitle(Integer.toString(notificationId))
.setContentText(title)
.setWhen(System.currentTimeMillis())
.setSmallIcon(android.R.drawable.stat_notify_chat)
.addAction(action)
.setDefaults(Notification.DEFAULT_VIBRATE);
mNotificationManager.notify(notificationId, n.build());
}
/**
* dismiss notification
* @param mNotificationManager NotificationManager
*/
public void dismissNotifications(NotificationManager mNotificationManager){
mNotificationManager.cancelAll();
}
/**
* open notification shade
*/
public void openNotification(){
mDevice.openNotification();
}
}

View file

@ -0,0 +1,231 @@
/*
* Copyright (C) 2016 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.system.helpers;
import android.app.Instrumentation;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.Until;
import android.system.helpers.ActivityHelper;
import android.util.Log;
import org.junit.Assert;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Implement common helper methods for Overview.
*/
public class OverviewHelper {
private static final String TAG = OverviewHelper.class.getSimpleName();
private static final int TIMEOUT = 3000;
private static final String RECENTS = "com.android.systemui:id/recents_view";
private UiDevice mDevice = null;
private Instrumentation mInstrumentation = null;
private ActivityHelper mActHelper = null;
private final CommandsHelper mCommandsHelper;
public static OverviewHelper sInstance = null;
public OverviewHelper() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mActHelper = ActivityHelper.getInstance();
mCommandsHelper = CommandsHelper.getInstance(mInstrumentation);
}
public static OverviewHelper getInstance() {
if (sInstance == null) {
sInstance = new OverviewHelper();
}
return sInstance;
}
/**
* Navigates to the recents screen
* @returns recents object
* @throws UiObjectNotFoundException
*/
public UiObject2 navigateToRecents() throws Exception {
mDevice.pressRecentApps();
mDevice.waitForIdle();
return mDevice.wait(Until.findObject(By.res(RECENTS)), TIMEOUT);
}
/**
* Populates recents by launching six apps
* @throws InterruptedException
*/
public void populateRecents() throws InterruptedException {
// We launch six apps, since five is the maximum number
// of apps under Recents
String[] appPackages = {"com.google.android.gm",
"com.google.android.deskclock", "com.android.settings",
"com.google.android.youtube", "com.google.android.contacts",
"com.google.android.apps.maps"};
for (String appPackage : appPackages) {
mActHelper.launchPackage(appPackage);
}
}
public ArrayList<String> populateManyRecentApps() throws IOException {
PackageManager pm = mInstrumentation.getContext().getPackageManager();
List<PackageInfo> packages = pm.getInstalledPackages(0);
ArrayList<String> launchedPackages = new ArrayList<>();
for (PackageInfo pkg : packages) {
if (pkg.packageName.equals(mInstrumentation.getTargetContext().getPackageName())) {
continue;
}
Intent intent = pm.getLaunchIntentForPackage(pkg.packageName);
if (intent == null) {
continue;
}
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
mInstrumentation.getTargetContext().startActivity(intent);
} catch (SecurityException e) {
Log.i(TAG, "Failed to start package " + pkg.packageName + ", exception: " + e);
}
// Don't overload the system
SystemClock.sleep(500);
launchedPackages.add(pkg.packageName);
}
// Give the apps some time to finish starting. Some apps start another activity while
// starting, and we don't want to happen when we are testing stuff.
SystemClock.sleep(3000);
// Close any crash dialogs
while (mDevice.hasObject(By.textContains("has stopped"))) {
UiObject2 crashDialog = mDevice.findObject(By.text("Close"));
if (crashDialog != null) {
crashDialog.clickAndWait(Until.newWindow(), 2000);
}
}
return launchedPackages;
}
public void forceStopPackages(ArrayList<String> packages) {
for (String pkg : packages) {
mCommandsHelper.executeShellCommand("am force-stop " + pkg);
}
}
/**
* Scrolls through given recents object to the top
* @param recents Recents object
*/
public void scrollToTopOfRecents(UiObject2 recents) {
Rect r = recents.getVisibleBounds();
// decide the top & bottom edges for scroll gesture
int top = r.top + r.height() / 4; // top edge = top + 25% height
int bottom = r.bottom - 200; // bottom edge = bottom & shift up 200px
mDevice.swipe(r.width() / 2, top, r.width() / 2, bottom, 5);
mDevice.waitForIdle();
}
/**
* Docks an app to the top half of the multiwindow screen
* @param appPackageName name of app package
* @param appName Name of app to verify on screen
* @throws UiObjectNotFoundException, InterruptedException
*/
public void dockAppToTopMultiwindowSlot(String appPackageName, String appName)
throws Exception {
mDevice.pressRecentApps();
mDevice.waitForIdle();
UiObject2 recentsView = mDevice.wait(Until.findObject
(By.res("com.android.systemui:id/recents_view")),TIMEOUT);
// Check if recents isn't already empty, if not, clear it.
if (!mDevice.wait(Until.hasObject(By.text("No recent items")),TIMEOUT)) {
scrollToTopOfRecents(recentsView);
// click clear all
UiObject2 clearAll = mDevice.wait(Until.findObject(By.text("CLEAR ALL")),TIMEOUT);
if (!clearAll.equals(null)) {
clearAll.click();
}
Thread.sleep(TIMEOUT);
}
// Open app
mActHelper.launchPackage(appPackageName);
// Go to overview
mDevice.pressRecentApps();
mDevice.waitForIdle();
// Long press on app
UiObject2 appObject = mDevice.wait(Until.findObject
(By.desc(appName)),TIMEOUT);
int yCoordinate = mDevice.getDisplayHeight() / 12;
int xCoordinate = mDevice.getDisplayWidth() / 2;
// Drag and drop the app object to the multiwindow area
appObject.drag(new Point(xCoordinate, yCoordinate), 1000);
// Adding a sleep to allow the drag and drop animation to finish.
Thread.sleep(TIMEOUT);
mDevice.click(mDevice.getDisplayHeight() / 4, mDevice.getDisplayWidth() / 2);
Assert.assertTrue("App not correctly docked to top multiwindow slot",
mDevice.wait(Until.hasObject(By.pkg(appPackageName)
.res("android:id/content")), TIMEOUT));
}
/**
* Docks two apps, one to the each half of the multiwindow screen
* @param topAppPackageName name of app package for top half
* @param topAppName Name of top app to verify on screen
* @param bottomAppPackageName name of app package for bottom half
* @throws UiObjectNotFoundException, InterruptedException
*/
public void dockAppsToBothMultiwindowAreas(String topAppPackageName,
String topAppName, String bottomAppPackageName) throws Exception {
dockAppToTopMultiwindowSlot(topAppPackageName, topAppName);
mDevice.pressHome();
mDevice.waitForIdle();
// After docking the top app, simply launching another app
// will launch it in the bottom half in docked mode. This
// results in two apps being docked to multiwindow.
mActHelper.launchPackage(bottomAppPackageName);
}
/**
* Undocks apps from multiwindow. Only the package for the upper app is needed.
* @param topAppPackageName name of app package for top half
* @throws UiObjectNotFoundException, InterruptedException
*/
public void undockAppFromMultiwindow(String topAppPackageName) throws Exception {
mDevice.click(mDevice.getDisplayHeight() / 4, mDevice.getDisplayWidth() / 2);
UiObject2 appArea = mDevice.wait(Until.findObject(By.pkg(topAppPackageName)
.res("android:id/content")), TIMEOUT);
Rect appBounds = appArea.getVisibleBounds();
int xCoordinate = mDevice.getDisplayWidth() / 2;
mDevice.drag(xCoordinate, appBounds.bottom, xCoordinate,
mDevice.getDisplayHeight() - 120, 4);
// Adding a sleep to allow the drag and drop animation to finish.
Thread.sleep(TIMEOUT);
}
}

View file

@ -0,0 +1,150 @@
/*
* Copyright (C) 2016 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.system.helpers;
import android.app.Instrumentation;
import android.content.ContentResolver;
import android.graphics.Point;
import android.provider.Settings;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import org.junit.Assert;
/**
* Implement common helper methods for Quick settings.
*/
public class QuickSettingsHelper {
private UiDevice mDevice = null;
private ContentResolver mResolver;
private Instrumentation mInstrumentation;
private static final int LONG_TIMEOUT = 2000;
private static final int SHORT_TIMEOUT = 500;
public QuickSettingsHelper(UiDevice device, Instrumentation inst, ContentResolver resolver) {
this.mDevice = device;
mInstrumentation = inst;
mResolver = resolver;
}
public enum QuickSettingDefaultTiles {
WIFI("Wi-Fi"), SIM("Mobile data"), DND("Do not disturb"), FLASHLIGHT("Flashlight"), SCREEN(
"Auto-rotate screen"), BLUETOOTH("Bluetooth"), AIRPLANE("Airplane mode"),
BRIGHTNESS("Display brightness");
private final String name;
private QuickSettingDefaultTiles(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
};
public enum QuickSettingEditMenuTiles {
LOCATION("Location"), HOTSPOT("Hotspot"), INVERTCOLORS("Invert colors"),
DATASAVER("Data Saver"), CAST("Cast"), NEARBY("Nearby");
private final String name;
private QuickSettingEditMenuTiles(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
};
public void addQuickSettingTileFromEditMenu(String quickSettingTile,
String quickSettingTileToReplace, String quickSettingTileToCheckForInCSV)
throws Exception {
// Draw down quick settings
launchQuickSetting();
// Press Edit button
UiObject2 quickSettingEdit = mDevice.wait(Until.findObject
(By.descContains("Edit")), LONG_TIMEOUT);
quickSettingEdit.click();
// Scroll down to bottom to see all QS options on Edit
swipeDown();
// Drag and drop QS item onto existing QS tile to replace it
// This is because we need specific coordinates on which to
// drop the quick setting tile.
UiObject2 quickSettingTileObject = mDevice.wait(Until.findObject
(By.descContains(quickSettingTile)), LONG_TIMEOUT);
Point destination = mDevice.wait(Until.findObject
(By.descContains(quickSettingTileToReplace)), LONG_TIMEOUT)
.getVisibleCenter();
Assert.assertNotNull(quickSettingTile + " in Edit menu can't be found",
quickSettingTileObject);
Assert.assertNotNull(quickSettingTileToReplace + " in QS menu can't be found",
destination);
// Long press the icon, then drag it to the destination slowly.
// Without the long press, it ends up scrolling down quick settings.
quickSettingTileObject.click(2000);
quickSettingTileObject.drag(destination, 1000);
// Hit the back button in the QS menu to go back to quick settings.
mDevice.wait(Until.findObject(By.descContains("Navigate up")), LONG_TIMEOUT);
// Retrieve the quick settings CSV string and verify that the newly
// added item is present.
String quickSettingsList = Settings.Secure.getString
(mInstrumentation.getContext().getContentResolver(),
"sysui_qs_tiles");
Assert.assertTrue(quickSettingTile + " not present in qs tiles after addition.",
quickSettingsList.contains(quickSettingTileToCheckForInCSV));
}
public void setQuickSettingsDefaultTiles() throws Exception {
modifyListOfQuickSettingsTiles
("wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location");
}
public void modifyListOfQuickSettingsTiles(String commaSeparatedList) throws Exception {
Settings.Secure.putString(mInstrumentation.getContext().getContentResolver(),
"sysui_qs_tiles", commaSeparatedList);
Thread.sleep(LONG_TIMEOUT);
}
public void launchQuickSetting() throws Exception {
mDevice.pressHome();
swipeDown();
Thread.sleep(LONG_TIMEOUT);
swipeDown();
}
public void swipeUp() throws Exception {
mDevice.swipe(mDevice.getDisplayWidth() / 2, mDevice.getDisplayHeight(),
mDevice.getDisplayWidth() / 2, 0, 30);
Thread.sleep(SHORT_TIMEOUT);
}
public void swipeDown() throws Exception {
mDevice.swipe(mDevice.getDisplayWidth() / 2, 0, mDevice.getDisplayWidth() / 2,
mDevice.getDisplayHeight() / 2 + 50, 20);
Thread.sleep(SHORT_TIMEOUT);
}
public void swipeLeft() {
mDevice.swipe(mDevice.getDisplayWidth() / 2, mDevice.getDisplayHeight() / 2, 0,
mDevice.getDisplayHeight() / 2, 5);
}
}