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 17 package android.media.session.cts; 18 19 import static android.media.cts.MediaSessionTestHelperConstants.FLAG_CREATE_MEDIA_SESSION; 20 import static android.media.cts.MediaSessionTestHelperConstants.FLAG_CREATE_MEDIA_SESSION2; 21 import static android.media.cts.MediaSessionTestHelperConstants.FLAG_SET_MEDIA_SESSION_ACTIVE; 22 import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_APK; 23 import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_PKG; 24 25 import static com.google.common.truth.Truth.assertWithMessage; 26 27 import android.media.cts.BaseMultiUserTest; 28 import android.media.cts.MediaSessionTestHelperConstants; 29 import android.platform.test.annotations.AppModeFull; 30 import android.platform.test.annotations.AppModeInstant; 31 import android.platform.test.annotations.RequiresDevice; 32 33 import com.android.ddmlib.Log.LogLevel; 34 import com.android.tradefed.device.DeviceNotAvailableException; 35 import com.android.tradefed.device.ITestDevice; 36 import com.android.tradefed.log.LogUtil.CLog; 37 import com.android.tradefed.util.RunUtil; 38 39 import java.util.ArrayList; 40 import java.util.List; 41 42 /** 43 * Host-side test for the media session manager that installs and runs device-side tests after the 44 * proper device setup. 45 * <p>Corresponding device-side tests are written in the {@link #DEVICE_SIDE_TEST_CLASS} 46 * which is in the {@link #DEVICE_SIDE_TEST_APK}. 47 */ 48 public class MediaSessionManagerHostTest extends BaseMultiUserTest { 49 /** 50 * Package name of the device-side tests. 51 */ 52 private static final String DEVICE_SIDE_TEST_PKG = "android.media.session.cts"; 53 /** 54 * Package file name (.apk) for the device-side tests. 55 */ 56 private static final String DEVICE_SIDE_TEST_APK = "CtsMediaSessionHostTestApp.apk"; 57 /** 58 * Fully qualified class name for the device-side tests. 59 */ 60 private static final String DEVICE_SIDE_TEST_CLASS = 61 "android.media.session.cts.MediaSessionManagerTest"; 62 63 private static final int TIMEOUT_MS = 1000; 64 65 /** 66 * Returned by {@link ITestDevice#getCurrentUser()} when there is an error retrieving the 67 * current user id. 68 */ 69 private static final int INVALID_USER_ID = -10000; 70 71 private final List<Integer> mNotificationListeners = new ArrayList<>(); 72 73 @Override setUp()74 public void setUp() throws Exception { 75 super.setUp(); 76 mNotificationListeners.clear(); 77 } 78 79 @Override tearDown()80 public void tearDown() throws Exception { 81 getDevice().uninstallPackage(MEDIA_SESSION_TEST_HELPER_PKG); 82 getDevice().uninstallPackage(DEVICE_SIDE_TEST_PKG); 83 for (int userId : mNotificationListeners) { 84 setAllowGetActiveSessionForTest(false, userId); 85 } 86 super.tearDown(); 87 } 88 89 /** 90 * Tests {@link MediaSessionManager#getActiveSessions} with the primary user. 91 */ 92 @AppModeInstant 93 @RequiresDevice testGetActiveSessionsInstant_primaryUser()94 public void testGetActiveSessionsInstant_primaryUser() throws Exception { 95 testGetActiveSessions_primaryUser(true); 96 } 97 98 /** 99 * Tests {@link MediaSessionManager#getActiveSessions} with the primary user. 100 */ 101 @AppModeFull 102 @RequiresDevice testGetActiveSessionsFull_primaryUser()103 public void testGetActiveSessionsFull_primaryUser() throws Exception { 104 testGetActiveSessions_primaryUser(false); 105 } 106 testGetActiveSessions_primaryUser(boolean instant)107 private void testGetActiveSessions_primaryUser(boolean instant) throws Exception { 108 int userIdForTesting = getUserIdForTesting(); 109 110 setAllowGetActiveSessionForTest(true, userIdForTesting); 111 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, instant); 112 runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper"); 113 114 installAppAsUser( 115 MEDIA_SESSION_TEST_HELPER_APK, 116 MEDIA_SESSION_TEST_HELPER_PKG, 117 userIdForTesting, 118 false); 119 sendControlCommand(userIdForTesting, FLAG_CREATE_MEDIA_SESSION); 120 runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper"); 121 122 sendControlCommand(userIdForTesting, FLAG_SET_MEDIA_SESSION_ACTIVE); 123 runTest("testGetActiveSessions_hasMediaSessionFromMediaSessionTestHelper"); 124 } 125 126 /** 127 * Tests {@link MediaSessionManager#getActiveSessions} with additional users. 128 */ 129 @AppModeInstant 130 @RequiresDevice testGetActiveSessionsInstant_additionalUser()131 public void testGetActiveSessionsInstant_additionalUser() throws Exception { 132 testGetActiveSessions_additionalUser(true); 133 } 134 135 /** 136 * Tests {@link MediaSessionManager#getActiveSessions} with additional users. 137 */ 138 @AppModeFull 139 @RequiresDevice testGetActiveSessionsFull_additionalUser()140 public void testGetActiveSessionsFull_additionalUser() throws Exception { 141 testGetActiveSessions_additionalUser(false); 142 } 143 testGetActiveSessions_additionalUser(boolean instant)144 private void testGetActiveSessions_additionalUser(boolean instant) throws Exception { 145 if (!canCreateAdditionalUsers(1)) { 146 CLog.logAndDisplay(LogLevel.INFO, 147 "Cannot create a new user. Skipping multi-user test cases."); 148 return; 149 } 150 151 // Test if another user can get the session. 152 int newUser = createAndStartUser(); 153 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, newUser, instant); 154 setAllowGetActiveSessionForTest(true, newUser); 155 runTestAsUser("testGetActiveSessions_noMediaSession", newUser); 156 removeUser(newUser); 157 } 158 159 /** 160 * Tests {@link MediaSessionManager#getActiveSessions} with restricted profiles. 161 */ 162 @AppModeInstant 163 @RequiresDevice testGetActiveSessionsInstant_restrictedProfiles()164 public void testGetActiveSessionsInstant_restrictedProfiles() throws Exception { 165 testGetActiveSessions_restrictedProfiles(true); 166 } 167 168 /** 169 * Tests {@link MediaSessionManager#getActiveSessions} with restricted profiles. 170 */ 171 @AppModeFull 172 @RequiresDevice testGetActiveSessionsFull_restrictedProfiles()173 public void testGetActiveSessionsFull_restrictedProfiles() throws Exception { 174 testGetActiveSessions_restrictedProfiles(false); 175 } 176 testGetActiveSessions_restrictedProfiles(boolean instant)177 private void testGetActiveSessions_restrictedProfiles(boolean instant) 178 throws Exception { 179 if (!canCreateAdditionalUsers(1)) { 180 CLog.logAndDisplay(LogLevel.INFO, 181 "Cannot create a new user. Skipping multi-user test cases."); 182 return; 183 } 184 185 // Test if another restricted profile can get the session. 186 // Remove the created user first not to exceed system's user number limit. 187 // Restricted profile's parent must be the primary user (the system user). 188 int newUser = createAndStartRestrictedProfile(getDevice().getPrimaryUserId()); 189 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, newUser, instant); 190 setAllowGetActiveSessionForTest(true, newUser); 191 runTestAsUser("testGetActiveSessions_noMediaSession", newUser); 192 removeUser(newUser); 193 } 194 195 /** 196 * Tests {@link MediaSessionManager#getActiveSessions} with managed profiles. 197 */ 198 @AppModeInstant 199 @RequiresDevice testGetActiveSessionsInstant_managedProfiles()200 public void testGetActiveSessionsInstant_managedProfiles() throws Exception { 201 testGetActiveSessions_managedProfiles(true); 202 } 203 204 /** 205 * Tests {@link MediaSessionManager#getActiveSessions} with managed profiles. 206 */ 207 @AppModeFull 208 @RequiresDevice testGetActiveSessionsFull_managedProfiles()209 public void testGetActiveSessionsFull_managedProfiles() throws Exception { 210 testGetActiveSessions_managedProfiles(false); 211 } 212 testGetActiveSessions_managedProfiles(boolean instant)213 private void testGetActiveSessions_managedProfiles(boolean instant) 214 throws Exception { 215 if (!hasDeviceFeature("android.software.managed_users")) { 216 CLog.logAndDisplay(LogLevel.INFO, 217 "Device doesn't support managed profiles. Test won't run."); 218 return; 219 } 220 221 // Test if another managed profile can get the session. 222 // Remove the created user first not to exceed system's user number limit. 223 // Managed profile's parent must not be the primary user (in the context of this test, we 224 // use the main user). 225 int newUser = createAndStartManagedProfile(getUserIdForTesting()); 226 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, newUser, instant); 227 setAllowGetActiveSessionForTest(true, newUser); 228 runTestAsUser("testGetActiveSessions_noMediaSession", newUser); 229 removeUser(newUser); 230 } 231 232 @AppModeFull 233 @RequiresDevice testGetActiveSessions_noSession2()234 public void testGetActiveSessions_noSession2() throws Exception { 235 int userIdForTesting = getUserIdForTesting(); 236 237 setAllowGetActiveSessionForTest(true, userIdForTesting); 238 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, false); 239 runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper"); 240 241 installAppAsUser( 242 MEDIA_SESSION_TEST_HELPER_APK, 243 MEDIA_SESSION_TEST_HELPER_PKG, 244 userIdForTesting, 245 false); 246 sendControlCommand(userIdForTesting, FLAG_CREATE_MEDIA_SESSION2); 247 248 // Wait for a second for framework to recognize media session2. 249 RunUtil.getDefault().sleep(TIMEOUT_MS); 250 runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper"); 251 } 252 253 @AppModeFull 254 @RequiresDevice testGetActiveSessions_withSession2()255 public void testGetActiveSessions_withSession2() throws Exception { 256 int userIdForTesting = getUserIdForTesting(); 257 258 setAllowGetActiveSessionForTest(true, userIdForTesting); 259 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, false); 260 runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper"); 261 262 installAppAsUser( 263 MEDIA_SESSION_TEST_HELPER_APK, 264 MEDIA_SESSION_TEST_HELPER_PKG, 265 userIdForTesting, 266 false); 267 sendControlCommand( 268 userIdForTesting, 269 FLAG_CREATE_MEDIA_SESSION 270 | FLAG_CREATE_MEDIA_SESSION2 271 | FLAG_SET_MEDIA_SESSION_ACTIVE); 272 273 // Wait for a second for framework to recognize media session2. 274 RunUtil.getDefault().sleep(TIMEOUT_MS); 275 276 runTest("testGetActiveSessions_hasMediaSessionFromMediaSessionTestHelper"); 277 } 278 279 @AppModeFull 280 @RequiresDevice testOnMediaKeyEventSessionChangedListener()281 public void testOnMediaKeyEventSessionChangedListener() throws Exception { 282 int userIdForTesting = getUserIdForTesting(); 283 284 setAllowGetActiveSessionForTest(true, userIdForTesting); 285 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, false); 286 runTest("testOnMediaKeyEventSessionChangedListener"); 287 } 288 289 @AppModeFull 290 @RequiresDevice testOnMediaKeyEventSessionChangedListener_whenSessionIsReleased()291 public void testOnMediaKeyEventSessionChangedListener_whenSessionIsReleased() throws Exception { 292 int userIdForTesting = getUserIdForTesting(); 293 294 setAllowGetActiveSessionForTest(true, userIdForTesting); 295 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, false); 296 runTest("testOnMediaKeyEventSessionChangedListener_whenSessionIsReleased"); 297 } 298 299 @AppModeFull 300 @RequiresDevice testIsTrusted_withEnabledNotificationListener_returnsTrue()301 public void testIsTrusted_withEnabledNotificationListener_returnsTrue() throws Exception { 302 if (!canCreateAdditionalUsers(1)) { 303 CLog.logAndDisplay(LogLevel.INFO, 304 "Cannot create a new user. Skipping multi-user test cases."); 305 return; 306 } 307 308 int newUserId = createAndStartUser(); 309 setAllowGetActiveSessionForTest(true, newUserId); 310 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, newUserId, false); 311 runTestAsUser("testIsTrusted_returnsTrue", newUserId); 312 } 313 314 @AppModeFull 315 @RequiresDevice testIsTrusted_withoutEnabledNotificationListener_returnsFalse()316 public void testIsTrusted_withoutEnabledNotificationListener_returnsFalse() 317 throws Exception { 318 if (!canCreateAdditionalUsers(1)) { 319 CLog.logAndDisplay(LogLevel.INFO, 320 "Cannot create a new user. Skipping multi-user test cases."); 321 return; 322 } 323 324 int newUserId = createAndStartUser(); 325 setAllowGetActiveSessionForTest(false, newUserId); 326 installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, newUserId, false); 327 runTestAsUser("testIsTrusted_returnsFalse", newUserId); 328 } 329 runTest(String testMethodName)330 private void runTest(String testMethodName) throws DeviceNotAvailableException { 331 runTestAsUser(testMethodName, getUserIdForTesting()); 332 } 333 runTestAsUser(String testMethodName, int userId)334 private void runTestAsUser(String testMethodName, int userId) 335 throws DeviceNotAvailableException { 336 runDeviceTests(DEVICE_SIDE_TEST_PKG, DEVICE_SIDE_TEST_CLASS, testMethodName, userId); 337 } 338 339 /** 340 * If running headless system user mode, returns the current user. Otherwise, returns the main 341 * user. 342 * 343 * <p>Historically, some tests in this class would use the main user for running device-side 344 * tests. Headless surfaces (like Android Auto) do not have a main user. As a result, on 345 * headless surfaces, we use the current user in replacement of the missing main user. 346 */ getUserIdForTesting()347 private int getUserIdForTesting() throws DeviceNotAvailableException { 348 if (getDevice().isHeadlessSystemUserMode()) { 349 int currentUserId = getDevice().getCurrentUser(); 350 assertWithMessage( 351 "Unable to fetch a valid current user id in headless system user mode.") 352 .that(currentUserId) 353 .isNotEqualTo(INVALID_USER_ID); 354 return currentUserId; 355 } else { 356 return getDevice().getMainUserId(); 357 } 358 } 359 360 /** 361 * Sets to allow or disallow the {@link #DEVICE_SIDE_TEST_CLASS} 362 * to call {@link MediaSessionManager#getActiveSessions} for testing. 363 * <p>{@link MediaSessionManager#getActiveSessions} bypasses the permission check if the 364 * caller is the enabled notification listener. This method uses the behavior by allowing 365 * this class as the notification listener service. 366 * <p>Note that the device-side test {@link android.media.cts.MediaSessionManagerTest} already 367 * covers the test for failing {@link MediaSessionManager#getActiveSessions} without the 368 * permission nor the notification listener. 369 */ setAllowGetActiveSessionForTest(boolean allow, int userId)370 private void setAllowGetActiveSessionForTest(boolean allow, int userId) throws Exception { 371 String notificationListener = DEVICE_SIDE_TEST_PKG + "/" + DEVICE_SIDE_TEST_CLASS; 372 String command = "cmd notification " 373 + ((allow) ? "allow_listener " : "disallow_listener ") 374 + notificationListener + " " + userId; 375 executeShellCommand(command); 376 if (allow) { 377 mNotificationListeners.add(userId); 378 } 379 } 380 sendControlCommand(int userId, int flag)381 private void sendControlCommand(int userId, int flag) throws Exception { 382 executeShellCommand(MediaSessionTestHelperConstants.buildControlCommand(userId, flag)); 383 } 384 } 385