From 2241956858b9f4a230c11fb8ed6f94bb43379c45 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell <rtmitchell@google.com> Date: Mon, 28 Dec 2020 13:03:50 -0800 Subject: [PATCH] OMS: add tests for the OMS transactional API Add test cases for the new OMS transactional API. Also, migrate the existing OverlayDeviceTests from the overlay manager's shell interface to OverlayManager and transactions. Bug: 119916381 Test: atest OverlayDeviceTests Change-Id: Ie5344c53dbd470c0eb3143798d27ac490096b34e --- .../overlaytest/LocalOverlayManager.java | 78 ++++++---- .../android/overlaytest/TransactionTest.java | 133 ++++++++++++++++++ .../overlaytest/WithMultipleOverlaysTest.java | 9 +- .../android/overlaytest/WithOverlayTest.java | 11 +- .../overlaytest/WithoutOverlayTest.java | 9 +- 5 files changed, 190 insertions(+), 50 deletions(-) create mode 100644 core/tests/overlaytests/device/src/com/android/overlaytest/TransactionTest.java diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/LocalOverlayManager.java b/core/tests/overlaytests/device/src/com/android/overlaytest/LocalOverlayManager.java index 390bb766ab81..76c01a7e1125 100644 --- a/core/tests/overlaytests/device/src/com/android/overlaytest/LocalOverlayManager.java +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/LocalOverlayManager.java @@ -18,60 +18,76 @@ package com.android.overlaytest; import static java.util.concurrent.TimeUnit.SECONDS; -import android.app.UiAutomation; -import android.content.res.Resources; -import android.os.ParcelFileDescriptor; +import android.annotation.NonNull; +import android.content.Context; +import android.content.om.OverlayManager; +import android.content.om.OverlayManagerTransaction; +import android.os.UserHandle; import androidx.test.InstrumentationRegistry; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; import java.util.concurrent.Executor; import java.util.concurrent.FutureTask; class LocalOverlayManager { private static final long TIMEOUT = 30; - public static void setEnabledAndWait(Executor executor, final String packageName, - boolean enable) throws Exception { - final String pattern = (enable ? "[x]" : "[ ]") + " " + packageName; - if (executeShellCommand("cmd overlay list").contains(pattern)) { - // nothing to do, overlay already in the requested state - return; + public static void toggleOverlaysAndWait(@NonNull final String[] overlaysToEnable, + @NonNull final String[] overlaysToDisable) throws Exception { + final int userId = UserHandle.myUserId(); + OverlayManagerTransaction.Builder builder = new OverlayManagerTransaction.Builder(); + for (String pkg : overlaysToEnable) { + builder.setEnabled(pkg, true, userId); } + for (String pkg : overlaysToDisable) { + builder.setEnabled(pkg, false, userId); + } + OverlayManagerTransaction transaction = builder.build(); - final Resources res = InstrumentationRegistry.getContext().getResources(); - final String[] oldApkPaths = res.getAssets().getApkPaths(); + final Context ctx = InstrumentationRegistry.getTargetContext(); FutureTask<Boolean> task = new FutureTask<>(() -> { while (true) { - if (!Arrays.equals(oldApkPaths, res.getAssets().getApkPaths())) { + final String[] paths = ctx.getResources().getAssets().getApkPaths(); + if (arrayTailContains(paths, overlaysToEnable) + && arrayDoesNotContain(paths, overlaysToDisable)) { return true; } Thread.sleep(10); } }); + + OverlayManager om = ctx.getSystemService(OverlayManager.class); + om.commit(transaction); + + Executor executor = (cmd) -> new Thread(cmd).start(); executor.execute(task); - executeShellCommand("cmd overlay " + (enable ? "enable " : "disable ") + packageName); task.get(TIMEOUT, SECONDS); } - private static String executeShellCommand(final String command) - throws Exception { - final UiAutomation uiAutomation = - InstrumentationRegistry.getInstrumentation().getUiAutomation(); - final ParcelFileDescriptor pfd = uiAutomation.executeShellCommand(command); - try (InputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { - final BufferedReader reader = new BufferedReader( - new InputStreamReader(in, StandardCharsets.UTF_8)); - StringBuilder str = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - str.append(line); + private static boolean arrayTailContains(@NonNull final String[] array, + @NonNull final String[] substrings) { + if (array.length < substrings.length) { + return false; + } + for (int i = 0; i < substrings.length; i++) { + String a = array[array.length - substrings.length + i]; + String s = substrings[i]; + if (!a.contains(s)) { + return false; + } + } + return true; + } + + private static boolean arrayDoesNotContain(@NonNull final String[] array, + @NonNull final String[] substrings) { + for (String s : substrings) { + for (String a : array) { + if (a.contains(s)) { + return false; + } } - return str.toString(); } + return true; } } diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/TransactionTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/TransactionTest.java new file mode 100644 index 000000000000..0b4f5e227169 --- /dev/null +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/TransactionTest.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2019 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.overlaytest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.testng.Assert.assertThrows; + +import android.content.Context; +import android.content.om.OverlayInfo; +import android.content.om.OverlayManager; +import android.content.om.OverlayManagerTransaction; +import android.content.res.Resources; +import android.os.UserHandle; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.MediumTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.List; + +@RunWith(JUnit4.class) +@MediumTest +public class TransactionTest { + static final String APP_OVERLAY_ONE_PKG = "com.android.overlaytest.app_overlay_one"; + static final String APP_OVERLAY_TWO_PKG = "com.android.overlaytest.app_overlay_two"; + + private Context mContext; + private Resources mResources; + private OverlayManager mOverlayManager; + private int mUserId; + private UserHandle mUserHandle; + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getContext(); + mResources = mContext.getResources(); + mOverlayManager = mContext.getSystemService(OverlayManager.class); + mUserId = UserHandle.myUserId(); + mUserHandle = UserHandle.of(mUserId); + + LocalOverlayManager.toggleOverlaysAndWait( + new String[]{}, + new String[]{APP_OVERLAY_ONE_PKG, APP_OVERLAY_TWO_PKG}); + } + + @Test + public void testValidTransaction() throws Exception { + assertOverlayIsEnabled(APP_OVERLAY_ONE_PKG, false, mUserId); + assertOverlayIsEnabled(APP_OVERLAY_TWO_PKG, false, mUserId); + + OverlayManagerTransaction t = new OverlayManagerTransaction.Builder() + .setEnabled(APP_OVERLAY_ONE_PKG, true) + .setEnabled(APP_OVERLAY_TWO_PKG, true) + .build(); + mOverlayManager.commit(t); + + assertOverlayIsEnabled(APP_OVERLAY_ONE_PKG, true, mUserId); + assertOverlayIsEnabled(APP_OVERLAY_TWO_PKG, true, mUserId); + List<OverlayInfo> ois = + mOverlayManager.getOverlayInfosForTarget("com.android.overlaytest", mUserHandle); + assertEquals(ois.size(), 2); + assertEquals(ois.get(0).packageName, APP_OVERLAY_ONE_PKG); + assertEquals(ois.get(1).packageName, APP_OVERLAY_TWO_PKG); + + OverlayManagerTransaction t2 = new OverlayManagerTransaction.Builder() + .setEnabled(APP_OVERLAY_TWO_PKG, true) + .setEnabled(APP_OVERLAY_ONE_PKG, true) + .build(); + mOverlayManager.commit(t2); + + assertOverlayIsEnabled(APP_OVERLAY_ONE_PKG, true, mUserId); + assertOverlayIsEnabled(APP_OVERLAY_TWO_PKG, true, mUserId); + List<OverlayInfo> ois2 = + mOverlayManager.getOverlayInfosForTarget("com.android.overlaytest", mUserHandle); + assertEquals(ois2.size(), 2); + assertEquals(ois2.get(0).packageName, APP_OVERLAY_TWO_PKG); + assertEquals(ois2.get(1).packageName, APP_OVERLAY_ONE_PKG); + + OverlayManagerTransaction t3 = new OverlayManagerTransaction.Builder() + .setEnabled(APP_OVERLAY_TWO_PKG, false) + .build(); + mOverlayManager.commit(t3); + + assertOverlayIsEnabled(APP_OVERLAY_ONE_PKG, true, mUserId); + assertOverlayIsEnabled(APP_OVERLAY_TWO_PKG, false, mUserId); + List<OverlayInfo> ois3 = + mOverlayManager.getOverlayInfosForTarget("com.android.overlaytest", mUserHandle); + assertEquals(ois3.size(), 2); + assertEquals(ois3.get(0).packageName, APP_OVERLAY_TWO_PKG); + assertEquals(ois3.get(1).packageName, APP_OVERLAY_ONE_PKG); + } + + @Test + public void testInvalidRequestHasNoEffect() { + assertOverlayIsEnabled(APP_OVERLAY_ONE_PKG, false, mUserId); + assertOverlayIsEnabled(APP_OVERLAY_TWO_PKG, false, mUserId); + + OverlayManagerTransaction t = new OverlayManagerTransaction.Builder() + .setEnabled(APP_OVERLAY_ONE_PKG, true) + .setEnabled("does-not-exist", true) + .setEnabled(APP_OVERLAY_TWO_PKG, true) + .build(); + assertThrows(SecurityException.class, () -> mOverlayManager.commit(t)); + + assertOverlayIsEnabled(APP_OVERLAY_ONE_PKG, false, mUserId); + assertOverlayIsEnabled(APP_OVERLAY_TWO_PKG, false, mUserId); + } + + private void assertOverlayIsEnabled(final String packageName, boolean enabled, int userId) { + final OverlayInfo oi = mOverlayManager.getOverlayInfo(packageName, UserHandle.of(userId)); + assertNotNull(oi); + assertEquals(oi.isEnabled(), enabled); + } +} diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java index d28c47d9c922..420f755c5251 100644 --- a/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/WithMultipleOverlaysTest.java @@ -22,8 +22,6 @@ import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.util.concurrent.Executor; - @RunWith(JUnit4.class) @MediumTest public class WithMultipleOverlaysTest extends OverlayBaseTest { @@ -33,9 +31,8 @@ public class WithMultipleOverlaysTest extends OverlayBaseTest { @BeforeClass public static void enableOverlay() throws Exception { - Executor executor = (cmd) -> new Thread(cmd).start(); - LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_ONE_PKG, true); - LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_TWO_PKG, true); - LocalOverlayManager.setEnabledAndWait(executor, FRAMEWORK_OVERLAY_PKG, true); + LocalOverlayManager.toggleOverlaysAndWait( + new String[]{FRAMEWORK_OVERLAY_PKG, APP_OVERLAY_ONE_PKG, APP_OVERLAY_TWO_PKG}, + new String[]{}); } } diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java index 6566ad304c1c..a86255e96388 100644 --- a/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/WithOverlayTest.java @@ -22,8 +22,6 @@ import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.util.concurrent.Executor; - @RunWith(JUnit4.class) @MediumTest public class WithOverlayTest extends OverlayBaseTest { @@ -32,10 +30,9 @@ public class WithOverlayTest extends OverlayBaseTest { } @BeforeClass - public static void enableOverlay() throws Exception { - Executor executor = (cmd) -> new Thread(cmd).start(); - LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_ONE_PKG, true); - LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_TWO_PKG, false); - LocalOverlayManager.setEnabledAndWait(executor, FRAMEWORK_OVERLAY_PKG, true); + public static void enableOverlays() throws Exception { + LocalOverlayManager.toggleOverlaysAndWait( + new String[]{FRAMEWORK_OVERLAY_PKG, APP_OVERLAY_ONE_PKG}, + new String[]{APP_OVERLAY_TWO_PKG}); } } diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java index 48cfeab2fbff..51c411819b87 100644 --- a/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java +++ b/core/tests/overlaytests/device/src/com/android/overlaytest/WithoutOverlayTest.java @@ -22,8 +22,6 @@ import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.util.concurrent.Executor; - @RunWith(JUnit4.class) @MediumTest public class WithoutOverlayTest extends OverlayBaseTest { @@ -33,9 +31,8 @@ public class WithoutOverlayTest extends OverlayBaseTest { @BeforeClass public static void disableOverlays() throws Exception { - Executor executor = (cmd) -> new Thread(cmd).start(); - LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_ONE_PKG, false); - LocalOverlayManager.setEnabledAndWait(executor, APP_OVERLAY_TWO_PKG, false); - LocalOverlayManager.setEnabledAndWait(executor, FRAMEWORK_OVERLAY_PKG, false); + LocalOverlayManager.toggleOverlaysAndWait( + new String[]{}, + new String[]{FRAMEWORK_OVERLAY_PKG, APP_OVERLAY_ONE_PKG, APP_OVERLAY_TWO_PKG}); } } -- GitLab