1 /* 2 * Copyright (C) 2017 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 package com.android.cts.launchertests; 17 18 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.setDefaultLauncher; 19 20 import static junit.framework.Assert.assertFalse; 21 import static junit.framework.Assert.assertNotNull; 22 import static junit.framework.Assert.assertTrue; 23 24 import static org.testng.Assert.assertThrows; 25 26 import android.content.BroadcastReceiver; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.os.Bundle; 31 import android.os.UserHandle; 32 import android.os.UserManager; 33 import android.support.test.uiautomator.UiDevice; 34 import android.text.TextUtils; 35 36 import androidx.test.InstrumentationRegistry; 37 import androidx.test.runner.AndroidJUnit4; 38 39 import com.android.compatibility.common.util.BlockingBroadcastReceiver; 40 41 import org.junit.After; 42 import org.junit.Before; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 46 import java.util.concurrent.LinkedBlockingQueue; 47 import java.util.concurrent.TimeUnit; 48 49 /** 50 * Test that runs {@link UserManager#trySetQuietModeEnabled(boolean, UserHandle)} API 51 * against valid target user. 52 */ 53 @RunWith(AndroidJUnit4.class) 54 public class QuietModeTest { 55 private static final String PARAM_TARGET_USER = "TARGET_USER"; 56 private static final String PARAM_ORIGINAL_DEFAULT_LAUNCHER = "ORIGINAL_DEFAULT_LAUNCHER"; 57 private static final ComponentName LAUNCHER_ACTIVITY = 58 new ComponentName( 59 "com.android.cts.launchertests.support", 60 "com.android.cts.launchertests.support.LauncherActivity"); 61 62 private static final ComponentName COMMAND_RECEIVER = 63 new ComponentName( 64 "com.android.cts.launchertests.support", 65 "com.android.cts.launchertests.support.QuietModeCommandReceiver"); 66 67 private UserManager mUserManager; 68 private UserHandle mTargetUser; 69 private Context mContext; 70 private String mOriginalLauncher; 71 private UiDevice mUiDevice; 72 73 @Before setupUserManager()74 public void setupUserManager() throws Exception { 75 mContext = InstrumentationRegistry.getTargetContext(); 76 mUserManager = mContext.getSystemService(UserManager.class); 77 } 78 79 @Before readParams()80 public void readParams() { 81 Context context = InstrumentationRegistry.getContext(); 82 Bundle arguments = InstrumentationRegistry.getArguments(); 83 UserManager userManager = context.getSystemService(UserManager.class); 84 final int userSn = Integer.parseInt(arguments.getString(PARAM_TARGET_USER)); 85 mTargetUser = userManager.getUserForSerialNumber(userSn); 86 mOriginalLauncher = arguments.getString(PARAM_ORIGINAL_DEFAULT_LAUNCHER); 87 } 88 89 @Before wakeupDeviceAndUnlock()90 public void wakeupDeviceAndUnlock() throws Exception { 91 mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 92 mUiDevice.wakeUp(); 93 mUiDevice.pressMenu(); 94 } 95 96 @Before 97 @After revertToDefaultLauncher()98 public void revertToDefaultLauncher() throws Exception { 99 if (TextUtils.isEmpty(mOriginalLauncher)) { 100 return; 101 } 102 setDefaultLauncher(InstrumentationRegistry.getInstrumentation(), mOriginalLauncher); 103 startActivitySync(mOriginalLauncher); 104 } 105 106 @Test testTryEnableQuietMode_defaultForegroundLauncher()107 public void testTryEnableQuietMode_defaultForegroundLauncher() throws Exception { 108 setTestAppAsDefaultLauncher(); 109 startLauncherActivityInTestApp(); 110 111 Intent intent = trySetQuietModeEnabled(true); 112 assertNotNull("Failed to receive ACTION_MANAGED_PROFILE_UNAVAILABLE broadcast", intent); 113 assertTrue(mUserManager.isQuietModeEnabled(mTargetUser)); 114 115 intent = trySetQuietModeEnabled(false); 116 assertNotNull("Failed to receive ACTION_MANAGED_PROFILE_AVAILABLE broadcast", intent); 117 assertFalse(mUserManager.isQuietModeEnabled(mTargetUser)); 118 } 119 120 @Test testTryEnableQuietMode_notForegroundLauncher()121 public void testTryEnableQuietMode_notForegroundLauncher() throws InterruptedException { 122 setTestAppAsDefaultLauncher(); 123 124 assertThrows(SecurityException.class, () -> trySetQuietModeEnabled(true)); 125 assertFalse(mUserManager.isQuietModeEnabled(mTargetUser)); 126 } 127 128 @Test testTryEnableQuietMode_notDefaultLauncher()129 public void testTryEnableQuietMode_notDefaultLauncher() throws Exception { 130 startLauncherActivityInTestApp(); 131 132 assertThrows(SecurityException.class, () -> trySetQuietModeEnabled(true)); 133 assertFalse(mUserManager.isQuietModeEnabled(mTargetUser)); 134 } 135 trySetQuietModeEnabled(boolean enabled)136 private Intent trySetQuietModeEnabled(boolean enabled) throws Exception { 137 final String action = enabled 138 ? Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE 139 : Intent.ACTION_MANAGED_PROFILE_AVAILABLE; 140 141 BlockingBroadcastReceiver receiver = 142 new BlockingBroadcastReceiver(mContext, action); 143 try { 144 receiver.register(); 145 146 boolean notShowingConfirmCredential = askLauncherSupportAppToSetQuietMode(enabled); 147 assertTrue(notShowingConfirmCredential); 148 149 return receiver.awaitForBroadcast(); 150 } finally { 151 receiver.unregisterQuietly(); 152 } 153 } 154 155 /** 156 * Ask launcher support test app to set quiet mode by sending broadcast. 157 * <p> 158 * We cannot simply make this package the launcher and call the API because instrumentation 159 * process would always considered to be in the foreground. The trick here is to send 160 * broadcast to another test app which is launcher itself and call the API through it. 161 * The receiver will then send back the result, and it should be either true, false or 162 * security-exception. 163 * <p> 164 * All the constants defined here should be aligned with 165 * com.android.cts.launchertests.support.QuietModeCommandReceiver. 166 */ askLauncherSupportAppToSetQuietMode(boolean enabled)167 private boolean askLauncherSupportAppToSetQuietMode(boolean enabled) throws Exception { 168 Intent intent = new Intent("toggle_quiet_mode"); 169 intent.setComponent(COMMAND_RECEIVER); 170 intent.putExtra("quiet_mode", enabled); 171 intent.putExtra(Intent.EXTRA_USER, mTargetUser); 172 173 // Ask launcher support app to set quiet mode by sending broadcast. 174 LinkedBlockingQueue<String> blockingQueue = new LinkedBlockingQueue<>(); 175 mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { 176 @Override 177 public void onReceive(Context context, Intent intent) { 178 blockingQueue.offer(getResultData()); 179 } 180 }, null, 0, "", null); 181 182 // Wait for the result. 183 String result = null; 184 for (int i = 0; i < 10; i++) { 185 // Broadcast won't be delivered when the device is sleeping, so wake up the device 186 // in between each attempt. 187 wakeupDeviceAndUnlock(); 188 result = blockingQueue.poll(10, TimeUnit.SECONDS); 189 if (!TextUtils.isEmpty(result)) { 190 break; 191 } 192 } 193 194 // Parse the result. 195 assertNotNull(result); 196 if ("true".equalsIgnoreCase(result)) { 197 return true; 198 } else if ("false".equalsIgnoreCase(result)) { 199 return false; 200 } else if ("security-exception".equals(result)) { 201 throw new SecurityException(); 202 } 203 throw new IllegalStateException("Unexpected result : " + result); 204 } 205 startActivitySync(String activity)206 private void startActivitySync(String activity) throws Exception { 207 mUiDevice.executeShellCommand("am start -W -n " + activity); 208 } 209 210 /** 211 * Start the launcher activity in the test app to make it foreground. 212 */ startLauncherActivityInTestApp()213 private void startLauncherActivityInTestApp() throws Exception { 214 startActivitySync(LAUNCHER_ACTIVITY.flattenToString()); 215 } 216 setTestAppAsDefaultLauncher()217 private void setTestAppAsDefaultLauncher() { 218 setDefaultLauncher( 219 InstrumentationRegistry.getInstrumentation(), 220 LAUNCHER_ACTIVITY.flattenToString()); 221 } 222 } 223 224