Cts tests for new @ChangeId in TileService
Test: atest CtsSystemUiHostTestCases
Fixes: 172251878
Change-Id: I46f7319fa2517ed0c1d6e2b12e83e2edbee4a736
diff --git a/hostsidetests/systemui/Android.bp b/hostsidetests/systemui/Android.bp
index 6fd9c8c..a5918f4 100644
--- a/hostsidetests/systemui/Android.bp
+++ b/hostsidetests/systemui/Android.bp
@@ -30,6 +30,7 @@
static_libs: [
"cts-statsd-atom-host-test-utils",
"platformprotos",
+ "CompatChangeGatingTestBase",
],
// Tag this module as a cts test artifact
test_suites: [
diff --git a/hostsidetests/systemui/app/src/android/systemui/cts/TestActiveTileService.java b/hostsidetests/systemui/app/src/android/systemui/cts/TestActiveTileService.java
index f8fe6c0..02b403a 100644
--- a/hostsidetests/systemui/app/src/android/systemui/cts/TestActiveTileService.java
+++ b/hostsidetests/systemui/app/src/android/systemui/cts/TestActiveTileService.java
@@ -22,6 +22,9 @@
public class TestActiveTileService extends TestTileService {
+ private static final String EXTRA_BAD_PACKAGE = "android.systemui.cts.EXTRA_BAD_PACKAGE";
+ private static final String TAG = "TestActiveTileService";
+
@Override
public void onTileAdded() {
Log.i(TAG, TEST_PREFIX + "onTileAdded");
@@ -32,7 +35,18 @@
public void onReceive(Context context, Intent intent) {
Log.i(TestActiveTileService.class.getSimpleName(),
TEST_PREFIX + "requestListeningState");
- requestListeningState(context, new ComponentName(context, TestActiveTileService.class));
+ ComponentName componentName;
+ boolean useBadPackage = intent.getBooleanExtra(EXTRA_BAD_PACKAGE, false);
+ if (useBadPackage) {
+ componentName = ComponentName.unflattenFromString("pkg/.cls");
+ } else {
+ componentName = new ComponentName(context, TestActiveTileService.class);
+ }
+ try {
+ requestListeningState(context, componentName);
+ } catch (SecurityException e) {
+ Log.i(TAG, TEST_PREFIX + "SecurityException");
+ }
}
}
}
diff --git a/hostsidetests/systemui/src/android/host/systemui/ActiveTileServiceCompatChangeTest.java b/hostsidetests/systemui/src/android/host/systemui/ActiveTileServiceCompatChangeTest.java
new file mode 100644
index 0000000..d861e40
--- /dev/null
+++ b/hostsidetests/systemui/src/android/host/systemui/ActiveTileServiceCompatChangeTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2022 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.host.systemui;
+
+import android.compat.cts.CompatChangeGatingTestCase;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.util.Set;
+
+public class ActiveTileServiceCompatChangeTest extends CompatChangeGatingTestCase {
+
+ // Constants for generating commands below.
+ private static final String PACKAGE = "android.systemui.cts";
+
+ // Commands used on the device.
+ private static final String ADD_TILE = "cmd statusbar add-tile ";
+ private static final String REM_TILE = "cmd statusbar remove-tile ";
+
+ public static final String REQUEST_SUPPORTED = "cmd statusbar check-support";
+ public static final String TEST_PREFIX = "TileTest_";
+
+ // Time between checks for logs we expect.
+ private static final long CHECK_DELAY = 500;
+ // Number of times to check before failing.
+ private static final long CHECK_RETRIES = 30;
+
+ private final String mService = "TestActiveTileService";
+ private final String mComponent = PACKAGE + "/." + mService;
+
+ private static final long REQUEST_LISTENING_MUST_MATCH_PACKAGE = 172251878L;
+
+ private static final String EXTRA_BAD_PACKAGE = "android.systemui.cts.EXTRA_BAD_PACKAGE";
+ private static final String ACTION_REQUEST_LISTENING =
+ "android.sysui.testtile.REQUEST_LISTENING";
+
+ private static final String REQUEST_LISTENING = "am broadcast -a " + ACTION_REQUEST_LISTENING
+ + " " + PACKAGE;
+
+ private static final String REQUEST_LISTENING_BAD =
+ REQUEST_LISTENING + " -ez " + EXTRA_BAD_PACKAGE + " true";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ clearLogcat();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ if (!supported()) return;
+ remTile();
+ // Try to wait for a onTileRemoved.
+ waitFor("onTileRemoved");
+ }
+
+ public void testRequestListening_changeEnabled() throws Exception {
+ runTest(true);
+ }
+
+ public void testRequestListening_changeDisabled() throws Exception {
+ runTest(false);
+ }
+
+ public void testRequestListeningBadPackage_changeEnabled_SecurityException() throws Exception {
+ if (!supported()) return;
+ Set<Long> enabledSet = Set.of(REQUEST_LISTENING_MUST_MATCH_PACKAGE);
+ Set<Long> disabledSet = Set.of();
+
+ setCompatConfig(enabledSet, disabledSet, PACKAGE);
+
+ addTile();
+ assertTrue(waitFor("onDestroy"));
+
+ // Request the listening state but use a bad component name (not in the same package)
+ getDevice().executeShellCommand(REQUEST_LISTENING_BAD);
+ assertTrue(waitFor("SecurityException"));
+ }
+
+ private void runTest(boolean enabled) throws Exception {
+ if (!supported()) return;
+ Set<Long> enabledSet = enabled ? Set.of(REQUEST_LISTENING_MUST_MATCH_PACKAGE) : Set.of();
+ Set<Long> disabledSet = enabled ? Set.of() : Set.of(REQUEST_LISTENING_MUST_MATCH_PACKAGE);
+
+ setCompatConfig(enabledSet, disabledSet, PACKAGE);
+
+ final long configId = getClass().getCanonicalName().hashCode();
+ createAndUploadStatsdConfig(configId, PACKAGE);
+
+ try {
+ executeRequestListeningTest();
+ } finally {
+ resetCompatChanges(Set.of(REQUEST_LISTENING_MUST_MATCH_PACKAGE), PACKAGE);
+ validatePostRunStatsdReport(configId, PACKAGE, enabledSet, disabledSet);
+ }
+ }
+
+ private void executeRequestListeningTest() throws Exception {
+ addTile();
+ assertTrue(waitFor("onDestroy"));
+
+ // Request the listening state and verify that it gets an onStartListening.
+ getDevice().executeShellCommand(REQUEST_LISTENING);
+ assertTrue(waitFor("requestListeningState"));
+ assertTrue(waitFor("onStartListening"));
+ }
+
+ private void addTile() throws Exception {
+ execute(ADD_TILE + mComponent);
+ }
+
+ private void remTile() throws Exception {
+ execute(REM_TILE + mComponent);
+ }
+
+ private void execute(String cmd) throws Exception {
+ getDevice().executeShellCommand(cmd);
+ // All of the status bar commands tend to have animations associated
+ // everything seems to be happier if you give them time to finish.
+ Thread.sleep(100);
+ }
+
+ protected boolean waitFor(String str) throws DeviceNotAvailableException, InterruptedException {
+ final String searchStr = TEST_PREFIX + str;
+ int ct = 0;
+ while (!hasLog(searchStr) && (ct++ < CHECK_RETRIES)) {
+ Thread.sleep(CHECK_DELAY);
+ }
+ return hasLog(searchStr);
+ }
+
+ protected boolean hasLog(String str) throws DeviceNotAvailableException {
+ String logs = getDevice().executeAdbCommand("logcat", "-v", "brief", "-d", mService + ":I",
+ "*:S");
+ return logs.contains(str);
+ }
+
+ private void clearLogcat() throws DeviceNotAvailableException {
+ getDevice().executeAdbCommand("logcat", "-c");
+ }
+
+ protected boolean supported() throws DeviceNotAvailableException {
+ return supportedHardware() && supportedSoftware();
+ }
+
+ private boolean supportedSoftware() throws DeviceNotAvailableException {
+ String supported = getDevice().executeShellCommand(REQUEST_SUPPORTED);
+ return Boolean.parseBoolean(supported);
+ }
+
+ private boolean supportedHardware() throws DeviceNotAvailableException {
+ String features = getDevice().executeShellCommand("pm list features");
+ return !features.contains("android.hardware.type.television")
+ && !features.contains("android.hardware.type.watch");
+ }
+}