1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.overlay.target; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.truth.Truth.assertWithMessage; 21 22 import static org.junit.Assert.fail; 23 24 import android.app.Instrumentation; 25 import android.content.Intent; 26 import android.os.Bundle; 27 import android.os.UserHandle; 28 29 import androidx.test.InstrumentationRegistry; 30 import androidx.test.rule.ActivityTestRule; 31 import androidx.test.runner.AndroidJUnit4; 32 33 import com.android.compatibility.common.util.PollingCheck; 34 import com.android.compatibility.common.util.SystemUtil; 35 36 import org.junit.Before; 37 import org.junit.Rule; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 41 import java.util.concurrent.CountDownLatch; 42 import java.util.concurrent.TimeUnit; 43 44 @RunWith(AndroidJUnit4.class) 45 public class OverlayTargetTest { 46 // overlay package 47 private static final String OVERLAY_ALL_PACKAGE_NAME = "com.android.cts.overlay.all"; 48 49 // Overlay states 50 private static final String STATE_DISABLED = "STATE_DISABLED"; 51 private static final String STATE_ENABLED = "STATE_ENABLED"; 52 53 // Default timeout value 54 private static final long TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5); 55 56 // Keys for test arguments 57 private static final String PARAM_START_SERVICE = "start_service"; 58 59 private Instrumentation mInstrumentation; 60 61 @Rule 62 public ActivityTestRule<OverlayTargetActivity> mActivityTestRule = new ActivityTestRule<>( 63 OverlayTargetActivity.class, false /* initialTouchMode */, false /* launchActivity */); 64 65 @Before setup()66 public void setup() { 67 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 68 launchOverlayTargetActivity(InstrumentationRegistry.getArguments()); 69 assertThat(mActivityTestRule.getActivity()).isNotNull(); 70 } 71 72 @Test overlayEnabled_activityInForeground()73 public void overlayEnabled_activityInForeground() throws Exception { 74 final OverlayTargetActivity targetActivity = mActivityTestRule.getActivity(); 75 final CountDownLatch latch = new CountDownLatch(1); 76 targetActivity.setConfigurationChangedCallback((activity, config) -> { 77 latch.countDown(); 78 activity.setConfigurationChangedCallback(null); 79 }); 80 81 setOverlayEnabled(OVERLAY_ALL_PACKAGE_NAME, true /* enabled */); 82 83 if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) { 84 fail("Fail to wait configuration changes for the overlay target activity."); 85 } 86 } 87 88 @Test overlayEnabled_activityInBackground_toForeground()89 public void overlayEnabled_activityInBackground_toForeground() throws Exception { 90 final OverlayTargetActivity targetActivity = mActivityTestRule.getActivity(); 91 // Activity goes into background 92 launchSimpleActivity(); 93 mInstrumentation.waitForIdleSync(); 94 final CountDownLatch latch = new CountDownLatch(1); 95 targetActivity.setConfigurationChangedCallback((activity, config) -> { 96 latch.countDown(); 97 activity.setConfigurationChangedCallback(null); 98 }); 99 setOverlayEnabled(OVERLAY_ALL_PACKAGE_NAME, true /* enabled */); 100 101 if (latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) { 102 fail("Activity in background should not receive configuration changes"); 103 } 104 105 // Bring activity to foreground 106 final Intent intent = new Intent(mInstrumentation.getTargetContext(), 107 OverlayTargetActivity.class); 108 intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 109 targetActivity.startActivity(intent); 110 111 if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) { 112 fail("Fail to wait configuration changes for the overlay target activity."); 113 } 114 } 115 launchOverlayTargetActivity(Bundle testArgs)116 private void launchOverlayTargetActivity(Bundle testArgs) { 117 final Intent intent = new Intent(mInstrumentation.getTargetContext(), 118 OverlayTargetActivity.class); 119 final boolean startService = (testArgs != null 120 && "true".equalsIgnoreCase(testArgs.getString(PARAM_START_SERVICE))); 121 intent.putExtra(OverlayTargetActivity.EXTRA_START_SERVICE, startService); 122 mActivityTestRule.launchActivity(intent); 123 mInstrumentation.waitForIdleSync(); 124 } 125 setOverlayEnabled(String overlayPackage, boolean enabled)126 private static void setOverlayEnabled(String overlayPackage, boolean enabled) 127 throws Exception { 128 final String current = getStateForOverlay(overlayPackage); 129 final String expected = enabled ? STATE_ENABLED : STATE_DISABLED; 130 assertThat(current).isNotEqualTo(expected); 131 SystemUtil.runShellCommand("cmd overlay " 132 + (enabled ? "enable" : "disable") 133 + " --user current " 134 + overlayPackage); 135 PollingCheck.check("Fail to wait overlay enabled state " + expected 136 + " for " + overlayPackage, TIMEOUT_MS, 137 () -> expected.equals(getStateForOverlay(overlayPackage))); 138 } 139 launchSimpleActivity()140 private void launchSimpleActivity() { 141 Intent intent = new Intent(Intent.ACTION_MAIN); 142 intent.setClass(mInstrumentation.getTargetContext(), SimpleActivity.class); 143 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 144 mInstrumentation.startActivitySync(intent); 145 } 146 getStateForOverlay(String overlayPackage)147 private static String getStateForOverlay(String overlayPackage) { 148 final String errorMsg = "Fail to parse the state of overlay package " + overlayPackage; 149 final String result = SystemUtil.runShellCommand("cmd overlay dump"); 150 final String overlayPackageForCurrentUser = overlayPackage + ":" + UserHandle.myUserId(); 151 final int startIndex = result.indexOf(overlayPackageForCurrentUser); 152 assertWithMessage(errorMsg).that(startIndex).isAtLeast(0); 153 154 final int endIndex = result.indexOf('}', startIndex); 155 assertWithMessage(errorMsg).that(endIndex).isGreaterThan(startIndex); 156 157 final int stateIndex = result.indexOf("mState", startIndex); 158 assertWithMessage(errorMsg).that(startIndex).isLessThan(stateIndex); 159 assertWithMessage(errorMsg).that(stateIndex).isLessThan(endIndex); 160 161 final int colonIndex = result.indexOf(':', stateIndex); 162 assertWithMessage(errorMsg).that(stateIndex).isLessThan(colonIndex); 163 assertWithMessage(errorMsg).that(colonIndex).isLessThan(endIndex); 164 165 final int endLineIndex = result.indexOf('\n', colonIndex); 166 assertWithMessage(errorMsg).that(colonIndex).isLessThan(endLineIndex); 167 assertWithMessage(errorMsg).that(endLineIndex).isLessThan(endIndex); 168 169 return result.substring(colonIndex + 2, endLineIndex); 170 } 171 } 172