blob: e8caff2cff0392624fde52be4ad100b735eb14a9 [file] [log] [blame]
/*
* Copyright (C) 2020 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.suspendapps.cts;
import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
import static android.suspendapps.cts.Constants.TEST_APP_PACKAGE_NAME;
import static android.suspendapps.cts.SuspendTestUtils.assertSameExtras;
import static android.suspendapps.cts.SuspendTestUtils.createExtras;
import static android.suspendapps.cts.SuspendTestUtils.startTestAppActivity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.content.Intent;
import android.content.pm.SuspendDialogInfo;
import android.os.Bundle;
import android.platform.test.annotations.SystemUserOnly;
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 androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.SystemUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
@RunWith(AndroidJUnit4.class)
public class DialogTests {
private static final String TEST_APP_LABEL = "Suspend Test App";
private static final long UI_TIMEOUT_MS = 60_000;
/** Used to poll for the intents sent by the system to this package */
static final SynchronousQueue<Intent> sIncomingIntent = new SynchronousQueue<>();
private Context mContext;
private TestAppInterface mTestAppInterface;
private UiDevice mUiDevice;
@Before
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mTestAppInterface = new TestAppInterface(mContext);
turnScreenOn();
}
private void turnScreenOn() throws Exception {
if (!mUiDevice.isScreenOn()) {
mUiDevice.wakeUp();
}
SystemUtil.runShellCommandForNoOutput("wm dismiss-keyguard");
}
@Test
public void testInterceptorActivity_unsuspend() throws Exception {
final SuspendDialogInfo dialogInfo = new SuspendDialogInfo.Builder()
.setIcon(R.drawable.ic_settings)
.setTitle(R.string.dialog_title)
.setMessage(R.string.dialog_message)
.setNeutralButtonText(R.string.unsuspend_button_text)
.setNeutralButtonAction(BUTTON_ACTION_UNSUSPEND)
.build();
SuspendTestUtils.suspend(null, null, dialogInfo);
// Ensure test app's activity is stopped before proceeding.
assertTrue(mTestAppInterface.awaitTestActivityStop());
final Bundle extrasForStart = new Bundle(createExtras("unsuspend", 90, "sval", 0.9));
startTestAppActivity(extrasForStart);
// Test activity should not start.
assertNull("Test activity started while suspended",
mTestAppInterface.awaitTestActivityStart(5_000));
final String expectedTitle = mContext.getResources().getString(R.string.dialog_title);
final String expectedButtonText = mContext.getResources().getString(
R.string.unsuspend_button_text);
assertNotNull("Given dialog title \"" + expectedTitle + "\" not shown",
mUiDevice.wait(Until.findObject(By.text(expectedTitle)), UI_TIMEOUT_MS));
// Sometimes, button texts can have styles that override case (e.g. b/134033532)
final Pattern buttonTextIgnoreCase = Pattern.compile(Pattern.quote(expectedButtonText),
Pattern.CASE_INSENSITIVE);
final UiObject2 unsuspendButton = mUiDevice.findObject(
By.clickable(true).text(buttonTextIgnoreCase));
assertNotNull("\"" + expectedButtonText + "\" button not shown", unsuspendButton);
// Tapping on the neutral button should:
// 1. Tell the suspending package that the test app was unsuspended
// 2. Launch the previously intercepted intent
// 3. Unsuspend the test app
unsuspendButton.click();
final Intent incomingIntent = sIncomingIntent.poll(30, TimeUnit.SECONDS);
assertNotNull(incomingIntent);
assertEquals(Intent.ACTION_PACKAGE_UNSUSPENDED_MANUALLY, incomingIntent.getAction());
assertEquals("Did not receive correct unsuspended package name", TEST_APP_PACKAGE_NAME,
incomingIntent.getStringExtra(Intent.EXTRA_PACKAGE_NAME));
final Intent activityIntent = mTestAppInterface.awaitTestActivityStart();
assertNotNull("Test activity did not start on neutral button tap", activityIntent);
assertSameExtras("Different extras passed to startActivity on unsuspend",
extrasForStart, activityIntent.getExtras());
assertFalse("Test package still suspended", mTestAppInterface.isTestAppSuspended());
}
@Test
public void testInterceptorActivity_moreDetails() throws Exception {
final SuspendDialogInfo dialogInfo = new SuspendDialogInfo.Builder()
.setIcon(R.drawable.ic_settings)
.setTitle(R.string.dialog_title)
.setMessage(R.string.dialog_message)
.setNeutralButtonText(R.string.more_details_button_text)
.build();
SuspendTestUtils.suspend(null, null, dialogInfo);
// Ensure test app's activity is stopped before proceeding.
assertTrue(mTestAppInterface.awaitTestActivityStop());
startTestAppActivity(null);
// Test activity should not start.
assertNull("Test activity started while suspended",
mTestAppInterface.awaitTestActivityStart(5_000));
// The dialog should have correct specifications
final String expectedTitle = mContext.getResources().getString(R.string.dialog_title);
final String expectedMessage = mContext.getResources().getString(R.string.dialog_message,
TEST_APP_LABEL);
final String expectedButtonText = mContext.getResources().getString(
R.string.more_details_button_text);
assertNotNull("Given dialog title: " + expectedTitle + " not shown",
mUiDevice.wait(Until.findObject(By.text(expectedTitle)), UI_TIMEOUT_MS));
assertNotNull("Given dialog message: " + expectedMessage + " not shown",
mUiDevice.findObject(By.text(expectedMessage)));
// Sometimes, button texts can have styles that override case (e.g. b/134033532)
final Pattern buttonTextIgnoreCase = Pattern.compile(Pattern.quote(expectedButtonText),
Pattern.CASE_INSENSITIVE);
final UiObject2 moreDetailsButton = mUiDevice.findObject(
By.clickable(true).text(buttonTextIgnoreCase));
assertNotNull(expectedButtonText + " button not shown", moreDetailsButton);
// Tapping on the neutral button should start the correct intent.
moreDetailsButton.click();
final Intent incomingIntent = sIncomingIntent.poll(30, TimeUnit.SECONDS);
assertNotNull(incomingIntent);
assertEquals(Intent.ACTION_SHOW_SUSPENDED_APP_DETAILS, incomingIntent.getAction());
assertEquals("Wrong package name sent with " + Intent.ACTION_SHOW_SUSPENDED_APP_DETAILS,
TEST_APP_PACKAGE_NAME, incomingIntent.getStringExtra(Intent.EXTRA_PACKAGE_NAME));
}
@Test
public void testInterceptorActivity_strings() throws Exception {
// The dialog should have correct specifications
final String expectedTitle = "Test Dialog Title";
final String expectedMessage = "This is a test message";
final String expectedButtonText = "Test button";
final SuspendDialogInfo dialogInfo = new SuspendDialogInfo.Builder()
.setIcon(R.drawable.ic_settings)
.setTitle(expectedTitle)
.setMessage(expectedMessage)
.setNeutralButtonText(expectedButtonText)
.build();
SuspendTestUtils.suspend(null, null, dialogInfo);
// Ensure test app's activity is stopped before proceeding.
assertTrue(mTestAppInterface.awaitTestActivityStop());
startTestAppActivity(null);
// Test activity should not start.
assertNull("Test activity started while suspended",
mTestAppInterface.awaitTestActivityStart(5_000));
assertNotNull("Given dialog title: " + expectedTitle + " not shown",
mUiDevice.wait(Until.findObject(By.text(expectedTitle)), UI_TIMEOUT_MS));
assertNotNull("Given dialog message: " + expectedMessage + " not shown",
mUiDevice.findObject(By.text(expectedMessage)));
// Sometimes, button texts can have styles that override case (e.g. b/134033532)
final Pattern buttonTextIgnoreCase = Pattern.compile(Pattern.quote(expectedButtonText),
Pattern.CASE_INSENSITIVE);
final UiObject2 moreDetailsButton = mUiDevice.findObject(
By.clickable(true).text(buttonTextIgnoreCase));
assertNotNull(expectedButtonText + " button not shown", moreDetailsButton);
}
@After
public void tearDown() {
if (mTestAppInterface != null) {
mTestAppInterface.disconnect();
}
mUiDevice.pressBack();
mUiDevice.pressHome();
}
}