1 /* 2 * Copyright (C) 2009 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.cts; 18 19 import static android.media.AudioManager.ADJUST_LOWER; 20 import static android.media.AudioManager.ADJUST_RAISE; 21 import static android.media.AudioManager.ADJUST_SAME; 22 import static android.media.AudioManager.MODE_IN_CALL; 23 import static android.media.AudioManager.MODE_IN_COMMUNICATION; 24 import static android.media.AudioManager.MODE_NORMAL; 25 import static android.media.AudioManager.MODE_RINGTONE; 26 import static android.media.AudioManager.RINGER_MODE_NORMAL; 27 import static android.media.AudioManager.RINGER_MODE_SILENT; 28 import static android.media.AudioManager.RINGER_MODE_VIBRATE; 29 import static android.media.AudioManager.STREAM_MUSIC; 30 import static android.media.AudioManager.USE_DEFAULT_STREAM_TYPE; 31 import static android.media.AudioManager.VIBRATE_SETTING_OFF; 32 import static android.media.AudioManager.VIBRATE_SETTING_ON; 33 import static android.media.AudioManager.VIBRATE_SETTING_ONLY_SILENT; 34 import static android.media.AudioManager.VIBRATE_TYPE_NOTIFICATION; 35 import static android.media.AudioManager.VIBRATE_TYPE_RINGER; 36 import static android.provider.Settings.System.SOUND_EFFECTS_ENABLED; 37 38 import android.app.NotificationManager; 39 import android.content.Context; 40 import android.content.res.Resources; 41 import android.media.AudioManager; 42 import android.content.pm.PackageManager; 43 import android.media.MediaPlayer; 44 import android.os.Vibrator; 45 import android.provider.Settings; 46 import android.provider.Settings.System; 47 import android.test.InstrumentationTestCase; 48 import android.view.SoundEffectConstants; 49 50 public class AudioManagerTest extends InstrumentationTestCase { 51 52 private final static int MP3_TO_PLAY = R.raw.testmp3; 53 private final static long TIME_TO_PLAY = 2000; 54 private final static String APPOPS_OP_STR = "android:write_settings"; 55 private AudioManager mAudioManager; 56 private NotificationManager mNm; 57 private boolean mHasVibrator; 58 private boolean mUseFixedVolume; 59 private boolean mIsTelevision; 60 private Context mContext; 61 62 @Override setUp()63 protected void setUp() throws Exception { 64 super.setUp(); 65 mContext = getInstrumentation().getContext(); 66 Utils.enableAppOps(mContext.getPackageName(), APPOPS_OP_STR, getInstrumentation()); 67 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 68 Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); 69 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 70 mHasVibrator = (vibrator != null) && vibrator.hasVibrator(); 71 mUseFixedVolume = mContext.getResources().getBoolean( 72 Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android")); 73 PackageManager packageManager = mContext.getPackageManager(); 74 mIsTelevision = packageManager != null 75 && (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) 76 || packageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION)); 77 } 78 testMicrophoneMute()79 public void testMicrophoneMute() throws Exception { 80 mAudioManager.setMicrophoneMute(true); 81 assertTrue(mAudioManager.isMicrophoneMute()); 82 mAudioManager.setMicrophoneMute(false); 83 assertFalse(mAudioManager.isMicrophoneMute()); 84 } 85 testSoundEffects()86 public void testSoundEffects() throws Exception { 87 try { 88 Utils.toggleNotificationPolicyAccess( 89 mContext.getPackageName(), getInstrumentation(), true); 90 // set relative setting 91 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); 92 } finally { 93 Utils.toggleNotificationPolicyAccess( 94 mContext.getPackageName(), getInstrumentation(), false); 95 } 96 Settings.System.putInt(mContext.getContentResolver(), SOUND_EFFECTS_ENABLED, 1); 97 98 // should hear sound after loadSoundEffects() called. 99 mAudioManager.loadSoundEffects(); 100 Thread.sleep(TIME_TO_PLAY); 101 float volume = 13; 102 mAudioManager.playSoundEffect(SoundEffectConstants.CLICK); 103 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP); 104 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN); 105 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT); 106 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT); 107 108 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP, volume); 109 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN, volume); 110 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT, volume); 111 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT, volume); 112 113 // won't hear sound after unloadSoundEffects() called(); 114 mAudioManager.unloadSoundEffects(); 115 mAudioManager.playSoundEffect(AudioManager.FX_KEY_CLICK); 116 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP); 117 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN); 118 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT); 119 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT); 120 121 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP, volume); 122 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN, volume); 123 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT, volume); 124 mAudioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT, volume); 125 } 126 testMusicActive()127 public void testMusicActive() throws Exception { 128 MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY); 129 assertNotNull(mp); 130 mp.setAudioStreamType(AudioManager.STREAM_MUSIC); 131 mp.start(); 132 Thread.sleep(TIME_TO_PLAY); 133 assertTrue(mAudioManager.isMusicActive()); 134 Thread.sleep(TIME_TO_PLAY); 135 mp.stop(); 136 mp.release(); 137 Thread.sleep(TIME_TO_PLAY); 138 assertFalse(mAudioManager.isMusicActive()); 139 } 140 testAccessMode()141 public void testAccessMode() throws Exception { 142 mAudioManager.setMode(MODE_RINGTONE); 143 assertEquals(MODE_RINGTONE, mAudioManager.getMode()); 144 mAudioManager.setMode(MODE_IN_COMMUNICATION); 145 assertEquals(MODE_IN_COMMUNICATION, mAudioManager.getMode()); 146 mAudioManager.setMode(MODE_NORMAL); 147 assertEquals(MODE_NORMAL, mAudioManager.getMode()); 148 } 149 150 @SuppressWarnings("deprecation") testRouting()151 public void testRouting() throws Exception { 152 // setBluetoothA2dpOn is a no-op, and getRouting should always return -1 153 // AudioManager.MODE_CURRENT 154 boolean oldA2DP = mAudioManager.isBluetoothA2dpOn(); 155 mAudioManager.setBluetoothA2dpOn(true); 156 assertEquals(oldA2DP , mAudioManager.isBluetoothA2dpOn()); 157 mAudioManager.setBluetoothA2dpOn(false); 158 assertEquals(oldA2DP , mAudioManager.isBluetoothA2dpOn()); 159 160 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_RINGTONE)); 161 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_NORMAL)); 162 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_CALL)); 163 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_COMMUNICATION)); 164 165 mAudioManager.setBluetoothScoOn(true); 166 assertTrue(mAudioManager.isBluetoothScoOn()); 167 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_RINGTONE)); 168 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_NORMAL)); 169 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_CALL)); 170 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_COMMUNICATION)); 171 172 mAudioManager.setBluetoothScoOn(false); 173 assertFalse(mAudioManager.isBluetoothScoOn()); 174 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_RINGTONE)); 175 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_NORMAL)); 176 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_CALL)); 177 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_COMMUNICATION)); 178 179 mAudioManager.setSpeakerphoneOn(true); 180 assertTrue(mAudioManager.isSpeakerphoneOn()); 181 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_CALL)); 182 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_COMMUNICATION)); 183 mAudioManager.setSpeakerphoneOn(false); 184 assertFalse(mAudioManager.isSpeakerphoneOn()); 185 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_CALL)); 186 assertEquals(AudioManager.MODE_CURRENT, mAudioManager.getRouting(MODE_IN_COMMUNICATION)); 187 } 188 testVibrateNotification()189 public void testVibrateNotification() throws Exception { 190 if (mUseFixedVolume || !mHasVibrator) { 191 return; 192 } 193 try { 194 Utils.toggleNotificationPolicyAccess( 195 mContext.getPackageName(), getInstrumentation(), true); 196 // VIBRATE_SETTING_ON 197 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON); 198 assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF, 199 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 200 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 201 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 202 203 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 204 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 205 206 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 207 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 208 mAudioManager.getRingerMode()); 209 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 210 211 // VIBRATE_SETTING_OFF 212 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF); 213 assertEquals(VIBRATE_SETTING_OFF, 214 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 215 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 216 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 217 218 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 219 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 220 221 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 222 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 223 mAudioManager.getRingerMode()); 224 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 225 226 // VIBRATE_SETTING_ONLY_SILENT 227 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT); 228 assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF, 229 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 230 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 231 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 232 233 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 234 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 235 236 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 237 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 238 mAudioManager.getRingerMode()); 239 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION)); 240 241 // VIBRATE_TYPE_NOTIFICATION 242 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON); 243 assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF, 244 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 245 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF); 246 assertEquals(VIBRATE_SETTING_OFF, mAudioManager 247 .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 248 mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT); 249 assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF, 250 mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION)); 251 } finally { 252 Utils.toggleNotificationPolicyAccess( 253 mContext.getPackageName(), getInstrumentation(), false); 254 } 255 } 256 testVibrateRinger()257 public void testVibrateRinger() throws Exception { 258 if (mUseFixedVolume || !mHasVibrator) { 259 return; 260 } 261 try { 262 Utils.toggleNotificationPolicyAccess( 263 mContext.getPackageName(), getInstrumentation(), true); 264 // VIBRATE_TYPE_RINGER 265 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON); 266 assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF, 267 mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 268 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 269 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 270 271 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 272 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 273 274 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 275 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 276 mAudioManager.getRingerMode()); 277 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 278 279 // VIBRATE_SETTING_OFF 280 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF); 281 assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 282 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 283 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 284 285 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 286 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 287 288 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 289 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 290 mAudioManager.getRingerMode()); 291 // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will 292 // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to 293 // disable the vibration for incoming calls only. 294 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 295 296 // VIBRATE_SETTING_ONLY_SILENT 297 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT); 298 assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF, 299 mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 300 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 301 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 302 303 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 304 assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 305 306 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 307 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 308 mAudioManager.getRingerMode()); 309 assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER)); 310 311 // VIBRATE_TYPE_NOTIFICATION 312 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON); 313 assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF, 314 mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 315 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF); 316 assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 317 mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT); 318 assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF, 319 mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER)); 320 } finally { 321 Utils.toggleNotificationPolicyAccess( 322 mContext.getPackageName(), getInstrumentation(), false); 323 } 324 } 325 testAccessRingMode()326 public void testAccessRingMode() throws Exception { 327 try { 328 Utils.toggleNotificationPolicyAccess( 329 mContext.getPackageName(), getInstrumentation(), true); 330 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 331 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 332 333 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 334 // AudioService#setRingerMode() has: 335 // if (isTelevision) return; 336 if (mUseFixedVolume || mIsTelevision) { 337 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 338 } else { 339 assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 340 } 341 342 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 343 if (mUseFixedVolume || mIsTelevision) { 344 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 345 } else { 346 assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT, 347 mAudioManager.getRingerMode()); 348 } 349 } finally { 350 Utils.toggleNotificationPolicyAccess( 351 mContext.getPackageName(), getInstrumentation(), false); 352 } 353 } 354 testSetRingerModePolicyAccess()355 public void testSetRingerModePolicyAccess() throws Exception { 356 if (mUseFixedVolume || mIsTelevision) { 357 return; 358 } 359 try { 360 // Apps without policy access cannot change silent -> normal or silent -> vibrate. 361 Utils.toggleNotificationPolicyAccess( 362 mContext.getPackageName(), getInstrumentation(), true); 363 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 364 assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 365 Utils.toggleNotificationPolicyAccess( 366 mContext.getPackageName(), getInstrumentation(), false); 367 368 try { 369 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 370 fail("Apps without notification policy access cannot change ringer mode"); 371 } catch (SecurityException e) { 372 } 373 374 try { 375 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 376 fail("Apps without notification policy access cannot change ringer mode"); 377 } catch (SecurityException e) { 378 } 379 380 // Apps without policy access cannot change normal -> silent. 381 Utils.toggleNotificationPolicyAccess( 382 mContext.getPackageName(), getInstrumentation(), true); 383 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 384 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 385 Utils.toggleNotificationPolicyAccess( 386 mContext.getPackageName(), getInstrumentation(), false); 387 388 try { 389 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 390 fail("Apps without notification policy access cannot change ringer mode"); 391 } catch (SecurityException e) { 392 } 393 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 394 395 if (mHasVibrator) { 396 // Apps without policy access cannot change vibrate -> silent. 397 Utils.toggleNotificationPolicyAccess( 398 mContext.getPackageName(), getInstrumentation(), true); 399 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 400 assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode()); 401 Utils.toggleNotificationPolicyAccess( 402 mContext.getPackageName(), getInstrumentation(), false); 403 404 try { 405 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 406 fail("Apps without notification policy access cannot change ringer mode"); 407 } catch (SecurityException e) { 408 } 409 410 // Apps without policy access can change vibrate -> normal and vice versa. 411 assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode()); 412 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 413 assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 414 mAudioManager.setRingerMode(RINGER_MODE_VIBRATE); 415 assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode()); 416 } 417 } finally { 418 Utils.toggleNotificationPolicyAccess( 419 mContext.getPackageName(), getInstrumentation(), false); 420 } 421 } 422 testVolumeDndAffectedStream()423 public void testVolumeDndAffectedStream() throws Exception { 424 if (mUseFixedVolume || mHasVibrator) { 425 return; 426 } 427 Utils.toggleNotificationPolicyAccess( 428 mContext.getPackageName(), getInstrumentation(), true); 429 mAudioManager.setStreamVolume( 430 AudioManager.STREAM_SYSTEM, 7, AudioManager.FLAG_ALLOW_RINGER_MODES); 431 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); 432 Utils.toggleNotificationPolicyAccess( 433 mContext.getPackageName(), getInstrumentation(), false); 434 // 7 to 0, fail. 435 try { 436 mAudioManager.setStreamVolume( 437 AudioManager.STREAM_SYSTEM, 0, AudioManager.FLAG_ALLOW_RINGER_MODES); 438 fail("Apps without notification policy access cannot change ringer mode"); 439 } catch (SecurityException e) {} 440 441 // 7 to 1: success 442 mAudioManager.setStreamVolume( 443 AudioManager.STREAM_SYSTEM, 1, AudioManager.FLAG_ALLOW_RINGER_MODES); 444 assertEquals("setStreamVolume did not change volume", 445 1, mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM)); 446 447 // 0 to non-zero: fail. 448 Utils.toggleNotificationPolicyAccess( 449 mContext.getPackageName(), getInstrumentation(), true); 450 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT); 451 mAudioManager.setStreamVolume( 452 AudioManager.STREAM_SYSTEM, 0, AudioManager.FLAG_ALLOW_RINGER_MODES); 453 Utils.toggleNotificationPolicyAccess( 454 mContext.getPackageName(), getInstrumentation(), false); 455 456 try { 457 mAudioManager.setStreamVolume( 458 AudioManager.STREAM_SYSTEM, 6, AudioManager.FLAG_ALLOW_RINGER_MODES); 459 fail("Apps without notification policy access cannot change ringer mode"); 460 } catch (SecurityException e) {} 461 } 462 testVolume()463 public void testVolume() throws Exception { 464 try { 465 Utils.toggleNotificationPolicyAccess( 466 mContext.getPackageName(), getInstrumentation(), true); 467 int volume, volumeDelta; 468 int[] streams = {AudioManager.STREAM_ALARM, 469 AudioManager.STREAM_MUSIC, 470 AudioManager.STREAM_VOICE_CALL, 471 AudioManager.STREAM_RING}; 472 473 mAudioManager.adjustVolume(ADJUST_RAISE, 0); 474 mAudioManager.adjustSuggestedStreamVolume( 475 ADJUST_LOWER, USE_DEFAULT_STREAM_TYPE, 0); 476 int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC); 477 478 for (int i = 0; i < streams.length; i++) { 479 // set ringer mode to back normal to not interfere with volume tests 480 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 481 482 int maxVolume = mAudioManager.getStreamMaxVolume(streams[i]); 483 int minVolume = mAudioManager.getStreamMinVolume(streams[i]); 484 485 // validate min 486 assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0); 487 assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume, 488 maxVolume), 489 minVolume < maxVolume); 490 491 mAudioManager.setStreamVolume(streams[i], 1, 0); 492 if (mUseFixedVolume) { 493 assertEquals(maxVolume, mAudioManager.getStreamVolume(streams[i])); 494 continue; 495 } 496 assertEquals(1, mAudioManager.getStreamVolume(streams[i])); 497 498 if (streams[i] == AudioManager.STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) { 499 // due to new regulations, music sent over a wired headset may be volume limited 500 // until the user explicitly increases the limit, so we can't rely on being able 501 // to set the volume to getStreamMaxVolume(). Instead, determine the current limit 502 // by increasing the volume until it won't go any higher, then use that volume as 503 // the maximum for the purposes of this test 504 int curvol = 0; 505 int prevvol = 0; 506 do { 507 prevvol = curvol; 508 mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, 0); 509 curvol = mAudioManager.getStreamVolume(streams[i]); 510 } while (curvol != prevvol); 511 maxVolume = maxMusicVolume = curvol; 512 } 513 mAudioManager.setStreamVolume(streams[i], maxVolume, 0); 514 mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, 0); 515 assertEquals(maxVolume, mAudioManager.getStreamVolume(streams[i])); 516 517 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(streams[i])); 518 mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, streams[i], 0); 519 assertEquals(maxVolume - volumeDelta, mAudioManager.getStreamVolume(streams[i])); 520 521 // volume lower 522 mAudioManager.setStreamVolume(streams[i], maxVolume, 0); 523 volume = mAudioManager.getStreamVolume(streams[i]); 524 while (volume > minVolume) { 525 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(streams[i])); 526 mAudioManager.adjustStreamVolume(streams[i], ADJUST_LOWER, 0); 527 assertEquals(Math.max(0, volume - volumeDelta), 528 mAudioManager.getStreamVolume(streams[i])); 529 volume = mAudioManager.getStreamVolume(streams[i]); 530 } 531 532 mAudioManager.adjustStreamVolume(streams[i], ADJUST_SAME, 0); 533 534 // volume raise 535 mAudioManager.setStreamVolume(streams[i], 1, 0); 536 volume = mAudioManager.getStreamVolume(streams[i]); 537 while (volume < maxVolume) { 538 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(streams[i])); 539 mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, 0); 540 assertEquals(Math.min(volume + volumeDelta, maxVolume), 541 mAudioManager.getStreamVolume(streams[i])); 542 volume = mAudioManager.getStreamVolume(streams[i]); 543 } 544 545 // volume same 546 mAudioManager.setStreamVolume(streams[i], maxVolume, 0); 547 for (int k = 0; k < maxVolume; k++) { 548 mAudioManager.adjustStreamVolume(streams[i], ADJUST_SAME, 0); 549 assertEquals(maxVolume, mAudioManager.getStreamVolume(streams[i])); 550 } 551 552 mAudioManager.setStreamVolume(streams[i], maxVolume, 0); 553 } 554 555 if (mUseFixedVolume) { 556 return; 557 } 558 559 // adjust volume 560 mAudioManager.adjustVolume(ADJUST_RAISE, 0); 561 562 MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY); 563 assertNotNull(mp); 564 mp.setAudioStreamType(STREAM_MUSIC); 565 mp.setLooping(true); 566 mp.start(); 567 Thread.sleep(TIME_TO_PLAY); 568 assertTrue(mAudioManager.isMusicActive()); 569 570 // adjust volume as ADJUST_SAME 571 for (int k = 0; k < maxMusicVolume; k++) { 572 mAudioManager.adjustVolume(ADJUST_SAME, 0); 573 assertEquals(maxMusicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC)); 574 } 575 576 // adjust volume as ADJUST_RAISE 577 mAudioManager.setStreamVolume(STREAM_MUSIC, 0, 0); 578 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC)); 579 mAudioManager.adjustVolume(ADJUST_RAISE, 0); 580 assertEquals(Math.min(volumeDelta, maxMusicVolume), 581 mAudioManager.getStreamVolume(STREAM_MUSIC)); 582 583 // adjust volume as ADJUST_LOWER 584 mAudioManager.setStreamVolume(STREAM_MUSIC, maxMusicVolume, 0); 585 maxMusicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC); 586 volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC)); 587 mAudioManager.adjustVolume(ADJUST_LOWER, 0); 588 assertEquals(Math.max(0, maxMusicVolume - volumeDelta), 589 mAudioManager.getStreamVolume(STREAM_MUSIC)); 590 591 mp.stop(); 592 mp.release(); 593 Thread.sleep(TIME_TO_PLAY); 594 assertFalse(mAudioManager.isMusicActive()); 595 } finally { 596 Utils.toggleNotificationPolicyAccess( 597 mContext.getPackageName(), getInstrumentation(), false); 598 } 599 } 600 testMuteFixedVolume()601 public void testMuteFixedVolume() throws Exception { 602 int[] streams = { 603 AudioManager.STREAM_VOICE_CALL, 604 AudioManager.STREAM_MUSIC, 605 AudioManager.STREAM_RING, 606 AudioManager.STREAM_ALARM, 607 AudioManager.STREAM_NOTIFICATION, 608 AudioManager.STREAM_SYSTEM}; 609 if (mUseFixedVolume) { 610 for (int i = 0; i < streams.length; i++) { 611 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0); 612 assertFalse("Muting should not affect a fixed volume device.", 613 mAudioManager.isStreamMute(streams[i])); 614 615 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0); 616 assertFalse("Toggling mute should not affect a fixed volume device.", 617 mAudioManager.isStreamMute(streams[i])); 618 619 mAudioManager.setStreamMute(streams[i], true); 620 assertFalse("Muting should not affect a fixed volume device.", 621 mAudioManager.isStreamMute(streams[i])); 622 } 623 } 624 } 625 testMuteDndAffectedStreams()626 public void testMuteDndAffectedStreams() throws Exception { 627 if (mUseFixedVolume) { 628 return; 629 } 630 int[] streams = { AudioManager.STREAM_RING }; 631 try { 632 // Mute streams 633 Utils.toggleNotificationPolicyAccess( 634 mContext.getPackageName(), getInstrumentation(), true); 635 mAudioManager.setRingerMode(RINGER_MODE_SILENT); 636 Utils.toggleNotificationPolicyAccess( 637 mContext.getPackageName(), getInstrumentation(), false); 638 // Verify streams cannot be unmuted without policy access. 639 for (int i = 0; i < streams.length; i++) { 640 try { 641 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_UNMUTE, 0); 642 assertEquals("Apps without Notification policy access can't change ringer mode", 643 RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 644 } catch (SecurityException e) { 645 } 646 647 try { 648 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 649 0); 650 assertEquals("Apps without Notification policy access can't change ringer mode", 651 RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 652 } catch (SecurityException e) { 653 } 654 655 try { 656 mAudioManager.setStreamMute(streams[i], false); 657 assertEquals("Apps without Notification policy access can't change ringer mode", 658 RINGER_MODE_SILENT, mAudioManager.getRingerMode()); 659 } catch (SecurityException e) { 660 } 661 } 662 663 // This ensures we're out of vibrate or silent modes. 664 Utils.toggleNotificationPolicyAccess( 665 mContext.getPackageName(), getInstrumentation(), true); 666 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 667 for (int i = 0; i < streams.length; i++) { 668 // ensure each stream is on and turned up. 669 mAudioManager.setStreamVolume(streams[i], 670 mAudioManager.getStreamMaxVolume(streams[i]), 671 0); 672 673 Utils.toggleNotificationPolicyAccess( 674 mContext.getPackageName(), getInstrumentation(), false); 675 try { 676 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0); 677 assertEquals("Apps without Notification policy access can't change ringer mode", 678 RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 679 } catch (SecurityException e) { 680 } 681 try { 682 mAudioManager.adjustStreamVolume( 683 streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0); 684 assertEquals("Apps without Notification policy access can't change ringer mode", 685 RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 686 } catch (SecurityException e) { 687 } 688 689 try { 690 mAudioManager.setStreamMute(streams[i], true); 691 assertEquals("Apps without Notification policy access can't change ringer mode", 692 RINGER_MODE_NORMAL, mAudioManager.getRingerMode()); 693 } catch (SecurityException e) { 694 } 695 Utils.toggleNotificationPolicyAccess( 696 mContext.getPackageName(), getInstrumentation(), true); 697 testStreamMuting(streams[i]); 698 } 699 } finally { 700 Utils.toggleNotificationPolicyAccess( 701 mContext.getPackageName(), getInstrumentation(), false); 702 } 703 } 704 testMuteDndUnaffectedStreams()705 public void testMuteDndUnaffectedStreams() throws Exception { 706 if (mUseFixedVolume) { 707 return; 708 } 709 int[] streams = { 710 AudioManager.STREAM_VOICE_CALL, 711 AudioManager.STREAM_MUSIC, 712 AudioManager.STREAM_ALARM 713 }; 714 715 try { 716 int muteAffectedStreams = System.getInt(mContext.getContentResolver(), 717 System.MUTE_STREAMS_AFFECTED, 718 // Same defaults as in AudioService. Should be kept in 719 // sync. 720 ((1 << AudioManager.STREAM_MUSIC) | 721 (1 << AudioManager.STREAM_RING) | 722 (1 << AudioManager.STREAM_NOTIFICATION) | 723 (1 << AudioManager.STREAM_SYSTEM))); 724 Utils.toggleNotificationPolicyAccess( 725 mContext.getPackageName(), getInstrumentation(), true); 726 // This ensures we're out of vibrate or silent modes. 727 mAudioManager.setRingerMode(RINGER_MODE_NORMAL); 728 Utils.toggleNotificationPolicyAccess( 729 mContext.getPackageName(), getInstrumentation(), false); 730 for (int i = 0; i < streams.length; i++) { 731 // ensure each stream is on and turned up. 732 mAudioManager.setStreamVolume(streams[i], 733 mAudioManager.getStreamMaxVolume(streams[i]), 734 0); 735 if (((1 << streams[i]) & muteAffectedStreams) == 0) { 736 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0); 737 assertFalse("Stream " + streams[i] + " should not be affected by mute.", 738 mAudioManager.isStreamMute(streams[i])); 739 mAudioManager.setStreamMute(streams[i], true); 740 assertFalse("Stream " + streams[i] + " should not be affected by mute.", 741 mAudioManager.isStreamMute(streams[i])); 742 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 743 0); 744 assertFalse("Stream " + streams[i] + " should not be affected by mute.", 745 mAudioManager.isStreamMute(streams[i])); 746 continue; 747 } 748 testStreamMuting(streams[i]); 749 } 750 } finally { 751 Utils.toggleNotificationPolicyAccess( 752 mContext.getPackageName(), getInstrumentation(), false); 753 } 754 } 755 testStreamMuting(int stream)756 private void testStreamMuting(int stream) { 757 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0); 758 assertTrue("Muting stream " + stream + " failed.", 759 mAudioManager.isStreamMute(stream)); 760 761 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0); 762 assertFalse("Unmuting stream " + stream + " failed.", 763 mAudioManager.isStreamMute(stream)); 764 765 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0); 766 assertTrue("Toggling mute on stream " + stream + " failed.", 767 mAudioManager.isStreamMute(stream)); 768 769 mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE, 0); 770 assertFalse("Toggling mute on stream " + stream + " failed.", 771 mAudioManager.isStreamMute(stream)); 772 773 mAudioManager.setStreamMute(stream, true); 774 assertTrue("Muting stream " + stream + " using setStreamMute failed", 775 mAudioManager.isStreamMute(stream)); 776 777 // mute it three more times to verify the ref counting is gone. 778 mAudioManager.setStreamMute(stream, true); 779 mAudioManager.setStreamMute(stream, true); 780 mAudioManager.setStreamMute(stream, true); 781 782 mAudioManager.setStreamMute(stream, false); 783 assertFalse("Unmuting stream " + stream + " using setStreamMute failed.", 784 mAudioManager.isStreamMute(stream)); 785 } 786 testSetInvalidRingerMode()787 public void testSetInvalidRingerMode() { 788 int ringerMode = mAudioManager.getRingerMode(); 789 mAudioManager.setRingerMode(-1337); 790 assertEquals(ringerMode, mAudioManager.getRingerMode()); 791 792 mAudioManager.setRingerMode(-3007); 793 assertEquals(ringerMode, mAudioManager.getRingerMode()); 794 } 795 testAdjustVolumeInTotalSilenceMode()796 public void testAdjustVolumeInTotalSilenceMode() throws Exception { 797 if (mUseFixedVolume || mIsTelevision) { 798 return; 799 } 800 try { 801 Utils.toggleNotificationPolicyAccess( 802 mContext.getPackageName(), getInstrumentation(), true); 803 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0); 804 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE); 805 806 int musicVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 807 mAudioManager.adjustStreamVolume( 808 AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0); 809 assertEquals(musicVolume, mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)); 810 811 } finally { 812 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL); 813 Utils.toggleNotificationPolicyAccess( 814 mContext.getPackageName(), getInstrumentation(), false); 815 } 816 } 817 testAdjustVolumeInAlarmsOnlyMode()818 public void testAdjustVolumeInAlarmsOnlyMode() throws Exception { 819 if (mUseFixedVolume || mIsTelevision) { 820 return; 821 } 822 try { 823 Utils.toggleNotificationPolicyAccess( 824 mContext.getPackageName(), getInstrumentation(), true); 825 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0); 826 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS); 827 828 int musicVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 829 mAudioManager.adjustStreamVolume( 830 AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0); 831 int volumeDelta = 832 getVolumeDelta(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)); 833 assertEquals(musicVolume + volumeDelta, 834 mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)); 835 836 } finally { 837 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL); 838 Utils.toggleNotificationPolicyAccess( 839 mContext.getPackageName(), getInstrumentation(), false); 840 } 841 } 842 testSetStreamVolumeInTotalSilenceMode()843 public void testSetStreamVolumeInTotalSilenceMode() throws Exception { 844 if (mUseFixedVolume || mIsTelevision) { 845 return; 846 } 847 try { 848 Utils.toggleNotificationPolicyAccess( 849 mContext.getPackageName(), getInstrumentation(), true); 850 mAudioManager.setStreamVolume(AudioManager.STREAM_RING, 1, 0); 851 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0); 852 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE); 853 854 int musicVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 855 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 7, 0); 856 assertEquals(musicVolume, mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)); 857 858 mAudioManager.setStreamVolume(AudioManager.STREAM_RING, 7, 0); 859 assertEquals(7, mAudioManager.getStreamVolume(AudioManager.STREAM_RING)); 860 } finally { 861 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL); 862 Utils.toggleNotificationPolicyAccess( 863 mContext.getPackageName(), getInstrumentation(), false); 864 } 865 } 866 testSetStreamVolumeInAlarmsOnlyMode()867 public void testSetStreamVolumeInAlarmsOnlyMode() throws Exception { 868 if (mUseFixedVolume || mIsTelevision) { 869 return; 870 } 871 try { 872 Utils.toggleNotificationPolicyAccess( 873 mContext.getPackageName(), getInstrumentation(), true); 874 mAudioManager.setStreamVolume(AudioManager.STREAM_RING, 1, 0); 875 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0); 876 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS); 877 878 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 3, 0); 879 assertEquals(3, mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)); 880 881 mAudioManager.setStreamVolume(AudioManager.STREAM_RING, 7, 0); 882 assertEquals(7, mAudioManager.getStreamVolume(AudioManager.STREAM_RING)); 883 } finally { 884 setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL); 885 Utils.toggleNotificationPolicyAccess( 886 mContext.getPackageName(), getInstrumentation(), false); 887 } 888 } 889 setInterruptionFilter(int filter)890 private void setInterruptionFilter(int filter) throws Exception { 891 mNm.setInterruptionFilter(filter); 892 for (int i = 0; i < 5; i++) { 893 if (mNm.getCurrentInterruptionFilter() == filter) { 894 break; 895 } 896 Thread.sleep(1000); 897 } 898 } 899 getVolumeDelta(int volume)900 private int getVolumeDelta(int volume) { 901 return 1; 902 } 903 904 } 905