1 /* 2 * Copyright 2019 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.tv.tuner.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotEquals; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assert.fail; 26 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.ServiceConnection; 31 import android.content.pm.PackageManager; 32 import android.media.tv.tuner.DemuxCapabilities; 33 import android.media.tv.tuner.Descrambler; 34 import android.media.tv.tuner.Lnb; 35 import android.media.tv.tuner.LnbCallback; 36 import android.media.tv.tuner.Tuner; 37 import android.media.tv.tuner.TunerVersionChecker; 38 import android.media.tv.tuner.dvr.DvrPlayback; 39 import android.media.tv.tuner.dvr.DvrRecorder; 40 import android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener; 41 import android.media.tv.tuner.dvr.OnRecordStatusChangedListener; 42 import android.media.tv.tuner.filter.AlpFilterConfiguration; 43 import android.media.tv.tuner.filter.AudioDescriptor; 44 import android.media.tv.tuner.filter.AvSettings; 45 import android.media.tv.tuner.filter.DownloadEvent; 46 import android.media.tv.tuner.filter.DownloadSettings; 47 import android.media.tv.tuner.filter.Filter; 48 import android.media.tv.tuner.filter.FilterCallback; 49 import android.media.tv.tuner.filter.FilterConfiguration; 50 import android.media.tv.tuner.filter.FilterEvent; 51 import android.media.tv.tuner.filter.IpCidChangeEvent; 52 import android.media.tv.tuner.filter.IpFilterConfiguration; 53 import android.media.tv.tuner.filter.IpPayloadEvent; 54 import android.media.tv.tuner.filter.MediaEvent; 55 import android.media.tv.tuner.filter.MmtpFilterConfiguration; 56 import android.media.tv.tuner.filter.MmtpRecordEvent; 57 import android.media.tv.tuner.filter.PesEvent; 58 import android.media.tv.tuner.filter.PesSettings; 59 import android.media.tv.tuner.filter.RecordSettings; 60 import android.media.tv.tuner.filter.RestartEvent; 61 import android.media.tv.tuner.filter.ScramblingStatusEvent; 62 import android.media.tv.tuner.filter.SectionEvent; 63 import android.media.tv.tuner.filter.SectionSettingsWithSectionBits; 64 import android.media.tv.tuner.filter.SectionSettingsWithTableInfo; 65 import android.media.tv.tuner.filter.Settings; 66 import android.media.tv.tuner.filter.SharedFilter; 67 import android.media.tv.tuner.filter.SharedFilterCallback; 68 import android.media.tv.tuner.filter.TemiEvent; 69 import android.media.tv.tuner.filter.TimeFilter; 70 import android.media.tv.tuner.filter.TlvFilterConfiguration; 71 import android.media.tv.tuner.filter.TsFilterConfiguration; 72 import android.media.tv.tuner.filter.TsRecordEvent; 73 import android.media.tv.tuner.frontend.AnalogFrontendCapabilities; 74 import android.media.tv.tuner.frontend.AnalogFrontendSettings; 75 import android.media.tv.tuner.frontend.Atsc3FrontendCapabilities; 76 import android.media.tv.tuner.frontend.Atsc3FrontendSettings; 77 import android.media.tv.tuner.frontend.Atsc3PlpInfo; 78 import android.media.tv.tuner.frontend.AtscFrontendCapabilities; 79 import android.media.tv.tuner.frontend.AtscFrontendSettings; 80 import android.media.tv.tuner.frontend.DtmbFrontendCapabilities; 81 import android.media.tv.tuner.frontend.DtmbFrontendSettings; 82 import android.media.tv.tuner.frontend.DvbcFrontendCapabilities; 83 import android.media.tv.tuner.frontend.DvbcFrontendSettings; 84 import android.media.tv.tuner.frontend.DvbsFrontendCapabilities; 85 import android.media.tv.tuner.frontend.DvbsFrontendSettings; 86 import android.media.tv.tuner.frontend.DvbtFrontendCapabilities; 87 import android.media.tv.tuner.frontend.DvbtFrontendSettings; 88 import android.media.tv.tuner.frontend.FrontendCapabilities; 89 import android.media.tv.tuner.frontend.FrontendInfo; 90 import android.media.tv.tuner.frontend.FrontendSettings; 91 import android.media.tv.tuner.frontend.FrontendStatus; 92 import android.media.tv.tuner.frontend.FrontendStatus.Atsc3PlpTuningInfo; 93 import android.media.tv.tuner.frontend.FrontendStatusReadiness; 94 import android.media.tv.tuner.frontend.Isdbs3FrontendCapabilities; 95 import android.media.tv.tuner.frontend.Isdbs3FrontendSettings; 96 import android.media.tv.tuner.frontend.IsdbsFrontendCapabilities; 97 import android.media.tv.tuner.frontend.IsdbsFrontendSettings; 98 import android.media.tv.tuner.frontend.IsdbtFrontendCapabilities; 99 import android.media.tv.tuner.frontend.IsdbtFrontendSettings; 100 import android.media.tv.tuner.frontend.OnTuneEventListener; 101 import android.media.tv.tuner.frontend.ScanCallback; 102 import android.media.tv.tunerresourcemanager.TunerFrontendInfo; 103 import android.media.tv.tunerresourcemanager.TunerFrontendRequest; 104 import android.media.tv.tunerresourcemanager.TunerResourceManager; 105 import android.os.ConditionVariable; 106 import android.os.Handler; 107 import android.os.IBinder; 108 import android.os.Looper; 109 import android.os.Message; 110 111 import androidx.test.InstrumentationRegistry; 112 import androidx.test.filters.SmallTest; 113 import androidx.test.runner.AndroidJUnit4; 114 115 import com.android.compatibility.common.util.RequiredFeatureRule; 116 117 import org.junit.After; 118 import org.junit.Before; 119 import org.junit.Rule; 120 import org.junit.Test; 121 import org.junit.runner.RunWith; 122 123 import java.time.Duration; 124 import java.time.Instant; 125 import java.util.List; 126 import java.util.concurrent.BlockingQueue; 127 import java.util.concurrent.CountDownLatch; 128 import java.util.concurrent.Executor; 129 import java.util.concurrent.LinkedBlockingQueue; 130 import java.util.concurrent.TimeUnit; 131 import java.util.concurrent.locks.ReentrantLock; 132 133 @RunWith(AndroidJUnit4.class) 134 @SmallTest 135 public class TunerTest { 136 private static final String TAG = "MediaTunerTest"; 137 138 @Rule 139 public RequiredFeatureRule featureRule = new RequiredFeatureRule( 140 PackageManager.FEATURE_TUNER); 141 142 private static final int TIMEOUT_MS = 10 * 1000; // 10 seconds 143 private static final int SCAN_TIMEOUT_MS = 2 * 60 * 1000; // 2 minutes 144 private static final long TIMEOUT_BINDER_SERVICE_SEC = 2; 145 146 private Context mContext; 147 private Tuner mTuner; 148 private CountDownLatch mLockLatch = new CountDownLatch(1); 149 private TunerResourceManager mTunerResourceManager = null; 150 private TestServiceConnection mConnection; 151 private ISharedFilterTestServer mSharedFilterTestServer; 152 153 private class TestServiceConnection implements ServiceConnection { 154 private BlockingQueue<IBinder> mBlockingQueue = new LinkedBlockingQueue<>(); 155 onServiceConnected(ComponentName componentName, IBinder service)156 public void onServiceConnected(ComponentName componentName, IBinder service) { 157 mBlockingQueue.offer(service); 158 } 159 onServiceDisconnected(ComponentName componentName)160 public void onServiceDisconnected(ComponentName componentName) {} 161 getService()162 public IBinder getService() throws Exception { 163 final IBinder service = 164 mBlockingQueue.poll(TIMEOUT_BINDER_SERVICE_SEC, TimeUnit.SECONDS); 165 return service; 166 } 167 } 168 169 private class TunerResourceTestServiceConnection implements ServiceConnection { 170 private BlockingQueue<IBinder> mBlockingQueue = new LinkedBlockingQueue<>(); 171 172 @Override onServiceConnected(ComponentName componentName, IBinder service)173 public void onServiceConnected(ComponentName componentName, IBinder service) { 174 mBlockingQueue.offer(service); 175 } 176 177 @Override onServiceDisconnected(ComponentName componentName)178 public void onServiceDisconnected(ComponentName componentName){} 179 getService()180 public ITunerResourceTestServer getService() throws Exception { 181 final IBinder service = 182 mBlockingQueue.poll(TIMEOUT_BINDER_SERVICE_SEC, TimeUnit.SECONDS); 183 return ITunerResourceTestServer.Stub.asInterface(service); 184 } 185 } 186 187 private class TunerTestOnTuneEventListener implements OnTuneEventListener { 188 public static final int INVALID_TUNE_EVENT = -1; 189 private static final int SLEEP_TIME_MS = 100; 190 private static final int TIMEOUT_MS = 500; 191 private final ReentrantLock mLock = new ReentrantLock(); 192 private final ConditionVariable mCV = new ConditionVariable(); 193 private int mLastTuneEvent = INVALID_TUNE_EVENT; 194 195 @Override onTuneEvent(int tuneEvent)196 public void onTuneEvent(int tuneEvent) { 197 synchronized (mLock) { 198 mLastTuneEvent = tuneEvent; 199 mCV.open(); 200 } 201 } 202 resetLastTuneEvent()203 public void resetLastTuneEvent() { 204 synchronized (mLock) { 205 mLastTuneEvent = INVALID_TUNE_EVENT; 206 } 207 } 208 getLastTuneEvent()209 public int getLastTuneEvent() { 210 try { 211 // yield to let the callback handling execute 212 Thread.sleep(SLEEP_TIME_MS); 213 } catch (Exception e) { 214 // ignore exception 215 } 216 synchronized (mLock) { 217 mCV.block(TIMEOUT_MS); 218 mCV.close(); 219 return mLastTuneEvent; 220 } 221 } 222 } 223 224 private class TunerTestLnbCallback implements LnbCallback { 225 public static final int INVALID_LNB_EVENT = -1; 226 private static final int SLEEP_TIME_MS = 100; 227 private static final int TIMEOUT_MS = 500; 228 private final ReentrantLock mDMLock = new ReentrantLock(); 229 private final ConditionVariable mDMCV = new ConditionVariable(); 230 private boolean mOnDiseqcMessageCalled = false; 231 232 // will not test this as there is no good way to trigger this 233 @Override onEvent(int lnbEventType)234 public void onEvent(int lnbEventType) {} 235 236 // will test this instead 237 @Override onDiseqcMessage(byte[] diseqcMessage)238 public void onDiseqcMessage(byte[] diseqcMessage) { 239 synchronized (mDMLock) { 240 mOnDiseqcMessageCalled = true; 241 mDMCV.open(); 242 } 243 } 244 resetOnDiseqcMessageCalled()245 public void resetOnDiseqcMessageCalled() { 246 synchronized (mDMLock) { 247 mOnDiseqcMessageCalled = false; 248 } 249 } 250 getOnDiseqcMessageCalled()251 public boolean getOnDiseqcMessageCalled() { 252 try { 253 // yield to let the callback handling execute 254 Thread.sleep(SLEEP_TIME_MS); 255 } catch (Exception e) { 256 // ignore exception 257 } 258 259 synchronized (mDMLock) { 260 mDMCV.block(TIMEOUT_MS); 261 mDMCV.close(); 262 return mOnDiseqcMessageCalled; 263 } 264 } 265 } 266 267 @Before setUp()268 public void setUp() throws Exception { 269 mContext = InstrumentationRegistry.getTargetContext(); 270 InstrumentationRegistry 271 .getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(); 272 mTuner = new Tuner(mContext, null, 100); 273 } 274 275 @After tearDown()276 public void tearDown() { 277 if (mTuner != null) { 278 mTuner.close(); 279 mTuner = null; 280 } 281 } 282 283 @Test testTunerConstructor()284 public void testTunerConstructor() throws Exception { 285 assertNotNull(mTuner); 286 } 287 288 @Test testTunerVersion()289 public void testTunerVersion() { 290 assertNotNull(mTuner); 291 int version = TunerVersionChecker.getTunerVersion(); 292 assertTrue(version >= TunerVersionChecker.TUNER_VERSION_1_0); 293 assertTrue(version <= TunerVersionChecker.TUNER_VERSION_2_0); 294 } 295 296 @Test testFrontendHardwareInfo()297 public void testFrontendHardwareInfo() throws Exception { 298 String hwInfo = null; 299 try { 300 hwInfo = mTuner.getCurrentFrontendHardwareInfo(); 301 if (TunerVersionChecker.isHigherOrEqualVersionTo( 302 TunerVersionChecker.TUNER_VERSION_2_0)) { 303 fail("Get Frontend hardware info should throw IllegalStateException."); 304 } else { 305 assertNull(hwInfo); 306 } 307 } catch (IllegalStateException e) { 308 // pass 309 } 310 311 List<Integer> ids = mTuner.getFrontendIds(); 312 if (ids == null) return; 313 assertFalse(ids.isEmpty()); 314 315 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 316 int res = mTuner.tune(createFrontendSettings(info)); 317 hwInfo = mTuner.getCurrentFrontendHardwareInfo(); 318 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) { 319 assertNotNull(hwInfo); 320 assertFalse(hwInfo.isEmpty()); 321 } else { 322 assertNull(hwInfo); 323 } 324 res = mTuner.cancelTuning(); 325 assertEquals(Tuner.RESULT_SUCCESS, res); 326 } 327 328 @Test testTuning()329 public void testTuning() throws Exception { 330 List<Integer> ids = mTuner.getFrontendIds(); 331 if (ids == null) return; 332 assertFalse(ids.isEmpty()); 333 334 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 335 int res = mTuner.tune(createFrontendSettings(info)); 336 assertEquals(Tuner.RESULT_SUCCESS, res); 337 res = mTuner.setLnaEnabled(false); 338 assertTrue((res == Tuner.RESULT_SUCCESS) || (res == Tuner.RESULT_UNAVAILABLE)); 339 res = mTuner.cancelTuning(); 340 assertEquals(Tuner.RESULT_SUCCESS, res); 341 } 342 343 @Test testMultiTuning()344 public void testMultiTuning() throws Exception { 345 List<Integer> ids = mTuner.getFrontendIds(); 346 if (ids == null) return; 347 assertFalse(ids.isEmpty()); 348 349 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 350 int res = mTuner.tune(createFrontendSettings(info)); 351 assertEquals(Tuner.RESULT_SUCCESS, res); 352 res = mTuner.cancelTuning(); 353 assertEquals(Tuner.RESULT_SUCCESS, res); 354 355 // Tune again with the same frontend. 356 mTuner.tune(createFrontendSettings(info)); 357 assertEquals(Tuner.RESULT_SUCCESS, res); 358 res = mTuner.cancelTuning(); 359 assertEquals(Tuner.RESULT_SUCCESS, res); 360 361 for (int i = 1; i < ids.size(); i++) { 362 FrontendInfo info2 = mTuner.getFrontendInfoById(ids.get(i)); 363 if (info2.getType() != info.getType()) { 364 res = mTuner.tune(createFrontendSettings(info2)); 365 assertEquals(Tuner.RESULT_INVALID_STATE, res); 366 } 367 } 368 } 369 370 @Test testScanning()371 public void testScanning() throws Exception { 372 // Use the same test approach as testTune since it is not possible to test all frontends on 373 // one signal source 374 List<Integer> ids = mTuner.getFrontendIds(); 375 if (ids == null) return; 376 assertFalse(ids.isEmpty()); 377 378 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 379 int res = mTuner.scan( 380 createFrontendSettings(info), 381 Tuner.SCAN_TYPE_AUTO, 382 getExecutor(), 383 getScanCallback()); 384 assertEquals(Tuner.RESULT_SUCCESS, res); 385 res = mTuner.cancelScanning(); 386 assertEquals(Tuner.RESULT_SUCCESS, res); 387 } 388 389 @Test testFrontendStatus()390 public void testFrontendStatus() throws Exception { 391 List<Integer> ids = mTuner.getFrontendIds(); 392 if (ids == null) return; 393 assertFalse(ids.isEmpty()); 394 395 for (int id : ids) { 396 Tuner tuner = new Tuner(mContext, null, 100); 397 FrontendInfo info = tuner.getFrontendInfoById(id); 398 int res = tuner.tune(createFrontendSettings(info)); 399 400 int[] statusCapabilities = info.getStatusCapabilities(); 401 assertNotNull(statusCapabilities); 402 FrontendStatus status = tuner.getFrontendStatus(statusCapabilities); 403 assertNotNull(status); 404 405 for (int i = 0; i < statusCapabilities.length; i++) { 406 switch (statusCapabilities[i]) { 407 case FrontendStatus.FRONTEND_STATUS_TYPE_DEMOD_LOCK: 408 status.isDemodLocked(); 409 break; 410 case FrontendStatus.FRONTEND_STATUS_TYPE_SNR: 411 status.getSnr(); 412 break; 413 case FrontendStatus.FRONTEND_STATUS_TYPE_BER: 414 status.getBer(); 415 break; 416 case FrontendStatus.FRONTEND_STATUS_TYPE_PER: 417 status.getPer(); 418 break; 419 case FrontendStatus.FRONTEND_STATUS_TYPE_PRE_BER: 420 status.getPerBer(); 421 break; 422 case FrontendStatus.FRONTEND_STATUS_TYPE_SIGNAL_QUALITY: 423 status.getSignalQuality(); 424 break; 425 case FrontendStatus.FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH: 426 status.getSignalStrength(); 427 break; 428 case FrontendStatus.FRONTEND_STATUS_TYPE_SYMBOL_RATE: 429 status.getSymbolRate(); 430 break; 431 case FrontendStatus.FRONTEND_STATUS_TYPE_FEC: 432 status.getInnerFec(); 433 break; 434 case FrontendStatus.FRONTEND_STATUS_TYPE_MODULATION: 435 if (info.getType() != FrontendSettings.TYPE_DVBT) 436 status.getModulation(); 437 break; 438 case FrontendStatus.FRONTEND_STATUS_TYPE_SPECTRAL: 439 status.getSpectralInversion(); 440 break; 441 case FrontendStatus.FRONTEND_STATUS_TYPE_LNB_VOLTAGE: 442 status.getLnbVoltage(); 443 break; 444 case FrontendStatus.FRONTEND_STATUS_TYPE_PLP_ID: 445 status.getPlpId(); 446 break; 447 case FrontendStatus.FRONTEND_STATUS_TYPE_EWBS: 448 status.isEwbs(); 449 break; 450 case FrontendStatus.FRONTEND_STATUS_TYPE_AGC: 451 status.getAgc(); 452 break; 453 case FrontendStatus.FRONTEND_STATUS_TYPE_LNA: 454 status.isLnaOn(); 455 break; 456 case FrontendStatus.FRONTEND_STATUS_TYPE_LAYER_ERROR: 457 boolean[] r = status.getLayerErrors(); 458 assertNotNull(r); 459 break; 460 case FrontendStatus.FRONTEND_STATUS_TYPE_MER: 461 status.getMer(); 462 break; 463 case FrontendStatus.FRONTEND_STATUS_TYPE_FREQ_OFFSET: 464 status.getFreqOffsetLong(); 465 status.getFreqOffset(); 466 break; 467 case FrontendStatus.FRONTEND_STATUS_TYPE_HIERARCHY: 468 status.getHierarchy(); 469 break; 470 case FrontendStatus.FRONTEND_STATUS_TYPE_RF_LOCK: 471 status.isRfLocked(); 472 break; 473 case FrontendStatus.FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO: 474 Atsc3PlpTuningInfo[] tuningInfos = status.getAtsc3PlpTuningInfo(); 475 if (tuningInfos != null) { 476 for (Atsc3PlpTuningInfo tuningInfo : tuningInfos) { 477 tuningInfo.getPlpId(); 478 tuningInfo.isLocked(); 479 tuningInfo.getUec(); 480 } 481 } 482 break; 483 case FrontendStatus.FRONTEND_STATUS_TYPE_BERS: 484 int[] b = status.getBers(); 485 assertNotNull(b); 486 break; 487 case FrontendStatus.FRONTEND_STATUS_TYPE_CODERATES: 488 int[] c = status.getCodeRates(); 489 assertNotNull(c); 490 break; 491 case FrontendStatus.FRONTEND_STATUS_TYPE_BANDWIDTH: 492 status.getBandwidth(); 493 break; 494 case FrontendStatus.FRONTEND_STATUS_TYPE_GUARD_INTERVAL: 495 status.getGuardInterval(); 496 break; 497 case FrontendStatus.FRONTEND_STATUS_TYPE_TRANSMISSION_MODE: 498 status.getTransmissionMode(); 499 break; 500 case FrontendStatus.FRONTEND_STATUS_TYPE_UEC: 501 status.getUec(); 502 break; 503 case FrontendStatus.FRONTEND_STATUS_TYPE_T2_SYSTEM_ID: 504 status.getSystemId(); 505 break; 506 case FrontendStatus.FRONTEND_STATUS_TYPE_INTERLEAVINGS: 507 int[] l = status.getInterleaving(); 508 assertNotNull(l); 509 break; 510 case FrontendStatus.FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS: 511 int[] segment = status.getIsdbtSegment(); 512 assertNotNull(segment); 513 break; 514 case FrontendStatus.FRONTEND_STATUS_TYPE_TS_DATA_RATES: 515 int[] rates = status.getTsDataRate(); 516 assertNotNull(rates); 517 break; 518 case FrontendStatus.FRONTEND_STATUS_TYPE_MODULATIONS_EXT: 519 int[] modulations = status.getExtendedModulations(); 520 assertNotNull(modulations); 521 break; 522 case FrontendStatus.FRONTEND_STATUS_TYPE_ROLL_OFF: 523 status.getRollOff(); 524 break; 525 case FrontendStatus.FRONTEND_STATUS_TYPE_IS_MISO_ENABLED: 526 status.isMisoEnabled(); 527 break; 528 case FrontendStatus.FRONTEND_STATUS_TYPE_IS_LINEAR: 529 status.isLinear(); 530 break; 531 case FrontendStatus.FRONTEND_STATUS_TYPE_IS_SHORT_FRAMES_ENABLED: 532 status.isShortFramesEnabled(); 533 break; 534 case FrontendStatus.FRONTEND_STATUS_TYPE_ISDBT_MODE: 535 status.getIsdbtMode(); 536 break; 537 case FrontendStatus.FRONTEND_STATUS_TYPE_ISDBT_PARTIAL_RECEPTION_FLAG: 538 status.getIsdbtPartialReceptionFlag(); 539 break; 540 case FrontendStatus.FRONTEND_STATUS_TYPE_STREAM_IDS: 541 int[] streamIds = status.getStreamIds(); 542 assertNotNull(streamIds); 543 break; 544 case FrontendStatus.FRONTEND_STATUS_TYPE_DVBT_CELL_IDS: 545 int[] cellIds = status.getDvbtCellIds(); 546 assertNotNull(cellIds); 547 break; 548 case FrontendStatus.FRONTEND_STATUS_TYPE_ATSC3_ALL_PLP_INFO: 549 List<Atsc3PlpInfo> plps = status.getAllAtsc3PlpInfo(); 550 assertFalse(plps.isEmpty()); 551 break; 552 } 553 } 554 tuner.close(); 555 tuner = null; 556 } 557 } 558 559 @Test testFrontendStatusReadiness()560 public void testFrontendStatusReadiness() throws Exception { 561 // Test w/o active frontend 562 try { 563 int[] caps = {0}; 564 List<FrontendStatusReadiness> readiness = mTuner.getFrontendStatusReadiness(caps); 565 if (TunerVersionChecker.isHigherOrEqualVersionTo( 566 TunerVersionChecker.TUNER_VERSION_2_0)) { 567 fail("Get Frontend Status Readiness should throw IllegalStateException."); 568 } else { 569 assertTrue(readiness.isEmpty()); 570 } 571 } catch (IllegalStateException e) { 572 // pass 573 } 574 575 List<Integer> ids = mTuner.getFrontendIds(); 576 if (ids == null) 577 return; 578 assertFalse(ids.isEmpty()); 579 580 for (int id : ids) { 581 Tuner tuner = new Tuner(mContext, null, 100); 582 FrontendInfo info = tuner.getFrontendInfoById(id); 583 int res = tuner.tune(createFrontendSettings(info)); 584 585 int[] statusCapabilities = info.getStatusCapabilities(); 586 assertNotNull(statusCapabilities); 587 List<FrontendStatusReadiness> readiness = 588 tuner.getFrontendStatusReadiness(statusCapabilities); 589 if (TunerVersionChecker.isHigherOrEqualVersionTo( 590 TunerVersionChecker.TUNER_VERSION_2_0)) { 591 assertEquals(readiness.size(), statusCapabilities.length); 592 for (int i = 0; i < readiness.size(); i++) { 593 assertEquals(readiness.get(i).getStatusType(), statusCapabilities[i]); 594 int r = readiness.get(i).getStatusReadiness(); 595 if (r == FrontendStatusReadiness.FRONTEND_STATUS_READINESS_UNAVAILABLE 596 || r == FrontendStatusReadiness.FRONTEND_STATUS_READINESS_UNSTABLE 597 || r == FrontendStatusReadiness.FRONTEND_STATUS_READINESS_STABLE) { 598 // pass 599 } else { 600 fail("Get Frontend Status Readiness returned wrong readiness " + r); 601 } 602 } 603 } else { 604 assertTrue(readiness.isEmpty()); 605 } 606 tuner.cancelTuning(); 607 tuner.close(); 608 tuner = null; 609 } 610 } 611 612 @Test testLnb()613 public void testLnb() throws Exception { 614 Lnb lnb = mTuner.openLnb(getExecutor(), getLnbCallback()); 615 if (lnb == null) return; 616 assertEquals(lnb.setVoltage(Lnb.VOLTAGE_5V), Tuner.RESULT_SUCCESS); 617 assertEquals(lnb.setTone(Lnb.TONE_NONE), Tuner.RESULT_SUCCESS); 618 assertEquals( 619 lnb.setSatellitePosition(Lnb.POSITION_A), Tuner.RESULT_SUCCESS); 620 lnb.sendDiseqcMessage(new byte[] {1, 2}); 621 lnb.close(); 622 } 623 624 @Test testLnbAddAndRemoveCallback()625 public void testLnbAddAndRemoveCallback() throws Exception { 626 TunerTestLnbCallback lnbCB1 = new TunerTestLnbCallback(); 627 Lnb lnb = mTuner.openLnb(getExecutor(), lnbCB1); 628 if (lnb == null) { 629 return; 630 } 631 632 assertEquals(lnb.setVoltage(Lnb.VOLTAGE_5V), Tuner.RESULT_SUCCESS); 633 assertEquals(lnb.setTone(Lnb.TONE_NONE), Tuner.RESULT_SUCCESS); 634 assertEquals( 635 lnb.setSatellitePosition(Lnb.POSITION_A), Tuner.RESULT_SUCCESS); 636 lnb.sendDiseqcMessage(new byte[] {1, 2}); 637 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 638 lnbCB1.resetOnDiseqcMessageCalled(); 639 640 List<Integer> ids = mTuner.getFrontendIds(); 641 assertFalse(ids.isEmpty()); 642 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 643 FrontendSettings feSettings = createFrontendSettings(info); 644 int res = mTuner.tune(feSettings); 645 assertEquals(Tuner.RESULT_SUCCESS, res); 646 647 // create sharee 648 Tuner sharee = new Tuner(mContext, null, 100); 649 sharee.shareFrontendFromTuner(mTuner); 650 TunerTestLnbCallback lnbCB2 = new TunerTestLnbCallback(); 651 652 // add it as sharee 653 lnb.addCallback(getExecutor(), lnbCB2); 654 655 // check callback 656 lnb.sendDiseqcMessage(new byte[] {1, 2}); 657 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 658 lnbCB1.resetOnDiseqcMessageCalled(); 659 assertTrue(lnbCB2.getOnDiseqcMessageCalled()); 660 lnbCB2.resetOnDiseqcMessageCalled(); 661 662 // remove sharee the sharee (should succeed) 663 assertTrue(lnb.removeCallback(lnbCB2)); 664 665 // check callback (only the original owner gets callback 666 lnb.sendDiseqcMessage(new byte[] {1, 2}); 667 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 668 lnbCB1.resetOnDiseqcMessageCalled(); 669 assertFalse(lnbCB2.getOnDiseqcMessageCalled()); 670 lnbCB2.resetOnDiseqcMessageCalled(); 671 672 sharee.close(); 673 } 674 675 @Test testOpenLnbByname()676 public void testOpenLnbByname() throws Exception { 677 Lnb lnb = mTuner.openLnbByName("default", getExecutor(), getLnbCallback()); 678 if (lnb != null) { 679 lnb.close(); 680 } 681 } 682 683 @Test testCiCam()684 public void testCiCam() throws Exception { 685 // open filter to get demux resource 686 mTuner.openFilter( 687 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 688 689 mTuner.connectCiCam(1); 690 mTuner.disconnectCiCam(); 691 } 692 693 @Test testFrontendToCiCam()694 public void testFrontendToCiCam() throws Exception { 695 // tune to get frontend resource 696 List<Integer> ids = mTuner.getFrontendIds(); 697 if (ids == null) return; 698 assertFalse(ids.isEmpty()); 699 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 700 int res = mTuner.tune(createFrontendSettings(info)); 701 assertEquals(Tuner.RESULT_SUCCESS, res); 702 703 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 704 // TODO: get real CiCam id from MediaCas 705 // only tuner hal1.1 support CiCam 706 res = mTuner.connectFrontendToCiCam(0); 707 if (res != Tuner.INVALID_LTS_ID) 708 assertEquals(mTuner.disconnectFrontendToCiCam(0), Tuner.RESULT_SUCCESS); 709 } 710 } 711 712 @Test testRemoveOutputPid()713 public void testRemoveOutputPid() throws Exception { 714 // Test w/o active frontend 715 try { 716 int status = mTuner.removeOutputPid(10); 717 if (TunerVersionChecker.isHigherOrEqualVersionTo( 718 TunerVersionChecker.TUNER_VERSION_2_0)) { 719 fail("Remove output PID should throw IllegalStateException."); 720 } else { 721 assertEquals(status, Tuner.RESULT_UNAVAILABLE); 722 } 723 } catch (IllegalStateException e) { 724 // pass 725 } 726 727 // tune to get frontend resource 728 List<Integer> ids = mTuner.getFrontendIds(); 729 if (ids == null) 730 return; 731 assertFalse(ids.isEmpty()); 732 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 733 int res = mTuner.tune(createFrontendSettings(info)); 734 assertEquals(Tuner.RESULT_SUCCESS, res); 735 736 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 737 // TODO: get real CiCam id from MediaCas 738 res = mTuner.connectFrontendToCiCam(0); 739 } else { 740 assertEquals(Tuner.INVALID_LTS_ID, mTuner.connectFrontendToCiCam(0)); 741 } 742 743 int status = mTuner.removeOutputPid(10); 744 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) { 745 if (status != Tuner.RESULT_SUCCESS) { 746 assertEquals(status, Tuner.RESULT_UNAVAILABLE); 747 } 748 } else { 749 assertEquals(status, Tuner.RESULT_UNAVAILABLE); 750 } 751 752 if (res != Tuner.INVALID_LTS_ID) { 753 assertEquals(mTuner.disconnectFrontendToCiCam(0), Tuner.RESULT_SUCCESS); 754 } else { 755 // Make sure the connectFrontendToCiCam only fails because the current device 756 // does not support connecting frontend to cicam 757 assertEquals(mTuner.disconnectFrontendToCiCam(0), Tuner.RESULT_UNAVAILABLE); 758 } 759 } 760 761 @Test testAvSyncId()762 public void testAvSyncId() throws Exception { 763 // open filter to get demux resource 764 Filter f = mTuner.openFilter( 765 Filter.TYPE_TS, Filter.SUBTYPE_AUDIO, 1000, getExecutor(), getFilterCallback()); 766 assertNotNull(f); 767 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 768 Settings settings = AvSettings 769 .builder(Filter.TYPE_TS, true) 770 .setPassthrough(false) 771 .setUseSecureMemory(false) 772 .setAudioStreamType(AvSettings.AUDIO_STREAM_TYPE_MPEG1) 773 .build(); 774 FilterConfiguration config = TsFilterConfiguration 775 .builder() 776 .setTpid(10) 777 .setSettings(settings) 778 .build(); 779 f.configure(config); 780 int id = mTuner.getAvSyncHwId(f); 781 if (id != Tuner.INVALID_AV_SYNC_ID) { 782 assertNotEquals(Tuner.INVALID_TIMESTAMP, mTuner.getAvSyncTime(id)); 783 } 784 } 785 786 @Test testReadFilter()787 public void testReadFilter() throws Exception { 788 Filter f = mTuner.openFilter( 789 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 790 assertNotNull(f); 791 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 792 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 793 assertNotEquals(Tuner.INVALID_FILTER_ID_LONG, f.getIdLong()); 794 } else { 795 assertEquals(Tuner.INVALID_FILTER_ID_LONG, f.getIdLong()); 796 } 797 798 Settings settings = SectionSettingsWithTableInfo 799 .builder(Filter.TYPE_TS) 800 .setTableId(2) 801 .setVersion(1) 802 .setCrcEnabled(true) 803 .setRaw(false) 804 .setRepeat(false) 805 .build(); 806 FilterConfiguration config = TsFilterConfiguration 807 .builder() 808 .setTpid(10) 809 .setSettings(settings) 810 .build(); 811 f.configure(config); 812 f.setMonitorEventMask( 813 Filter.MONITOR_EVENT_SCRAMBLING_STATUS | Filter.MONITOR_EVENT_IP_CID_CHANGE); 814 815 // Tune a frontend before start the filter 816 List<Integer> ids = mTuner.getFrontendIds(); 817 if (ids == null) return; 818 assertFalse(ids.isEmpty()); 819 820 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 821 int res = mTuner.tune(createFrontendSettings(info)); 822 assertEquals(Tuner.RESULT_SUCCESS, res); 823 824 f.start(); 825 f.flush(); 826 f.read(new byte[3], 0, 3); 827 f.stop(); 828 f.close(); 829 830 res = mTuner.cancelTuning(); 831 assertEquals(Tuner.RESULT_SUCCESS, res); 832 } 833 834 @Test testAudioFilterStreamTypeConfig()835 public void testAudioFilterStreamTypeConfig() throws Exception { 836 Filter f = mTuner.openFilter( 837 Filter.TYPE_TS, Filter.SUBTYPE_AUDIO, 1000, getExecutor(), getFilterCallback()); 838 assertNotNull(f); 839 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 840 841 Settings settings = AvSettings 842 .builder(Filter.TYPE_TS, true) 843 .setPassthrough(false) 844 .setUseSecureMemory(false) 845 .setAudioStreamType(AvSettings.AUDIO_STREAM_TYPE_MPEG1) 846 .build(); 847 FilterConfiguration config = TsFilterConfiguration 848 .builder() 849 .setTpid(10) 850 .setSettings(settings) 851 .build(); 852 f.configure(config); 853 854 // Tune a frontend before start the filter 855 List<Integer> ids = mTuner.getFrontendIds(); 856 if (ids == null) return; 857 assertFalse(ids.isEmpty()); 858 859 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 860 int res = mTuner.tune(createFrontendSettings(info)); 861 assertEquals(Tuner.RESULT_SUCCESS, res); 862 863 f.start(); 864 f.flush(); 865 f.stop(); 866 f.close(); 867 868 res = mTuner.cancelTuning(); 869 assertEquals(Tuner.RESULT_SUCCESS, res); 870 } 871 872 @Test testTimeFilter()873 public void testTimeFilter() throws Exception { 874 if (!mTuner.getDemuxCapabilities().isTimeFilterSupported()) return; 875 TimeFilter f = mTuner.openTimeFilter(); 876 assertNotNull(f); 877 f.setCurrentTimestamp(0); 878 assertNotEquals(Tuner.INVALID_TIMESTAMP, f.getTimeStamp()); 879 assertNotEquals(Tuner.INVALID_TIMESTAMP, f.getSourceTime()); 880 f.clearTimestamp(); 881 f.close(); 882 } 883 884 @Test testIpFilter()885 public void testIpFilter() throws Exception { 886 Filter f = mTuner.openFilter( 887 Filter.TYPE_IP, Filter.SUBTYPE_IP, 1000, getExecutor(), getFilterCallback()); 888 if (f == null) return; 889 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 890 891 FilterConfiguration config = IpFilterConfiguration 892 .builder() 893 .setSrcIpAddress(new byte[] {(byte) 0xC0, (byte) 0xA8, 0, 1}) 894 .setDstIpAddress(new byte[] {(byte) 0xC0, (byte) 0xA8, 3, 4}) 895 .setSrcPort(33) 896 .setDstPort(23) 897 .setPassthrough(false) 898 .setSettings(null) 899 .setIpFilterContextId(1) 900 .build(); 901 f.configure(config); 902 903 // Tune a frontend before start the filter 904 List<Integer> ids = mTuner.getFrontendIds(); 905 if (ids == null) return; 906 assertFalse(ids.isEmpty()); 907 908 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 909 int res = mTuner.tune(createFrontendSettings(info)); 910 assertEquals(Tuner.RESULT_SUCCESS, res); 911 912 f.start(); 913 f.stop(); 914 f.close(); 915 916 res = mTuner.cancelTuning(); 917 assertEquals(Tuner.RESULT_SUCCESS, res); 918 } 919 920 @Test testAlpSectionFilterConfig()921 public void testAlpSectionFilterConfig() throws Exception { 922 Filter f = mTuner.openFilter( 923 Filter.TYPE_ALP, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 924 if (f == null) return; 925 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 926 927 SectionSettingsWithSectionBits settings = 928 SectionSettingsWithSectionBits 929 .builder(Filter.TYPE_TS) 930 .setCrcEnabled(true) 931 .setRepeat(false) 932 .setRaw(false) 933 .setFilter(new byte[]{2, 3, 4}) 934 .setMask(new byte[]{7, 6, 5, 4}) 935 .setMode(new byte[]{22, 55, 33}) 936 .build(); 937 AlpFilterConfiguration config = 938 AlpFilterConfiguration 939 .builder() 940 .setPacketType(AlpFilterConfiguration.PACKET_TYPE_COMPRESSED) 941 .setLengthType(AlpFilterConfiguration.LENGTH_TYPE_WITH_ADDITIONAL_HEADER) 942 .setSettings(settings) 943 .build(); 944 f.configure(config); 945 f.start(); 946 f.stop(); 947 f.close(); 948 } 949 950 @Test testMmtpPesFilterConfig()951 public void testMmtpPesFilterConfig() throws Exception { 952 Filter f = mTuner.openFilter( 953 Filter.TYPE_MMTP, Filter.SUBTYPE_PES, 1000, getExecutor(), getFilterCallback()); 954 if (f == null) return; 955 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 956 957 PesSettings settings = 958 PesSettings 959 .builder(Filter.TYPE_TS) 960 .setStreamId(3) 961 .setRaw(false) 962 .build(); 963 MmtpFilterConfiguration config = 964 MmtpFilterConfiguration 965 .builder() 966 .setMmtpPacketId(3) 967 .setSettings(settings) 968 .build(); 969 f.configure(config); 970 f.start(); 971 f.stop(); 972 f.close(); 973 } 974 975 @Test testMmtpDownloadFilterConfig()976 public void testMmtpDownloadFilterConfig() throws Exception { 977 Filter f = mTuner.openFilter( 978 Filter.TYPE_MMTP, Filter.SUBTYPE_DOWNLOAD, 979 1000, getExecutor(), getFilterCallback()); 980 if (f == null) return; 981 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 982 983 DownloadSettings.Builder builder = DownloadSettings.builder(Filter.TYPE_MMTP); 984 if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 985 builder.setUseDownloadId(true); 986 } 987 builder.setDownloadId(2); 988 DownloadSettings settings = builder.build(); 989 if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 990 assertEquals(settings.useDownloadId(), true); 991 } else { 992 assertEquals(settings.useDownloadId(), false); 993 } 994 assertEquals(settings.getDownloadId(), 2); 995 996 MmtpFilterConfiguration config = 997 MmtpFilterConfiguration 998 .builder() 999 .setMmtpPacketId(3) 1000 .setSettings(settings) 1001 .build(); 1002 f.configure(config); 1003 f.start(); 1004 f.stop(); 1005 f.close(); 1006 } 1007 1008 @Test testTsAvFilterConfig()1009 public void testTsAvFilterConfig() throws Exception { 1010 Filter f = mTuner.openFilter( 1011 Filter.TYPE_TS, Filter.SUBTYPE_AUDIO, 1000, getExecutor(), getFilterCallback()); 1012 assertNotNull(f); 1013 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1014 1015 AvSettings settings = 1016 AvSettings 1017 .builder(Filter.TYPE_TS, true) // is Audio 1018 .setPassthrough(false) 1019 .setUseSecureMemory(false) 1020 .setAudioStreamType(AvSettings.AUDIO_STREAM_TYPE_MPEG1) 1021 .build(); 1022 TsFilterConfiguration config = 1023 TsFilterConfiguration 1024 .builder() 1025 .setTpid(521) 1026 .setSettings(settings) 1027 .build(); 1028 f.configure(config); 1029 f.start(); 1030 f.stop(); 1031 f.close(); 1032 } 1033 1034 @Test testTsRecordFilterConfig()1035 public void testTsRecordFilterConfig() throws Exception { 1036 Filter f = mTuner.openFilter( 1037 Filter.TYPE_TS, Filter.SUBTYPE_RECORD, 1000, getExecutor(), getFilterCallback()); 1038 assertNotNull(f); 1039 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1040 1041 RecordSettings settings = 1042 RecordSettings 1043 .builder(Filter.TYPE_TS) 1044 .setTsIndexMask( 1045 RecordSettings.TS_INDEX_FIRST_PACKET 1046 | RecordSettings.TS_INDEX_PRIVATE_DATA) 1047 .setScIndexType(RecordSettings.INDEX_TYPE_SC) 1048 .setScIndexMask(RecordSettings.SC_INDEX_B_SLICE) 1049 .build(); 1050 TsFilterConfiguration config = 1051 TsFilterConfiguration 1052 .builder() 1053 .setTpid(521) 1054 .setSettings(settings) 1055 .build(); 1056 f.configure(config); 1057 f.start(); 1058 f.stop(); 1059 f.close(); 1060 } 1061 1062 @Test testTlvTlvFilterConfig()1063 public void testTlvTlvFilterConfig() throws Exception { 1064 Filter f = mTuner.openFilter( 1065 Filter.TYPE_TLV, Filter.SUBTYPE_TLV, 1000, getExecutor(), getFilterCallback()); 1066 if (f == null) return; 1067 assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId()); 1068 1069 TlvFilterConfiguration config = 1070 TlvFilterConfiguration 1071 .builder() 1072 .setPacketType(TlvFilterConfiguration.PACKET_TYPE_IPV4) 1073 .setCompressedIpPacket(true) 1074 .setPassthrough(false) 1075 .setSettings(null) 1076 .build(); 1077 f.configure(config); 1078 f.start(); 1079 f.stop(); 1080 f.close(); 1081 } 1082 1083 @Test testDescrambler()1084 public void testDescrambler() throws Exception { 1085 Descrambler d = mTuner.openDescrambler(); 1086 byte[] keyToken = new byte[] {1, 3, 2}; 1087 assertNotNull(d); 1088 Filter f = mTuner.openFilter( 1089 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 1090 assertTrue(d.isValidKeyToken(keyToken)); 1091 d.setKeyToken(keyToken); 1092 d.addPid(Descrambler.PID_TYPE_T, 1, f); 1093 d.removePid(Descrambler.PID_TYPE_T, 1, f); 1094 f.close(); 1095 d.close(); 1096 } 1097 1098 @Test testDescramblerKeyTokenValidator()1099 public void testDescramblerKeyTokenValidator() throws Exception { 1100 byte[] invalidToken = new byte[17]; 1101 byte[] validToken = new byte[] {1, 3, 2}; 1102 assertTrue(Descrambler.isValidKeyToken(validToken)); 1103 assertTrue(Descrambler.isValidKeyToken(Tuner.VOID_KEYTOKEN)); 1104 assertFalse(Descrambler.isValidKeyToken(invalidToken)); 1105 } 1106 1107 @Test testOpenDvrRecorder()1108 public void testOpenDvrRecorder() throws Exception { 1109 DvrRecorder d = mTuner.openDvrRecorder(100, getExecutor(), getRecordListener()); 1110 assertNotNull(d); 1111 d.close(); 1112 } 1113 1114 @Test testOpenDvPlayback()1115 public void testOpenDvPlayback() throws Exception { 1116 DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener()); 1117 assertNotNull(d); 1118 d.close(); 1119 } 1120 1121 @Test testDemuxCapabilities()1122 public void testDemuxCapabilities() throws Exception { 1123 DemuxCapabilities d = mTuner.getDemuxCapabilities(); 1124 assertNotNull(d); 1125 1126 d.getDemuxCount(); 1127 d.getRecordCount(); 1128 d.getPlaybackCount(); 1129 d.getTsFilterCount(); 1130 d.getSectionFilterCount(); 1131 d.getAudioFilterCount(); 1132 d.getVideoFilterCount(); 1133 d.getPesFilterCount(); 1134 d.getPcrFilterCount(); 1135 d.getSectionFilterLength(); 1136 d.getFilterCapabilities(); 1137 d.getLinkCapabilities(); 1138 d.isTimeFilterSupported(); 1139 } 1140 1141 @Test testResourceLostListener()1142 public void testResourceLostListener() throws Exception { 1143 mTuner.setResourceLostListener(getExecutor(), new Tuner.OnResourceLostListener() { 1144 @Override 1145 public void onResourceLost(Tuner tuner) { 1146 } 1147 }); 1148 mTuner.clearResourceLostListener(); 1149 } 1150 1151 @Test testOnTuneEventListener()1152 public void testOnTuneEventListener() throws Exception { 1153 mTuner.setOnTuneEventListener(getExecutor(), new OnTuneEventListener() { 1154 @Override 1155 public void onTuneEvent(int tuneEvent) { 1156 } 1157 }); 1158 mTuner.clearOnTuneEventListener(); 1159 } 1160 1161 @Test testUpdateResourcePriority()1162 public void testUpdateResourcePriority() throws Exception { 1163 mTuner.updateResourcePriority(100, 20); 1164 } 1165 1166 @Test testResourceReclaimed()1167 public void testResourceReclaimed() throws Exception { 1168 List<Integer> ids = mTuner.getFrontendIds(); 1169 assertFalse(ids.isEmpty()); 1170 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1171 FrontendSettings feSettings = createFrontendSettings(info); 1172 1173 // first tune with mTuner to acquire resource 1174 int res = mTuner.tune(feSettings); 1175 assertEquals(Tuner.RESULT_SUCCESS, res); 1176 assertNotNull(mTuner.getFrontendInfo()); 1177 1178 // now tune with a higher priority tuner to have mTuner's resource reclaimed 1179 Tuner higherPrioTuner = new Tuner(mContext, null, 200); 1180 res = higherPrioTuner.tune(feSettings); 1181 assertEquals(Tuner.RESULT_SUCCESS, res); 1182 assertNotNull(higherPrioTuner.getFrontendInfo()); 1183 1184 higherPrioTuner.close(); 1185 } 1186 1187 // TODO: change this to use ITunerResourceTestServer 1188 @Test testResourceReclaimedDifferentThread()1189 public void testResourceReclaimedDifferentThread() throws Exception { 1190 List<Integer> ids = mTuner.getFrontendIds(); 1191 assertFalse(ids.isEmpty()); 1192 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1193 FrontendSettings feSettings = createFrontendSettings(info); 1194 1195 // first tune with mTuner to acquire resource 1196 int res = mTuner.tune(feSettings); 1197 assertEquals(Tuner.RESULT_SUCCESS, res); 1198 assertNotNull(mTuner.getFrontendInfo()); 1199 1200 // now tune with a higher priority tuner to have mTuner's resource reclaimed 1201 TunerHandler tunerHandler = createTunerHandler(null); 1202 Message msgCreate = new Message(); 1203 msgCreate.what = MSG_TUNER_HANDLER_CREATE; 1204 msgCreate.arg1 = 200; 1205 tunerHandler.sendMessage(msgCreate); 1206 mTunerHandlerTaskComplete.block(); 1207 mTunerHandlerTaskComplete.close(); 1208 1209 Message msgTune = new Message(); 1210 msgTune.what = MSG_TUNER_HANDLER_TUNE; 1211 msgTune.obj = (Object) feSettings; 1212 tunerHandler.sendMessage(msgTune); 1213 1214 // call mTuner.close in parallel 1215 int sleepMS = 1; 1216 //int sleepMS = (int) (Math.random() * 3.); 1217 try { 1218 Thread.sleep(sleepMS); 1219 } catch (Exception e) { } // ignore 1220 mTuner.close(); 1221 mTuner = null; 1222 1223 mTunerHandlerTaskComplete.block(); 1224 mTunerHandlerTaskComplete.close(); 1225 res = tunerHandler.getResult(); 1226 assertEquals(Tuner.RESULT_SUCCESS, res); 1227 1228 Tuner higherPrioTuner = tunerHandler.getTuner(); 1229 assertNotNull(higherPrioTuner.getFrontendInfo()); 1230 1231 Message msgClose = new Message(); 1232 msgClose.what = MSG_TUNER_HANDLER_CLOSE; 1233 tunerHandler.sendMessage(msgClose); 1234 1235 } 1236 1237 @Test testResourceReclaimedDifferentProcess()1238 public void testResourceReclaimedDifferentProcess() throws Exception { 1239 List<Integer> ids = mTuner.getFrontendIds(); 1240 int frontendIndex = 0; 1241 assertFalse(ids.isEmpty()); 1242 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(frontendIndex)); 1243 FrontendSettings feSettings = createFrontendSettings(info); 1244 1245 // set up the test server 1246 TunerResourceTestServiceConnection connection = new TunerResourceTestServiceConnection(); 1247 ITunerResourceTestServer tunerResourceTestServer = null; 1248 Intent intent = new Intent(mContext, TunerResourceTestService.class); 1249 1250 // get the TunerResourceTestService 1251 mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE); 1252 tunerResourceTestServer = connection.getService(); 1253 1254 // CASE1 - normal reclaim 1255 // 1256 // first tune with mTuner to acquire resource 1257 int res = mTuner.tune(feSettings); 1258 boolean tunerReclaimed = false; 1259 assertEquals(Tuner.RESULT_SUCCESS, res); 1260 assertNotNull(mTuner.getFrontendInfo()); 1261 1262 // now tune with a higher priority tuner to have mTuner's resource reclaimed 1263 1264 // create higher priority tuner 1265 tunerResourceTestServer.createTuner(200); 1266 1267 // now tune on higher priority tuner to get mTuner reclaimed 1268 res = tunerResourceTestServer.tune(frontendIndex); 1269 assertEquals(Tuner.RESULT_SUCCESS, res); 1270 1271 try { 1272 int[] statusCapabilities = info.getStatusCapabilities(); 1273 mTuner.getFrontendStatus(statusCapabilities); 1274 1275 } catch (IllegalStateException e) { 1276 tunerReclaimed = true; 1277 mTuner.close(); 1278 mTuner = null; 1279 } 1280 1281 // confirm if the mTuner is reclaimed 1282 assertTrue(tunerReclaimed); 1283 1284 tunerResourceTestServer.closeTuner(); 1285 assertTrue(tunerResourceTestServer.verifyTunerIsNull()); 1286 1287 1288 // CASE2 - race between Tuner#close() and reclaim 1289 mTuner = new Tuner(mContext, null, 100); 1290 res = mTuner.tune(feSettings); 1291 assertEquals(Tuner.RESULT_SUCCESS, res); 1292 assertNotNull(mTuner.getFrontendInfo()); 1293 1294 tunerResourceTestServer.createTuner(200); 1295 tunerResourceTestServer.tuneAsync(frontendIndex); 1296 1297 // adjust timing to induce race/deadlock 1298 int sleepMS = 4; 1299 //int sleepMS = (int) (Math.random() * 5.); 1300 try { 1301 Thread.sleep(sleepMS); 1302 } catch (Exception e) { } // ignore 1303 mTuner.close(); 1304 mTuner = null; 1305 1306 tunerResourceTestServer.closeTuner(); 1307 1308 // unbind 1309 mContext.unbindService(connection); 1310 } 1311 1312 @Test testShareFrontendFromTuner()1313 public void testShareFrontendFromTuner() throws Exception { 1314 Tuner tuner100 = new Tuner(mContext, null, 100); 1315 List<Integer> ids = tuner100.getFrontendIds(); 1316 assertFalse(ids.isEmpty()); 1317 FrontendInfo info = tuner100.getFrontendInfoById(ids.get(0)); 1318 FrontendSettings feSettings = createFrontendSettings(info); 1319 int[] statusTypes = {1}; 1320 boolean exceptionThrown = false; 1321 int res; 1322 1323 // CASE1: check resource reclaim while sharee's priority < owner's priority 1324 // let tuner100 share from tuner200 1325 Tuner tuner200 = new Tuner(mContext, null, 200); 1326 res = tuner200.tune(feSettings); 1327 assertEquals(Tuner.RESULT_SUCCESS, res); 1328 1329 info = tuner200.getFrontendInfoById(ids.get(0)); 1330 res = tuner200.tune(feSettings); 1331 assertEquals(Tuner.RESULT_SUCCESS, res); 1332 1333 tuner100 = new Tuner(mContext, null, 100); 1334 tuner100.shareFrontendFromTuner(tuner200); 1335 // call openFilter to trigger ITunerDemux.setFrontendDataSourceById() 1336 Filter f = tuner100.openFilter( 1337 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 1338 assertNotNull(f); 1339 1340 // setup onTuneCallback 1341 TunerTestOnTuneEventListener cb100 = new TunerTestOnTuneEventListener(); 1342 TunerTestOnTuneEventListener cb200 = new TunerTestOnTuneEventListener(); 1343 1344 // tune again on the owner 1345 info = tuner200.getFrontendInfoById(ids.get(1)); 1346 tuner100.setOnTuneEventListener(getExecutor(), cb100); 1347 tuner200.setOnTuneEventListener(getExecutor(), cb200); 1348 res = tuner200.tune(feSettings); 1349 assertEquals(Tuner.RESULT_SUCCESS, res); 1350 assertEquals(OnTuneEventListener.SIGNAL_LOCKED, cb100.getLastTuneEvent()); 1351 assertEquals(OnTuneEventListener.SIGNAL_LOCKED, cb200.getLastTuneEvent()); 1352 tuner100.clearOnTuneEventListener(); 1353 tuner200.clearOnTuneEventListener(); 1354 1355 // now let the higher priority tuner steal the resource 1356 Tuner tuner300 = new Tuner(mContext, null, 300); 1357 res = tuner300.tune(feSettings); 1358 assertEquals(Tuner.RESULT_SUCCESS, res); 1359 1360 // confirm owner & sharee's resource gets reclaimed by confirming an exception is thrown 1361 exceptionThrown = false; 1362 try { 1363 tuner200.getFrontendStatus(statusTypes); 1364 } catch (Exception e) { 1365 exceptionThrown = true; 1366 } 1367 assertTrue(exceptionThrown); 1368 1369 exceptionThrown = false; 1370 try { 1371 tuner100.getFrontendStatus(statusTypes); 1372 } catch (Exception e) { 1373 exceptionThrown = true; 1374 } 1375 assertTrue(exceptionThrown); 1376 1377 tuner100.close(); 1378 tuner200.close(); 1379 tuner300.close(); 1380 1381 1382 // CASE2: check resource reclaim fail when sharee's priority > new requester 1383 tuner100 = new Tuner(mContext, null, 100); 1384 res = tuner100.tune(feSettings); 1385 assertEquals(Tuner.RESULT_SUCCESS, res); 1386 1387 tuner300 = new Tuner(mContext, null, 300); 1388 tuner300.shareFrontendFromTuner(tuner100); 1389 f = tuner100.openFilter( 1390 Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, getExecutor(), getFilterCallback()); 1391 assertNotNull(f); 1392 1393 tuner200 = new Tuner(mContext, null, 200); 1394 res = tuner200.tune(feSettings); 1395 assertNotEquals(Tuner.RESULT_SUCCESS, res); 1396 1397 // confirm the original tuner is still intact 1398 res = tuner100.tune(feSettings); 1399 assertEquals(Tuner.RESULT_SUCCESS, res); 1400 1401 tuner100.close(); 1402 tuner200.close(); 1403 tuner300.close(); 1404 } 1405 testTransferFeOwnershipSingleTuner()1406 private void testTransferFeOwnershipSingleTuner() { 1407 List<Integer> ids = mTuner.getFrontendIds(); 1408 if (ids == null) { 1409 return; 1410 } 1411 assertFalse(ids.isEmpty()); 1412 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1413 FrontendSettings feSettings = createFrontendSettings(info); 1414 1415 // SCENARIO 1 - transfer and close the previous owner 1416 1417 // First create a tuner and tune() to acquire frontend resource 1418 Tuner tunerA = new Tuner(mContext, null, 100); 1419 int res = tunerA.tune(feSettings); 1420 assertEquals(Tuner.RESULT_SUCCESS, res); 1421 1422 // Create another tuner and share frontend from tunerA 1423 Tuner tunerB = new Tuner(mContext, null, 500); 1424 tunerB.shareFrontendFromTuner(tunerA); 1425 DvrRecorder d = tunerB.openDvrRecorder(100, getExecutor(), getRecordListener()); 1426 assertNotNull(d); 1427 1428 // Call transferOwner in the wrong configurations and confirm it fails 1429 assertEquals(Tuner.RESULT_INVALID_STATE, tunerB.transferOwner(tunerA)); 1430 Tuner nonSharee = new Tuner(mContext, null, 300); 1431 assertEquals(Tuner.RESULT_INVALID_STATE, tunerA.transferOwner(nonSharee)); 1432 nonSharee.close(); 1433 1434 // Now call it correctly to transfer ownership from tunerA to tunerB 1435 assertEquals(Tuner.RESULT_SUCCESS, tunerA.transferOwner(tunerB)); 1436 1437 // Close the original owner (tunerA) 1438 tunerA.close(); 1439 1440 // Confirm the new owner (tunerB) is still functional 1441 assertNotNull(tunerB.getFrontendInfo()); 1442 1443 // Close the new owner (tunerB) 1444 d.close(); 1445 tunerB.close(); 1446 1447 // SCENARIO 2 - transfer and closeFrontend and tune on the previous owner 1448 1449 // First create a tuner and tune() to acquire frontend resource 1450 tunerA = new Tuner(mContext, null, 200); 1451 res = tunerA.tune(feSettings); 1452 assertEquals(Tuner.RESULT_SUCCESS, res); 1453 1454 // Create another tuner and share frontend from tunerA 1455 tunerB = new Tuner(mContext, null, 100); 1456 tunerB.shareFrontendFromTuner(tunerA); 1457 assertNotNull(tunerB.getFrontendInfo()); 1458 1459 // Transfer ownership from tunerA to tunerB 1460 assertEquals(Tuner.RESULT_SUCCESS, tunerA.transferOwner(tunerB)); 1461 1462 // Close frontend for the original owner (tunerA) 1463 tunerA.closeFrontend(); 1464 1465 // Confirm tune works without going through Tuner.close() even after transferOwner() 1466 // The purpose isn't to get tunerB's frontend revoked, but doing so as singletuner 1467 // based test has wider coverage 1468 res = tunerA.tune(feSettings); // this should reclaim tunerB 1469 assertEquals(Tuner.RESULT_SUCCESS, res); 1470 1471 // Confirm tuberB is revoked 1472 assertNull(tunerB.getFrontendInfo()); 1473 1474 // Close tunerA 1475 tunerA.close(); 1476 1477 // close TunerB just in case 1478 tunerB.close(); 1479 } 1480 testTransferFeAndCiCamOwnership()1481 private void testTransferFeAndCiCamOwnership() { 1482 List<Integer> ids = mTuner.getFrontendIds(); 1483 assertNotNull(ids); 1484 assertFalse(ids.isEmpty()); 1485 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1486 FrontendSettings feSettings = createFrontendSettings(info); 1487 1488 // Create tuner and tune to get frontend resource 1489 Tuner tunerA = new Tuner(mContext, null, 100); 1490 assertEquals(Tuner.RESULT_SUCCESS, tunerA.tune(feSettings)); 1491 1492 int ciCamId = 0; 1493 boolean linkCiCamToFrontendSupported = false; 1494 1495 // connect CiCam to Frontend 1496 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 1497 // TODO: get real CiCam id from MediaCas 1498 assertEquals(Tuner.RESULT_SUCCESS, tunerA.connectFrontendToCiCam(ciCamId)); 1499 linkCiCamToFrontendSupported = true; 1500 } else { 1501 assertEquals(Tuner.INVALID_LTS_ID, tunerA.connectFrontendToCiCam(ciCamId)); 1502 } 1503 1504 // connect CiCam to Demux 1505 assertEquals(Tuner.RESULT_SUCCESS, tunerA.connectCiCam(ciCamId)); 1506 1507 // start another tuner and connect the same CiCam to its own demux 1508 Tuner tunerB = new Tuner(mContext, null, 400); 1509 tunerB.shareFrontendFromTuner(tunerA); 1510 assertNotNull(tunerB.getFrontendInfo()); 1511 assertEquals(Tuner.RESULT_SUCCESS, tunerB.connectCiCam(ciCamId)); 1512 1513 // unlink CiCam to Demux in tunerA and transfer ownership 1514 assertEquals(Tuner.RESULT_SUCCESS, tunerA.disconnectCiCam()); 1515 assertEquals(Tuner.RESULT_SUCCESS, tunerA.transferOwner(tunerB)); 1516 1517 // close the original owner 1518 tunerA.close(); 1519 1520 // disconnect CiCam from demux 1521 assertEquals(Tuner.RESULT_SUCCESS, tunerB.disconnectCiCam()); 1522 1523 // let Tuner.close() handle the release of CiCam 1524 tunerB.close(); 1525 1526 // now that the CiCam is released, disconnectFrontendToCiCam() should fail 1527 assertEquals(Tuner.RESULT_UNAVAILABLE, tunerB.disconnectFrontendToCiCam(ciCamId)); 1528 1529 // see if tune still works just in case 1530 tunerA = new Tuner(mContext, null, 100); 1531 assertEquals(Tuner.RESULT_SUCCESS, tunerA.tune(feSettings)); 1532 tunerA.close(); 1533 } 1534 testTransferFeAndLnbOwnership()1535 private void testTransferFeAndLnbOwnership() { 1536 List<Integer> ids = mTuner.getFrontendIds(); 1537 assertNotNull(ids); 1538 assertFalse(ids.isEmpty()); 1539 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1540 FrontendSettings feSettings = createFrontendSettings(info); 1541 1542 // Create tuner and tune to acquire frontend resource 1543 Tuner tunerA = new Tuner(mContext, null, 100); 1544 assertEquals(Tuner.RESULT_SUCCESS, tunerA.tune(feSettings)); 1545 1546 // Open Lnb and check the callback 1547 TunerTestLnbCallback lnbCB1 = new TunerTestLnbCallback(); 1548 Lnb lnbA = tunerA.openLnb(getExecutor(), lnbCB1); 1549 assertNotNull(lnbA); 1550 lnbA.setVoltage(Lnb.VOLTAGE_5V); 1551 lnbA.setTone(Lnb.TONE_CONTINUOUS); 1552 lnbA.sendDiseqcMessage(new byte[] {1, 2}); 1553 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 1554 lnbCB1.resetOnDiseqcMessageCalled(); 1555 1556 // Create another tuner and share from tunerB 1557 Tuner tunerB = new Tuner(mContext, null, 300); 1558 tunerB.shareFrontendFromTuner(tunerA); 1559 1560 // add sharee and check the callback 1561 TunerTestLnbCallback lnbCB2 = new TunerTestLnbCallback(); 1562 lnbA.addCallback(getExecutor(), lnbCB2); 1563 lnbA.sendDiseqcMessage(new byte[] {1, 2}); 1564 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 1565 lnbCB1.resetOnDiseqcMessageCalled(); 1566 assertTrue(lnbCB2.getOnDiseqcMessageCalled()); 1567 lnbCB2.resetOnDiseqcMessageCalled(); 1568 1569 // transfer owner and check callback 1570 assertEquals(Tuner.RESULT_SUCCESS, tunerA.transferOwner(tunerB)); 1571 lnbA.sendDiseqcMessage(new byte[] {1, 2}); 1572 assertTrue(lnbCB1.getOnDiseqcMessageCalled()); 1573 lnbCB1.resetOnDiseqcMessageCalled(); 1574 assertTrue(lnbCB2.getOnDiseqcMessageCalled()); 1575 lnbCB2.resetOnDiseqcMessageCalled(); 1576 1577 // remove the owner callback (just for testing) 1578 assertTrue(lnbA.removeCallback(lnbCB2)); 1579 1580 // remove sharee and check callback 1581 assertTrue(lnbA.removeCallback(lnbCB1)); 1582 lnbA.sendDiseqcMessage(new byte[] {1, 2}); 1583 assertFalse(lnbCB1.getOnDiseqcMessageCalled()); 1584 lnbCB1.resetOnDiseqcMessageCalled(); 1585 assertFalse(lnbCB2.getOnDiseqcMessageCalled()); 1586 lnbCB2.resetOnDiseqcMessageCalled(); 1587 1588 // close the original owner 1589 tunerA.close(); 1590 1591 // confirm the new owner is still intact 1592 int[] statusCapabilities = info.getStatusCapabilities(); 1593 assertNotNull(statusCapabilities); 1594 FrontendStatus status = tunerB.getFrontendStatus(statusCapabilities); 1595 assertNotNull(status); 1596 1597 tunerB.close(); 1598 } 1599 1600 @Test testTransferOwner()1601 public void testTransferOwner() throws Exception { 1602 testTransferFeOwnershipSingleTuner(); 1603 testTransferFeAndCiCamOwnership(); 1604 testTransferFeAndLnbOwnership(); 1605 } 1606 1607 @Test testClose()1608 public void testClose() throws Exception { 1609 Tuner other = new Tuner(mContext, null, 100); 1610 1611 List<Integer> ids = other.getFrontendIds(); 1612 if (ids == null) return; 1613 assertFalse(ids.isEmpty()); 1614 FrontendInfo info = other.getFrontendInfoById(ids.get(0)); 1615 1616 FrontendSettings feSettings = createFrontendSettings(info); 1617 int res = other.tune(feSettings); 1618 assertEquals(Tuner.RESULT_SUCCESS, res); 1619 assertNotNull(other.getFrontendInfo()); 1620 1621 other.close(); 1622 1623 // make sure pre-existing tuner is still functional 1624 res = mTuner.tune(feSettings); 1625 assertEquals(Tuner.RESULT_SUCCESS, res); 1626 assertNotNull(mTuner.getFrontendInfo()); 1627 1628 // Frontend sharing scenario 1: close owner first 1629 // create sharee 1630 Tuner sharee = new Tuner(mContext, null, 100); 1631 sharee.shareFrontendFromTuner(mTuner); 1632 1633 // close the owner 1634 mTuner.close(); 1635 mTuner = null; 1636 1637 // check the frontend of sharee is also released 1638 assertNull(sharee.getFrontendInfo()); 1639 1640 sharee.close(); 1641 1642 // Frontend sharing scenario 2: close sharee first 1643 // create owner first 1644 mTuner = new Tuner(mContext, null, 100); 1645 res = mTuner.tune(feSettings); 1646 assertEquals(Tuner.RESULT_SUCCESS, res); 1647 1648 // create sharee 1649 sharee = new Tuner(mContext, null, 100); 1650 sharee.shareFrontendFromTuner(mTuner); 1651 1652 // close sharee 1653 sharee.close(); 1654 1655 // confirm owner is still intact 1656 int[] statusCapabilities = info.getStatusCapabilities(); 1657 assertNotNull(statusCapabilities); 1658 FrontendStatus status = mTuner.getFrontendStatus(statusCapabilities); 1659 assertNotNull(status); 1660 } 1661 1662 @Test testCloseFrontend()1663 public void testCloseFrontend() throws Exception { 1664 List<Integer> ids = mTuner.getFrontendIds(); 1665 if (ids == null) { 1666 return; 1667 } 1668 1669 // SCENARIO 1 - without Lnb 1670 assertFalse(ids.isEmpty()); 1671 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 1672 FrontendSettings feSettings = createFrontendSettings(info); 1673 int res = mTuner.tune(feSettings); 1674 assertEquals(Tuner.RESULT_SUCCESS, res); 1675 assertNotNull(mTuner.getFrontendInfo()); 1676 1677 // now close frontend 1678 mTuner.closeFrontend(); 1679 1680 // confirm frontend is closed 1681 int[] statusCapabilities = info.getStatusCapabilities(); 1682 boolean frontendClosed = false; 1683 try { 1684 mTuner.getFrontendStatus(statusCapabilities); 1685 1686 } catch (IllegalStateException e) { 1687 frontendClosed = true; 1688 } 1689 assertTrue(frontendClosed); 1690 1691 // now tune to a different setting 1692 info = mTuner.getFrontendInfoById(ids.get(1)); 1693 feSettings = createFrontendSettings(info); 1694 mTuner.tune(feSettings); 1695 assertEquals(Tuner.RESULT_SUCCESS, res); 1696 assertNotNull(mTuner.getFrontendInfo()); 1697 FrontendStatus status = mTuner.getFrontendStatus(statusCapabilities); 1698 assertNotNull(status); 1699 1700 // SCENARIO 2 - with Lnb 1701 1702 TunerTestLnbCallback lnbCB1 = new TunerTestLnbCallback(); 1703 Lnb lnb = mTuner.openLnb(getExecutor(), lnbCB1); 1704 if (lnb == null) { 1705 return; 1706 } 1707 1708 mTuner.closeFrontend(); 1709 // confirm frontend is closed 1710 statusCapabilities = info.getStatusCapabilities(); 1711 frontendClosed = false; 1712 try { 1713 mTuner.getFrontendStatus(statusCapabilities); 1714 1715 } catch (IllegalStateException e) { 1716 frontendClosed = true; 1717 } 1718 assertTrue(frontendClosed); 1719 1720 info = mTuner.getFrontendInfoById(ids.get(0)); 1721 feSettings = createFrontendSettings(info); 1722 mTuner.tune(feSettings); 1723 assertEquals(Tuner.RESULT_SUCCESS, res); 1724 assertNotNull(mTuner.getFrontendInfo()); 1725 status = mTuner.getFrontendStatus(statusCapabilities); 1726 assertNotNull(status); 1727 } 1728 1729 @Test testHasUnusedFrontend1()1730 public void testHasUnusedFrontend1() throws Exception { 1731 prepTRMCustomFeResourceMapTest(); 1732 1733 // Use try block to ensure restoring the TunerResourceManager 1734 // Note: the handles will be changed from the original value, but should be OK 1735 try { 1736 TunerFrontendInfo[] infos = new TunerFrontendInfo[6]; 1737 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 1738 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 1739 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 1740 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBS, 1); 1741 infos[3] = tunerFrontendInfo(4, FrontendSettings.TYPE_DVBT, 2); 1742 infos[4] = tunerFrontendInfo(5, FrontendSettings.TYPE_DVBC, 2); 1743 infos[5] = tunerFrontendInfo(6, FrontendSettings.TYPE_DVBS, 2); 1744 1745 mTunerResourceManager.setFrontendInfoList(infos); 1746 1747 Tuner A = new Tuner(mContext, null, 100); 1748 Tuner B = new Tuner(mContext, null, 100); 1749 Tuner C = new Tuner(mContext, null, 100); 1750 1751 // check before anyone holds resource 1752 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_UNDEFINED)); 1753 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_ATSC)); 1754 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1755 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 1756 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 1757 1758 // let B hold resource 1759 assignFeResource(B.getClientId(), FrontendSettings.TYPE_DVBT, 1760 true /* expectedResult */, 1 /* expectedHandle */); 1761 1762 // check when one of the two exclusive groups are held 1763 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1764 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 1765 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 1766 1767 assertTrue(B.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1768 1769 // let C hold the resource 1770 assignFeResource(C.getClientId(), FrontendSettings.TYPE_DVBC, 1771 true /* expectedResult */, 5 /* expectedHandle */); 1772 1773 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1774 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 1775 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 1776 1777 assertFalse(B.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1778 assertFalse(C.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1779 1780 // let go of B's resource 1781 B.close(); 1782 1783 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1784 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 1785 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 1786 1787 assertTrue(B.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1788 assertTrue(C.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1789 1790 C.close(); 1791 A.close(); 1792 } catch (Exception e) { 1793 throw (e); 1794 } finally { 1795 cleanupTRMCustomFeResourceMapTest(); 1796 } 1797 } 1798 1799 @Test testHasUnusedFrontend2()1800 public void testHasUnusedFrontend2() throws Exception { 1801 prepTRMCustomFeResourceMapTest(); 1802 1803 // Use try block to ensure restoring the TunerResourceManager 1804 // Note: the handles will be changed from the original value, but should be OK 1805 try { 1806 TunerFrontendInfo[] infos = new TunerFrontendInfo[5]; 1807 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 1808 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 1809 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 1810 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBT, 2); 1811 infos[3] = tunerFrontendInfo(4, FrontendSettings.TYPE_DVBC, 2); 1812 infos[4] = tunerFrontendInfo(5, FrontendSettings.TYPE_DVBS, 3); 1813 1814 mTunerResourceManager.setFrontendInfoList(infos); 1815 1816 Tuner A = new Tuner(mContext, null, 100); 1817 Tuner B = new Tuner(mContext, null, 100); 1818 Tuner C = new Tuner(mContext, null, 100); 1819 1820 // let B hold resource 1821 assignFeResource(B.getClientId(), FrontendSettings.TYPE_DVBT, 1822 true /* expectedResult */, 1 /* expectedHandle */); 1823 1824 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1825 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 1826 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 1827 1828 // let C hold the resource 1829 assignFeResource(C.getClientId(), FrontendSettings.TYPE_DVBC, 1830 true /* expectedResult */, 4 /* expectedHandle */); 1831 1832 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1833 assertFalse(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 1834 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 1835 1836 B.close(); 1837 C.close(); 1838 } catch (Exception e) { 1839 throw (e); 1840 } finally { 1841 cleanupTRMCustomFeResourceMapTest(); 1842 } 1843 } 1844 1845 @Test testHasUnusedFrontend3()1846 public void testHasUnusedFrontend3() throws Exception { 1847 prepTRMCustomFeResourceMapTest(); 1848 1849 // Use try block to ensure restoring the TunerResourceManager 1850 // Note: the handles will be changed from the original value, but should be OK 1851 try { 1852 TunerFrontendInfo[] infos = new TunerFrontendInfo[6]; 1853 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 1854 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 1855 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 1856 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBS, 1); 1857 infos[3] = tunerFrontendInfo(4, FrontendSettings.TYPE_DVBT, 2); 1858 infos[4] = tunerFrontendInfo(5, FrontendSettings.TYPE_DVBC, 2); 1859 infos[5] = tunerFrontendInfo(6, FrontendSettings.TYPE_DVBS, 2); 1860 1861 mTunerResourceManager.setFrontendInfoList(infos); 1862 1863 Tuner A = new Tuner(mContext, null, 100); 1864 Tuner B = new Tuner(mContext, null, 100); 1865 Tuner C = new Tuner(mContext, null, 100); 1866 1867 // let B hold resource 1868 assignFeResource(B.getClientId(), FrontendSettings.TYPE_DVBT, 1869 true /* expectedResult */, 1 /* expectedHandle */); 1870 1871 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1872 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 1873 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 1874 1875 // let C share from B 1876 mTunerResourceManager.shareFrontend(C.getClientId(), B.getClientId()); 1877 1878 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBT)); 1879 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBC)); 1880 assertTrue(A.hasUnusedFrontend(FrontendSettings.TYPE_DVBS)); 1881 1882 A.close(); 1883 C.close(); 1884 B.close(); 1885 } catch (Exception e) { 1886 throw (e); 1887 } finally { 1888 cleanupTRMCustomFeResourceMapTest(); 1889 } 1890 } 1891 1892 @Test testIsLowestPriorityCornerCases()1893 public void testIsLowestPriorityCornerCases() throws Exception { 1894 prepTRMCustomFeResourceMapTest(); 1895 1896 // Use try block to ensure restoring the TunerResourceManager 1897 // Note: the handles will be changed from the original value, but should be OK 1898 try { 1899 setupSingleTunerSetupForIsLowestPriority(); 1900 1901 // must return true when non existing frontend type is specified 1902 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_UNDEFINED)); 1903 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_ATSC)); 1904 1905 // must return true when no one is holding the resource 1906 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBT)); 1907 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBC)); 1908 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBT)); 1909 1910 // must return true when the callee is the only one holding the resource 1911 assignFeResource(mTuner.getClientId(), FrontendSettings.TYPE_DVBT, 1912 true /* expectedResult */, 1 /* expectedHandle */); 1913 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBT)); 1914 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBC)); 1915 assertTrue(mTuner.isLowestPriority(FrontendSettings.TYPE_DVBT)); 1916 1917 } catch (Exception e) { 1918 throw (e); 1919 } finally { 1920 cleanupTRMCustomFeResourceMapTest(); 1921 } 1922 } 1923 1924 @Test testIsLowestPriorityTwoClients()1925 public void testIsLowestPriorityTwoClients() throws Exception { 1926 prepTRMCustomFeResourceMapTest(); 1927 1928 // Use try block to ensure restoring the TunerResourceManager 1929 // Note: the handles will be changed from the original value, but should be OK 1930 try { 1931 setupSingleTunerSetupForIsLowestPriority(); 1932 testTwoClientsForIsLowestPriority(200, 100); // A > B 1933 testTwoClientsForIsLowestPriority(100, 200); // A < B 1934 testTwoClientsForIsLowestPriority(100, 100); // A = B 1935 1936 setupDualTunerSetupForIsLowestPriority(); 1937 testTwoClientsForIsLowestPriority(200, 100); // A > B 1938 testTwoClientsForIsLowestPriority(100, 200); // A < B 1939 testTwoClientsForIsLowestPriority(100, 100); // A = B 1940 } catch (Exception e) { 1941 throw (e); 1942 } finally { 1943 cleanupTRMCustomFeResourceMapTest(); 1944 } 1945 } 1946 1947 @Test testIsLowestPriorityThreeClients()1948 public void testIsLowestPriorityThreeClients() throws Exception { 1949 prepTRMCustomFeResourceMapTest(); 1950 1951 // Use try block to ensure restoring the TunerResourceManager 1952 // Note: the handles will be changed from the original value, but should be OK 1953 try { 1954 setupDualTunerSetupForIsLowestPriority(); 1955 testThreeClientsForIsLowestPriority(300, 200, 100); // A > B > C 1956 testThreeClientsForIsLowestPriority(300, 100, 200); // A > C > B 1957 testThreeClientsForIsLowestPriority(200, 300, 100); // B > A > C 1958 testThreeClientsForIsLowestPriority(200, 100, 300); // C > A > B 1959 testThreeClientsForIsLowestPriority(100, 300, 200); // B > C > A 1960 testThreeClientsForIsLowestPriority(100, 200, 300); // C > B > A 1961 testThreeClientsForIsLowestPriority(100, 100, 100); // A = B = C 1962 testThreeClientsForIsLowestPriority(200, 200, 100); // A = B > C 1963 testThreeClientsForIsLowestPriority(200, 100, 100); // A > B = C 1964 testThreeClientsForIsLowestPriority(200, 100, 200); // A = C > B 1965 testThreeClientsForIsLowestPriority(200, 300, 200); // B > A = C 1966 testThreeClientsForIsLowestPriority(100, 100, 200); // C > A = B 1967 testThreeClientsForIsLowestPriority(100, 200, 200); // B = C > A 1968 } catch (Exception e) { 1969 throw (e); 1970 } finally { 1971 cleanupTRMCustomFeResourceMapTest(); 1972 } 1973 } 1974 tunerFrontendInfo( int handle, int frontendType, int exclusiveGroupId)1975 private TunerFrontendInfo tunerFrontendInfo( 1976 int handle, int frontendType, int exclusiveGroupId) { 1977 TunerFrontendInfo info = new TunerFrontendInfo(); 1978 info.handle = handle; 1979 info.type = frontendType; 1980 info.exclusiveGroupId = exclusiveGroupId; 1981 return info; 1982 } 1983 1984 /** 1985 * Prep function for TunerTest that requires custom frontend resource map 1986 */ prepTRMCustomFeResourceMapTest()1987 private void prepTRMCustomFeResourceMapTest() { 1988 if (mTunerResourceManager == null) { 1989 mTunerResourceManager = (TunerResourceManager) 1990 mContext.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE); 1991 } 1992 mTunerResourceManager.storeResourceMap(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); 1993 mTunerResourceManager.clearResourceMap(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); 1994 } 1995 1996 /** 1997 * Clean up function for TunerTest that requires custom frontend resource map 1998 */ cleanupTRMCustomFeResourceMapTest()1999 private void cleanupTRMCustomFeResourceMapTest() { 2000 // first close mTuner in case a frontend resource is opened 2001 if (mTuner != null) { 2002 mTuner.close(); 2003 mTuner = null; 2004 } 2005 2006 // now restore the original frontend resource map 2007 if (mTunerResourceManager != null) { 2008 mTunerResourceManager.restoreResourceMap( 2009 TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); 2010 } 2011 } 2012 clearFrontendInfoList()2013 private void clearFrontendInfoList() { 2014 if (mTunerResourceManager != null) { 2015 mTunerResourceManager.clearResourceMap( 2016 TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); 2017 } 2018 } 2019 assignFeResource(int clientId, int frontendType, boolean expectedResult, int expectedHandle)2020 private void assignFeResource(int clientId, int frontendType, 2021 boolean expectedResult, int expectedHandle) { 2022 int[] feHandle = new int[1]; 2023 TunerFrontendRequest request = new TunerFrontendRequest(); 2024 request.clientId = clientId; 2025 request.frontendType = frontendType; 2026 boolean granted = mTunerResourceManager.requestFrontend(request, feHandle); 2027 assertEquals(granted, expectedResult); 2028 assertEquals(feHandle[0], expectedHandle); 2029 } 2030 setupSingleTunerSetupForIsLowestPriority()2031 private void setupSingleTunerSetupForIsLowestPriority() { 2032 // first clear the frontend resource to register new set of resources 2033 clearFrontendInfoList(); 2034 2035 TunerFrontendInfo[] infos = new TunerFrontendInfo[3]; 2036 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 2037 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 2038 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 2039 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBS, 1); 2040 2041 mTunerResourceManager.setFrontendInfoList(infos); 2042 } 2043 setupDualTunerSetupForIsLowestPriority()2044 private void setupDualTunerSetupForIsLowestPriority() { 2045 // first clear the frontend resource to register new set of resources 2046 clearFrontendInfoList(); 2047 2048 TunerFrontendInfo[] infos = new TunerFrontendInfo[6]; 2049 // tunerFrontendInfo(handle, FrontendSettings.TYPE_*, exclusiveGroupId 2050 infos[0] = tunerFrontendInfo(1, FrontendSettings.TYPE_DVBT, 1); 2051 infos[1] = tunerFrontendInfo(2, FrontendSettings.TYPE_DVBC, 1); 2052 infos[2] = tunerFrontendInfo(3, FrontendSettings.TYPE_DVBS, 1); 2053 infos[3] = tunerFrontendInfo(4, FrontendSettings.TYPE_DVBT, 2); 2054 infos[4] = tunerFrontendInfo(5, FrontendSettings.TYPE_DVBC, 2); 2055 infos[5] = tunerFrontendInfo(6, FrontendSettings.TYPE_DVBS, 2); 2056 2057 mTunerResourceManager.setFrontendInfoList(infos); 2058 } 2059 2060 testTwoClientsForIsLowestPriority(int prioA, int prioB)2061 private void testTwoClientsForIsLowestPriority(int prioA, int prioB) { 2062 2063 Tuner A = new Tuner(mContext, null, prioA); 2064 Tuner B = new Tuner(mContext, null, prioB); 2065 2066 // all should return true 2067 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2068 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2069 2070 // let A hold resource 2071 assignFeResource(A.getClientId(), FrontendSettings.TYPE_DVBT, 2072 true /* expectedResult */, 1 /* expectedHandle */); 2073 2074 // should return true for A as A is the sole holder 2075 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2076 // should return false for B only if A < B 2077 if ( prioA < prioB ) { 2078 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2079 } else { 2080 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2081 } 2082 2083 A.close(); 2084 B.close(); 2085 } 2086 testThreeClientsForIsLowestPriority(int prioA, int prioB, int prioC)2087 private void testThreeClientsForIsLowestPriority(int prioA, int prioB, int prioC) { 2088 2089 Tuner A = new Tuner(mContext, null, prioA); 2090 Tuner B = new Tuner(mContext, null, prioB); 2091 Tuner C = new Tuner(mContext, null, prioC); 2092 2093 // all should return true 2094 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2095 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2096 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2097 2098 // let A & C hold resource 2099 assignFeResource(A.getClientId(), FrontendSettings.TYPE_DVBT, 2100 true /* expectedResult */, 1 /* expectedHandle */); 2101 2102 assignFeResource(C.getClientId(), FrontendSettings.TYPE_DVBC, 2103 true /* expectedResult */, 5 /* expectedHandle */); 2104 2105 // should return false for B only if A < B 2106 if (prioA > prioB && prioB > prioC) { 2107 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2108 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2109 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2110 } else if (prioA > prioC && prioC > prioB) { 2111 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2112 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2113 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2114 } else if (prioA > prioC && prioC > prioB) { 2115 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2116 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2117 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2118 } else if (prioB > prioA && prioA > prioC) { 2119 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2120 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2121 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2122 } else if (prioC > prioA && prioA > prioB) { 2123 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2124 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2125 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2126 } else if (prioB > prioC && prioC > prioA) { 2127 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2128 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2129 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2130 } else if (prioC > prioB && prioB > prioA) { 2131 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2132 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2133 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2134 } else if (prioA == prioB && prioB == prioC) { 2135 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2136 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2137 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2138 } else if (prioA == prioB && prioB > prioC) { 2139 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2140 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2141 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2142 } else if (prioA > prioB && prioB == prioC) { 2143 assertFalse(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2144 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2145 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2146 } else if (prioA == prioC && prioC > prioB) { 2147 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2148 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2149 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2150 } else if (prioB > prioA && prioA == prioC) { 2151 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2152 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2153 assertTrue(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2154 } else if (prioC > prioA && prioA == prioB) { 2155 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2156 assertTrue(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2157 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2158 } else if (prioB == prioC && prioC > prioA) { 2159 assertTrue(A.isLowestPriority(FrontendSettings.TYPE_DVBC)); 2160 assertFalse(B.isLowestPriority(FrontendSettings.TYPE_DVBS)); 2161 assertFalse(C.isLowestPriority(FrontendSettings.TYPE_DVBT)); 2162 } 2163 2164 A.close(); 2165 B.close(); 2166 C.close(); 2167 } 2168 2169 @Test testSharedFilterOneProcess()2170 public void testSharedFilterOneProcess() throws Exception { 2171 Filter f = createTsSectionFilter(mTuner, getExecutor(), getFilterCallback()); 2172 assertTrue(f != null); 2173 2174 String token1 = f.acquireSharedFilterToken(); 2175 assertTrue(token1 != null); 2176 2177 String token2 = f.acquireSharedFilterToken(); 2178 assertTrue(token2 == null); 2179 2180 // Tune a frontend before start the filter 2181 List<Integer> ids = mTuner.getFrontendIds(); 2182 assertFalse(ids.isEmpty()); 2183 2184 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 2185 int res = mTuner.tune(createFrontendSettings(info)); 2186 assertEquals(Tuner.RESULT_SUCCESS, res); 2187 2188 Settings settings = SectionSettingsWithTableInfo 2189 .builder(Filter.TYPE_TS) 2190 .setTableId(2) 2191 .setVersion(1) 2192 .setCrcEnabled(true) 2193 .setRaw(false) 2194 .setRepeat(false) 2195 .build(); 2196 FilterConfiguration config = TsFilterConfiguration 2197 .builder() 2198 .setTpid(10) 2199 .setSettings(settings) 2200 .build(); 2201 2202 assertEquals(f.configure(config), Tuner.RESULT_INVALID_STATE); 2203 assertEquals(f.setMonitorEventMask(Filter.MONITOR_EVENT_SCRAMBLING_STATUS), 2204 Tuner.RESULT_INVALID_STATE); 2205 assertEquals(f.setDataSource(null), Tuner.RESULT_INVALID_STATE); 2206 assertEquals(f.start(), Tuner.RESULT_INVALID_STATE); 2207 assertEquals(f.flush(), Tuner.RESULT_INVALID_STATE); 2208 assertEquals(f.read(new byte[3], 0, 3), 0); 2209 assertEquals(f.stop(), Tuner.RESULT_INVALID_STATE); 2210 2211 res = mTuner.cancelTuning(); 2212 assertEquals(Tuner.RESULT_SUCCESS, res); 2213 2214 f.freeSharedFilterToken(token1); 2215 f.close(); 2216 f = null; 2217 } 2218 2219 @Test testSharedFilterTwoProcessesCloseInSharedFilter()2220 public void testSharedFilterTwoProcessesCloseInSharedFilter() throws Exception { 2221 mConnection = new TestServiceConnection(); 2222 mContext.bindService(new Intent(mContext, SharedFilterTestService.class), mConnection, 2223 Context.BIND_AUTO_CREATE); 2224 mSharedFilterTestServer = 2225 ISharedFilterTestServer.Stub.asInterface(mConnection.getService()); 2226 2227 String token = mSharedFilterTestServer.acquireSharedFilterToken(); 2228 assertTrue(token != null); 2229 SharedFilter f = 2230 Tuner.openSharedFilter(mContext, token, getExecutor(), getSharedFilterCallback()); 2231 assertTrue(f != null); 2232 2233 assertEquals(f.start(), Tuner.RESULT_SUCCESS); 2234 assertEquals(f.flush(), Tuner.RESULT_SUCCESS); 2235 int size = f.read(new byte[3], 0, 3); 2236 assertTrue(size >= 0 && size <= 3); 2237 assertEquals(f.stop(), Tuner.RESULT_SUCCESS); 2238 2239 mLockLatch = new CountDownLatch(1); 2240 f.close(); 2241 f = null; 2242 mSharedFilterTestServer.closeFilter(); 2243 Thread.sleep(2000); 2244 assertEquals(mLockLatch.getCount(), 1); 2245 mLockLatch = null; 2246 2247 mContext.unbindService(mConnection); 2248 } 2249 2250 @Test testSharedFilterTwoProcessesCloseInFilter()2251 public void testSharedFilterTwoProcessesCloseInFilter() throws Exception { 2252 mConnection = new TestServiceConnection(); 2253 mContext.bindService(new Intent(mContext, SharedFilterTestService.class), mConnection, 2254 Context.BIND_AUTO_CREATE); 2255 mSharedFilterTestServer = 2256 ISharedFilterTestServer.Stub.asInterface(mConnection.getService()); 2257 2258 String token = mSharedFilterTestServer.acquireSharedFilterToken(); 2259 assertTrue(token != null); 2260 2261 SharedFilter f = 2262 Tuner.openSharedFilter(mContext, token, getExecutor(), getSharedFilterCallback()); 2263 assertTrue(f != null); 2264 2265 assertEquals(f.start(), Tuner.RESULT_SUCCESS); 2266 assertEquals(f.flush(), Tuner.RESULT_SUCCESS); 2267 int size = f.read(new byte[3], 0, 3); 2268 assertTrue(size >= 0 && size <= 3); 2269 assertEquals(f.stop(), Tuner.RESULT_SUCCESS); 2270 2271 mLockLatch = new CountDownLatch(1); 2272 mSharedFilterTestServer.closeFilter(); 2273 assertTrue(mLockLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 2274 mLockLatch = null; 2275 f.close(); 2276 f = null; 2277 2278 mContext.unbindService(mConnection); 2279 } 2280 2281 @Test testSharedFilterTwoProcessesReleaseInFilter()2282 public void testSharedFilterTwoProcessesReleaseInFilter() throws Exception { 2283 mConnection = new TestServiceConnection(); 2284 mContext.bindService(new Intent(mContext, SharedFilterTestService.class), mConnection, 2285 Context.BIND_AUTO_CREATE); 2286 mSharedFilterTestServer = 2287 ISharedFilterTestServer.Stub.asInterface(mConnection.getService()); 2288 2289 String token = mSharedFilterTestServer.acquireSharedFilterToken(); 2290 assertTrue(token != null); 2291 2292 SharedFilter f = 2293 Tuner.openSharedFilter(mContext, token, getExecutor(), getSharedFilterCallback()); 2294 assertTrue(f != null); 2295 2296 assertEquals(f.start(), Tuner.RESULT_SUCCESS); 2297 assertEquals(f.flush(), Tuner.RESULT_SUCCESS); 2298 int size = f.read(new byte[3], 0, 3); 2299 assertTrue(size >= 0 && size <= 3); 2300 assertEquals(f.stop(), Tuner.RESULT_SUCCESS); 2301 2302 mLockLatch = new CountDownLatch(1); 2303 mSharedFilterTestServer.freeSharedFilterToken(token); 2304 assertTrue(mLockLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 2305 mLockLatch = null; 2306 2307 mSharedFilterTestServer.closeFilter(); 2308 f.close(); 2309 f = null; 2310 2311 mContext.unbindService(mConnection); 2312 } 2313 2314 @Test testSharedFilterTwoProcessesVerifySharedFilter()2315 public void testSharedFilterTwoProcessesVerifySharedFilter() throws Exception { 2316 mConnection = new TestServiceConnection(); 2317 mContext.bindService(new Intent(mContext, SharedFilterTestService.class), mConnection, 2318 Context.BIND_AUTO_CREATE); 2319 mSharedFilterTestServer = 2320 ISharedFilterTestServer.Stub.asInterface(mConnection.getService()); 2321 2322 Filter f = createTsSectionFilter(mTuner, getExecutor(), getFilterCallback()); 2323 assertTrue(f != null); 2324 2325 String token = f.acquireSharedFilterToken(); 2326 assertTrue(token != null); 2327 2328 // Tune a frontend before start the shared filter 2329 List<Integer> ids = mTuner.getFrontendIds(); 2330 assertFalse(ids.isEmpty()); 2331 2332 FrontendInfo info = mTuner.getFrontendInfoById(ids.get(0)); 2333 int res = mTuner.tune(createFrontendSettings(info)); 2334 assertEquals(Tuner.RESULT_SUCCESS, res); 2335 assertTrue(mSharedFilterTestServer.verifySharedFilter(token)); 2336 2337 res = mTuner.cancelTuning(); 2338 assertEquals(Tuner.RESULT_SUCCESS, res); 2339 2340 f.freeSharedFilterToken(token); 2341 f.close(); 2342 f = null; 2343 2344 mContext.unbindService(mConnection); 2345 } 2346 2347 @Test testFilterTimeDelay()2348 public void testFilterTimeDelay() throws Exception { 2349 Filter f = createTsSectionFilter(mTuner, getExecutor(), getFilterCallback()); 2350 2351 int timeDelayInMs = 5000; 2352 Instant start = Instant.now(); 2353 int status = f.delayCallbackForDurationMillis(timeDelayInMs); 2354 2355 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) { 2356 // start / stop prevents initial race condition after first setting the time delay. 2357 f.start(); 2358 f.stop(); 2359 2360 mLockLatch = new CountDownLatch(1); 2361 f.start(); 2362 assertTrue(mLockLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 2363 2364 Instant finish = Instant.now(); 2365 Duration timeElapsed = Duration.between(start, finish); 2366 assertTrue(timeElapsed.toMillis() >= timeDelayInMs); 2367 } else { 2368 assertEquals(Tuner.RESULT_UNAVAILABLE, status); 2369 } 2370 f.close(); 2371 f = null; 2372 } 2373 2374 @Test testFilterDataSizeDelay()2375 public void testFilterDataSizeDelay() throws Exception { 2376 Filter f = createTsSectionFilter(mTuner, getExecutor(), getFilterCallback()); 2377 int status = f.delayCallbackUntilBytesAccumulated(5000); 2378 if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) { 2379 assertEquals(Tuner.RESULT_SUCCESS, status); 2380 } else { 2381 assertEquals(Tuner.RESULT_UNAVAILABLE, status); 2382 } 2383 f.close(); 2384 } 2385 2386 @Test testMaxNumberOfFrontends()2387 public void testMaxNumberOfFrontends() throws Exception { 2388 List<Integer> ids = mTuner.getFrontendIds(); 2389 assertFalse(ids.isEmpty()); 2390 for (int i = 0; i < ids.size(); i++) { 2391 int type = mTuner.getFrontendInfoById(ids.get(i)).getType(); 2392 if (TunerVersionChecker.isHigherOrEqualVersionTo( 2393 TunerVersionChecker.TUNER_VERSION_2_0)) { 2394 int defaultMax = -1; 2395 int status; 2396 // Check default value 2397 defaultMax = mTuner.getMaxNumberOfFrontends(type); 2398 assertTrue(defaultMax > 0); 2399 // Set to -1 2400 status = mTuner.setMaxNumberOfFrontends(type, -1); 2401 assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status); 2402 // Set to defaultMax + 1 2403 status = mTuner.setMaxNumberOfFrontends(type, defaultMax + 1); 2404 assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status); 2405 // Set to 0 2406 status = mTuner.setMaxNumberOfFrontends(type, 0); 2407 assertEquals(Tuner.RESULT_SUCCESS, status); 2408 // Check after set 2409 int currentMax = -1; 2410 currentMax = mTuner.getMaxNumberOfFrontends(type); 2411 assertEquals(currentMax, 0); 2412 // Reset to default 2413 status = mTuner.setMaxNumberOfFrontends(type, defaultMax); 2414 assertEquals(Tuner.RESULT_SUCCESS, status); 2415 currentMax = mTuner.getMaxNumberOfFrontends(type); 2416 assertEquals(defaultMax, currentMax); 2417 } else { 2418 int defaultMax = mTuner.getMaxNumberOfFrontends(type); 2419 assertEquals(defaultMax, -1); 2420 int status = mTuner.setMaxNumberOfFrontends(type, 0); 2421 assertEquals(Tuner.RESULT_UNAVAILABLE, status); 2422 } 2423 } 2424 // validate the behavior of tune 2425 FrontendInfo info1 = mTuner.getFrontendInfoById(ids.get(0)); 2426 FrontendSettings feSettings1 = createFrontendSettings(info1); 2427 int type1 = info1.getType(); 2428 if (ids.size() >= 1) { 2429 int originalMax1 = mTuner.getMaxNumberOfFrontends(type1); 2430 assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1)); 2431 assertNotNull(mTuner.getFrontendInfo()); 2432 2433 // validate that set max cannot be set to lower value than current usage 2434 assertEquals(Tuner.RESULT_INVALID_ARGUMENT, 2435 mTuner.setMaxNumberOfFrontends(type1, 0)); 2436 2437 // validate max value is reflected in the tune behavior 2438 mTuner.closeFrontend(); 2439 assertEquals(Tuner.RESULT_SUCCESS, 2440 mTuner.setMaxNumberOfFrontends(type1, 0)); 2441 assertEquals(Tuner.RESULT_UNAVAILABLE, 2442 mTuner.tune(feSettings1)); 2443 2444 assertEquals(Tuner.RESULT_SUCCESS, 2445 mTuner.setMaxNumberOfFrontends(type1, originalMax1)); 2446 assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1)); 2447 assertNotNull(mTuner.getFrontendInfo()); 2448 mTuner.closeFrontend(); 2449 } 2450 2451 // validate max number on one frontend type has no impact on other 2452 if (ids.size() >= 2) { 2453 FrontendInfo info2 = mTuner.getFrontendInfoById(ids.get(1)); 2454 int type2 = info2.getType(); 2455 int originalMax2 = mTuner.getMaxNumberOfFrontends(type2); 2456 2457 assertEquals(Tuner.RESULT_SUCCESS, 2458 mTuner.setMaxNumberOfFrontends(type2, 0)); 2459 assertEquals(Tuner.RESULT_SUCCESS, 2460 mTuner.tune(feSettings1)); 2461 assertNotNull(mTuner.getFrontendInfo()); 2462 2463 // set it back to the original max 2464 assertEquals(Tuner.RESULT_SUCCESS, 2465 mTuner.setMaxNumberOfFrontends(type2, originalMax2)); 2466 mTuner.closeFrontend(); 2467 2468 } 2469 } 2470 createTsSectionFilter( Tuner tuner, Executor e, FilterCallback cb)2471 public static Filter createTsSectionFilter( 2472 Tuner tuner, Executor e, FilterCallback cb) { 2473 Filter f = tuner.openFilter(Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, e, cb); 2474 Settings settings = SectionSettingsWithTableInfo 2475 .builder(Filter.TYPE_TS) 2476 .setTableId(2) 2477 .setVersion(1) 2478 .setCrcEnabled(true) 2479 .setRaw(false) 2480 .setRepeat(false) 2481 .build(); 2482 FilterConfiguration config = TsFilterConfiguration 2483 .builder() 2484 .setTpid(10) 2485 .setSettings(settings) 2486 .build(); 2487 f.configure(config); 2488 f.setMonitorEventMask( 2489 Filter.MONITOR_EVENT_SCRAMBLING_STATUS | Filter.MONITOR_EVENT_IP_CID_CHANGE); 2490 2491 return f; 2492 } 2493 hasTuner()2494 private boolean hasTuner() { 2495 return mContext.getPackageManager().hasSystemFeature("android.hardware.tv.tuner"); 2496 } 2497 getExecutor()2498 private Executor getExecutor() { 2499 return Runnable::run; 2500 } 2501 getLnbCallback()2502 private LnbCallback getLnbCallback() { 2503 return new LnbCallback() { 2504 @Override 2505 public void onEvent(int lnbEventType) {} 2506 @Override 2507 public void onDiseqcMessage(byte[] diseqcMessage) {} 2508 }; 2509 } 2510 getFilterCallback()2511 private FilterCallback getFilterCallback() { 2512 return new FilterCallback() { 2513 @Override 2514 public void onFilterEvent(Filter filter, FilterEvent[] events) { 2515 for (FilterEvent e : events) { 2516 if (e instanceof DownloadEvent) { 2517 testDownloadEvent(filter, (DownloadEvent) e); 2518 } else if (e instanceof IpPayloadEvent) { 2519 testIpPayloadEvent(filter, (IpPayloadEvent) e); 2520 } else if (e instanceof MediaEvent) { 2521 testMediaEvent(filter, (MediaEvent) e); 2522 } else if (e instanceof MmtpRecordEvent) { 2523 testMmtpRecordEvent(filter, (MmtpRecordEvent) e); 2524 } else if (e instanceof PesEvent) { 2525 testPesEvent(filter, (PesEvent) e); 2526 } else if (e instanceof SectionEvent) { 2527 testSectionEvent(filter, (SectionEvent) e); 2528 } else if (e instanceof TemiEvent) { 2529 testTemiEvent(filter, (TemiEvent) e); 2530 } else if (e instanceof TsRecordEvent) { 2531 testTsRecordEvent(filter, (TsRecordEvent) e); 2532 } else if (e instanceof ScramblingStatusEvent) { 2533 testScramblingStatusEvent(filter, (ScramblingStatusEvent) e); 2534 } else if (e instanceof IpCidChangeEvent) { 2535 testIpCidChangeEvent(filter, (IpCidChangeEvent) e); 2536 } else if (e instanceof RestartEvent) { 2537 testRestartEvent(filter, (RestartEvent) e); 2538 } 2539 } 2540 if (mLockLatch != null) { 2541 mLockLatch.countDown(); 2542 } 2543 } 2544 @Override 2545 public void onFilterStatusChanged(Filter filter, int status) {} 2546 }; 2547 } 2548 2549 private SharedFilterCallback getSharedFilterCallback() { 2550 return new SharedFilterCallback() { 2551 @Override 2552 public void onFilterEvent(SharedFilter filter, FilterEvent[] events) {} 2553 @Override 2554 public void onFilterStatusChanged(SharedFilter filter, int status) { 2555 if (status == SharedFilter.STATUS_INACCESSIBLE) { 2556 if (mLockLatch != null) { 2557 mLockLatch.countDown(); 2558 } 2559 } 2560 } 2561 }; 2562 } 2563 2564 private void testDownloadEvent(Filter filter, DownloadEvent e) { 2565 e.getItemId(); 2566 e.getDownloadId(); 2567 e.getMpuSequenceNumber(); 2568 e.getItemFragmentIndex(); 2569 e.getLastItemFragmentIndex(); 2570 long length = e.getDataLength(); 2571 if (length > 0) { 2572 byte[] buffer = new byte[(int) length]; 2573 assertNotEquals(0, filter.read(buffer, 0, length)); 2574 } 2575 } 2576 2577 private void testIpPayloadEvent(Filter filter, IpPayloadEvent e) { 2578 long length = e.getDataLength(); 2579 if (length > 0) { 2580 byte[] buffer = new byte[(int) length]; 2581 assertNotEquals(0, filter.read(buffer, 0, length)); 2582 } 2583 } 2584 2585 private void testMediaEvent(Filter filter, MediaEvent e) { 2586 e.getStreamId(); 2587 e.isPtsPresent(); 2588 e.getPts(); 2589 e.isDtsPresent(); 2590 e.getDts(); 2591 e.getDataLength(); 2592 e.getOffset(); 2593 e.getLinearBlock(); 2594 e.isSecureMemory(); 2595 e.getAvDataId(); 2596 e.getAudioHandle(); 2597 e.getMpuSequenceNumber(); 2598 e.isPrivateData(); 2599 e.getScIndexMask(); 2600 AudioDescriptor ad = e.getExtraMetaData(); 2601 if (ad != null) { 2602 ad.getAdFade(); 2603 ad.getAdPan(); 2604 ad.getAdVersionTextTag(); 2605 ad.getAdGainCenter(); 2606 ad.getAdGainFront(); 2607 ad.getAdGainSurround(); 2608 } 2609 e.release(); 2610 } 2611 2612 private void testMmtpRecordEvent(Filter filter, MmtpRecordEvent e) { 2613 e.getScHevcIndexMask(); 2614 e.getDataLength(); 2615 int mpuSequenceNumber = e.getMpuSequenceNumber(); 2616 long pts = e.getPts(); 2617 int firstMbInSlice = e.getFirstMacroblockInSlice(); 2618 int tsIndexMask = e.getTsIndexMask(); 2619 if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 2620 assertEquals(mpuSequenceNumber, Tuner.INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM); 2621 assertEquals(pts, Tuner.INVALID_TIMESTAMP); 2622 assertEquals(firstMbInSlice, Tuner.INVALID_FIRST_MACROBLOCK_IN_SLICE); 2623 assertEquals(tsIndexMask, 0); 2624 } 2625 } 2626 2627 private void testPesEvent(Filter filter, PesEvent e) { 2628 e.getStreamId(); 2629 e.getMpuSequenceNumber(); 2630 long length = e.getDataLength(); 2631 if (length > 0) { 2632 byte[] buffer = new byte[(int) length]; 2633 assertNotEquals(0, filter.read(buffer, 0, length)); 2634 } 2635 } 2636 2637 private void testSectionEvent(Filter filter, SectionEvent e) { 2638 e.getTableId(); 2639 e.getVersion(); 2640 e.getSectionNumber(); 2641 e.getDataLength(); 2642 long length = e.getDataLengthLong(); 2643 if (length > 0) { 2644 byte[] buffer = new byte[(int) length]; 2645 assertNotEquals(0, filter.read(buffer, 0, length)); 2646 } 2647 } 2648 2649 private void testTemiEvent(Filter filter, TemiEvent e) { 2650 e.getPts(); 2651 e.getDescriptorTag(); 2652 e.getDescriptorData(); 2653 } 2654 2655 private void testTsRecordEvent(Filter filter, TsRecordEvent e) { 2656 e.getPacketId(); 2657 e.getTsIndexMask(); 2658 e.getScIndexMask(); 2659 e.getDataLength(); 2660 long pts = e.getPts(); 2661 int firstMbInSlice = e.getFirstMacroblockInSlice(); 2662 if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) { 2663 assertEquals(pts, Tuner.INVALID_TIMESTAMP); 2664 assertEquals(firstMbInSlice, Tuner.INVALID_FIRST_MACROBLOCK_IN_SLICE); 2665 } 2666 } 2667 2668 private void testScramblingStatusEvent(Filter filter, ScramblingStatusEvent e) { 2669 e.getScramblingStatus(); 2670 } 2671 2672 private void testIpCidChangeEvent(Filter filter, IpCidChangeEvent e) { 2673 e.getIpCid(); 2674 } 2675 2676 private void testRestartEvent(Filter filter, RestartEvent e) { 2677 e.getStartId(); 2678 } 2679 2680 private OnRecordStatusChangedListener getRecordListener() { 2681 return new OnRecordStatusChangedListener() { 2682 @Override 2683 public void onRecordStatusChanged(int status) {} 2684 }; 2685 } 2686 2687 private OnPlaybackStatusChangedListener getPlaybackListener() { 2688 return new OnPlaybackStatusChangedListener() { 2689 @Override 2690 public void onPlaybackStatusChanged(int status) {} 2691 }; 2692 } 2693 2694 static public FrontendSettings createFrontendSettings(FrontendInfo info) { 2695 FrontendCapabilities caps = info.getFrontendCapabilities(); 2696 long minFreq = info.getFrequencyRangeLong().getLower(); 2697 long maxFreq = info.getFrequencyRangeLong().getUpper(); 2698 FrontendCapabilities feCaps = info.getFrontendCapabilities(); 2699 switch(info.getType()) { 2700 case FrontendSettings.TYPE_ANALOG: { 2701 AnalogFrontendCapabilities analogCaps = (AnalogFrontendCapabilities) caps; 2702 int signalType = getFirstCapable(analogCaps.getSignalTypeCapability()); 2703 int sif = getFirstCapable(analogCaps.getSifStandardCapability()); 2704 return AnalogFrontendSettings 2705 .builder() 2706 .setFrequencyLong(55250000) //2nd freq of VHF 2707 .setSignalType(signalType) 2708 .setSifStandard(sif) 2709 .build(); 2710 } 2711 case FrontendSettings.TYPE_ATSC3: { 2712 Atsc3FrontendCapabilities atsc3Caps = (Atsc3FrontendCapabilities) caps; 2713 int bandwidth = getFirstCapable(atsc3Caps.getBandwidthCapability()); 2714 int demod = getFirstCapable(atsc3Caps.getDemodOutputFormatCapability()); 2715 Atsc3FrontendSettings settings = 2716 Atsc3FrontendSettings 2717 .builder() 2718 .setFrequencyLong(473000000) // 1st freq of UHF 2719 .setBandwidth(bandwidth) 2720 .setDemodOutputFormat(demod) 2721 .build(); 2722 settings.setEndFrequencyLong(maxFreq); 2723 return settings; 2724 } 2725 case FrontendSettings.TYPE_ATSC: { 2726 AtscFrontendCapabilities atscCaps = (AtscFrontendCapabilities) caps; 2727 int modulation = getFirstCapable(atscCaps.getModulationCapability()); 2728 return AtscFrontendSettings 2729 .builder() 2730 .setFrequencyLong(479000000) // 2nd freq of UHF 2731 .setModulation(modulation) 2732 .build(); 2733 } 2734 case FrontendSettings.TYPE_DVBC: { 2735 DvbcFrontendCapabilities dvbcCaps = (DvbcFrontendCapabilities) caps; 2736 int modulation = getFirstCapable(dvbcCaps.getModulationCapability()); 2737 int fec = getFirstCapable(dvbcCaps.getFecCapability()); 2738 int annex = getFirstCapable(dvbcCaps.getAnnexCapability()); 2739 DvbcFrontendSettings settings = 2740 DvbcFrontendSettings 2741 .builder() 2742 .setFrequencyLong(490000000) 2743 .setModulation(modulation) 2744 .setInnerFec(fec) 2745 .setAnnex(annex) 2746 .build(); 2747 settings.setEndFrequencyLong(maxFreq); 2748 return settings; 2749 } 2750 case FrontendSettings.TYPE_DVBS: { 2751 DvbsFrontendCapabilities dvbsCaps = (DvbsFrontendCapabilities) caps; 2752 int modulation = getFirstCapable(dvbsCaps.getModulationCapability()); 2753 int standard = getFirstCapable(dvbsCaps.getStandardCapability()); 2754 DvbsFrontendSettings settings = 2755 DvbsFrontendSettings 2756 .builder() 2757 .setFrequencyLong(950000000) //950Mhz 2758 .setModulation(modulation) 2759 .setStandard(standard) 2760 .build(); 2761 settings.setEndFrequencyLong(maxFreq); 2762 return settings; 2763 } 2764 case FrontendSettings.TYPE_DVBT: { 2765 DvbtFrontendCapabilities dvbtCaps = (DvbtFrontendCapabilities) caps; 2766 int transmission = getFirstCapable(dvbtCaps.getTransmissionModeCapability()); 2767 int bandwidth = getFirstCapable(dvbtCaps.getBandwidthCapability()); 2768 int constellation = getFirstCapable(dvbtCaps.getConstellationCapability()); 2769 int codeRate = getFirstCapable(dvbtCaps.getCodeRateCapability()); 2770 int hierarchy = getFirstCapable(dvbtCaps.getHierarchyCapability()); 2771 int guardInterval = getFirstCapable(dvbtCaps.getGuardIntervalCapability()); 2772 DvbtFrontendSettings settings = DvbtFrontendSettings 2773 .builder() 2774 .setFrequencyLong(498000000) 2775 .setTransmissionMode(transmission) 2776 .setBandwidth(bandwidth) 2777 .setConstellation(constellation) 2778 .setHierarchy(hierarchy) 2779 .setHighPriorityCodeRate(codeRate) 2780 .setLowPriorityCodeRate(codeRate) 2781 .setGuardInterval(guardInterval) 2782 .setStandard(DvbtFrontendSettings.STANDARD_T) 2783 .setMiso(false) 2784 .build(); 2785 settings.setEndFrequencyLong(maxFreq); 2786 return settings; 2787 } 2788 case FrontendSettings.TYPE_ISDBS3: { 2789 Isdbs3FrontendCapabilities isdbs3Caps = (Isdbs3FrontendCapabilities) caps; 2790 int modulation = getFirstCapable(isdbs3Caps.getModulationCapability()); 2791 int codeRate = getFirstCapable(isdbs3Caps.getCodeRateCapability()); 2792 Isdbs3FrontendSettings settings = Isdbs3FrontendSettings 2793 .builder() 2794 .setFrequencyLong(1000000000) //1000 Mhz 2795 .setModulation(modulation) 2796 .setCodeRate(codeRate) 2797 .build(); 2798 settings.setEndFrequencyLong(maxFreq); 2799 return settings; 2800 } 2801 case FrontendSettings.TYPE_ISDBS: { 2802 IsdbsFrontendCapabilities isdbsCaps = (IsdbsFrontendCapabilities) caps; 2803 int modulation = getFirstCapable(isdbsCaps.getModulationCapability()); 2804 int codeRate = getFirstCapable(isdbsCaps.getCodeRateCapability()); 2805 IsdbsFrontendSettings settings = IsdbsFrontendSettings 2806 .builder() 2807 .setFrequencyLong(1050000000) //1050 Mhz 2808 .setModulation(modulation) 2809 .setCodeRate(codeRate) 2810 .build(); 2811 settings.setEndFrequencyLong(maxFreq); 2812 return settings; 2813 } 2814 case FrontendSettings.TYPE_ISDBT: { 2815 IsdbtFrontendCapabilities isdbtCaps = (IsdbtFrontendCapabilities) caps; 2816 int mode = getFirstCapable(isdbtCaps.getModeCapability()); 2817 int bandwidth = getFirstCapable(isdbtCaps.getBandwidthCapability()); 2818 int modulation = getFirstCapable(isdbtCaps.getModulationCapability()); 2819 int codeRate = getFirstCapable(isdbtCaps.getCodeRateCapability()); 2820 int guardInterval = getFirstCapable(isdbtCaps.getGuardIntervalCapability()); 2821 int timeInterleaveMode = 2822 getFirstCapable(isdbtCaps.getTimeInterleaveModeCapability()); 2823 boolean isSegmentAutoSupported = isdbtCaps.isSegmentAutoSupported(); 2824 boolean isFullSegmentSupported = isdbtCaps.isFullSegmentSupported(); 2825 2826 IsdbtFrontendSettings.Builder builder = IsdbtFrontendSettings.builder(); 2827 builder.setFrequencyLong(527143000); //22 ch 527.143 MHz 2828 builder.setBandwidth(bandwidth); 2829 builder.setMode(mode); 2830 builder.setGuardInterval(guardInterval); 2831 2832 if (!TunerVersionChecker.isHigherOrEqualVersionTo( 2833 TunerVersionChecker.TUNER_VERSION_2_0)) { 2834 builder.setModulation(modulation); 2835 builder.setCodeRate(codeRate); 2836 } else { 2837 IsdbtFrontendSettings.IsdbtLayerSettings.Builder layerBuilder = 2838 IsdbtFrontendSettings.IsdbtLayerSettings.builder(); 2839 layerBuilder.setTimeInterleaveMode(timeInterleaveMode); 2840 layerBuilder.setModulation(modulation); 2841 layerBuilder.setCodeRate(codeRate); 2842 if (isSegmentAutoSupported) { 2843 layerBuilder.setNumberOfSegments(0xFF); 2844 } else { 2845 if (isFullSegmentSupported) { 2846 layerBuilder.setNumberOfSegments(13); 2847 } else { 2848 layerBuilder.setNumberOfSegments(1); 2849 } 2850 } 2851 IsdbtFrontendSettings.IsdbtLayerSettings layer = layerBuilder.build(); 2852 builder.setLayerSettings( 2853 new IsdbtFrontendSettings.IsdbtLayerSettings[] {layer}); 2854 builder.setPartialReceptionFlag( 2855 IsdbtFrontendSettings.PARTIAL_RECEPTION_FLAG_TRUE); 2856 } 2857 IsdbtFrontendSettings settings = builder.build(); 2858 settings.setEndFrequencyLong(maxFreq); 2859 return settings; 2860 } 2861 case FrontendSettings.TYPE_DTMB: { 2862 DtmbFrontendCapabilities dtmbCaps = (DtmbFrontendCapabilities) caps; 2863 int modulation = getFirstCapable(dtmbCaps.getModulationCapability()); 2864 int transmissionMode = getFirstCapable( 2865 dtmbCaps.getTransmissionModeCapability()); 2866 int guardInterval = getFirstCapable(dtmbCaps.getGuardIntervalCapability()); 2867 int timeInterleaveMode = getFirstCapable( 2868 dtmbCaps.getTimeInterleaveModeCapability()); 2869 int codeRate = getFirstCapable(dtmbCaps.getCodeRateCapability()); 2870 int bandwidth = getFirstCapable(dtmbCaps.getBandwidthCapability()); 2871 DtmbFrontendSettings settings = 2872 DtmbFrontendSettings 2873 .builder() 2874 .setFrequencyLong(506000000) 2875 .setModulation(modulation) 2876 .setTransmissionMode(transmissionMode) 2877 .setBandwidth(bandwidth) 2878 .setCodeRate(codeRate) 2879 .setGuardInterval(guardInterval) 2880 .setTimeInterleaveMode(timeInterleaveMode) 2881 .build(); 2882 settings.setEndFrequencyLong(maxFreq); 2883 return settings; 2884 } 2885 default: 2886 break; 2887 } 2888 return null; 2889 } 2890 2891 static public int getFirstCapable(int caps) { 2892 if (caps == 0) return 0; 2893 int mask = 1; 2894 while ((mask & caps) == 0) { 2895 mask = mask << 1; 2896 } 2897 return (mask & caps); 2898 } 2899 2900 static public long getFirstCapable(long caps) { 2901 if (caps == 0) return 0; 2902 long mask = 1; 2903 while ((mask & caps) == 0) { 2904 mask = mask << 1; 2905 } 2906 return (mask & caps); 2907 } 2908 2909 private ScanCallback getScanCallback() { 2910 return new ScanCallback() { 2911 @Override 2912 public void onLocked() { 2913 if (mLockLatch != null) { 2914 mLockLatch.countDown(); 2915 } 2916 } 2917 2918 @Override 2919 public void onUnlocked() { 2920 ScanCallback.super.onUnlocked(); 2921 if (mLockLatch != null) { 2922 mLockLatch.countDown(); 2923 } 2924 } 2925 2926 @Override 2927 public void onScanStopped() {} 2928 2929 @Override 2930 public void onProgress(int percent) {} 2931 2932 @Override 2933 public void onFrequenciesReported(int[] frequency) {} 2934 2935 @Override 2936 public void onFrequenciesLongReported(long[] frequencies) { 2937 ScanCallback.super.onFrequenciesLongReported(frequencies); 2938 } 2939 2940 @Override 2941 public void onSymbolRatesReported(int[] rate) {} 2942 2943 @Override 2944 public void onPlpIdsReported(int[] plpIds) {} 2945 2946 @Override 2947 public void onGroupIdsReported(int[] groupIds) {} 2948 2949 @Override 2950 public void onInputStreamIdsReported(int[] inputStreamIds) {} 2951 2952 @Override 2953 public void onDvbsStandardReported(int dvbsStandard) {} 2954 2955 @Override 2956 public void onDvbtStandardReported(int dvbtStandard) {} 2957 2958 @Override 2959 public void onAnalogSifStandardReported(int sif) {} 2960 2961 @Override 2962 public void onAtsc3PlpInfosReported(Atsc3PlpInfo[] atsc3PlpInfos) { 2963 for (Atsc3PlpInfo info : atsc3PlpInfos) { 2964 if (info != null) { 2965 info.getPlpId(); 2966 info.getLlsFlag(); 2967 } 2968 } 2969 } 2970 2971 @Override 2972 public void onHierarchyReported(int hierarchy) {} 2973 2974 @Override 2975 public void onSignalTypeReported(int signalType) {} 2976 2977 @Override 2978 public void onModulationReported(int modulation) { 2979 ScanCallback.super.onModulationReported(modulation); 2980 } 2981 2982 @Override 2983 public void onPriorityReported(boolean isHighPriority) { 2984 ScanCallback.super.onPriorityReported(isHighPriority); 2985 } 2986 2987 @Override 2988 public void onDvbcAnnexReported(int dvbcAnnext) { 2989 ScanCallback.super.onDvbcAnnexReported(dvbcAnnext); 2990 } 2991 2992 @Override 2993 public void onDvbtCellIdsReported(int[] dvbtCellIds) { 2994 ScanCallback.super.onDvbtCellIdsReported(dvbtCellIds); 2995 } 2996 }; 2997 } 2998 2999 // TunerHandler utility for testing Tuner api calls in a different thread 3000 private static final int MSG_TUNER_HANDLER_CREATE = 1; 3001 private static final int MSG_TUNER_HANDLER_TUNE = 2; 3002 private static final int MSG_TUNER_HANDLER_CLOSE = 3; 3003 3004 private ConditionVariable mTunerHandlerTaskComplete = new ConditionVariable(); 3005 3006 private TunerHandler createTunerHandler(Looper looper) { 3007 if (looper != null) { 3008 return new TunerHandler(looper); 3009 } else if ((looper = Looper.myLooper()) != null) { 3010 return new TunerHandler(looper); 3011 } else if ((looper = Looper.getMainLooper()) != null) { 3012 return new TunerHandler(looper); 3013 } 3014 return null; 3015 } 3016 3017 private class TunerHandler extends Handler { 3018 Object mLock = new Object(); 3019 Tuner mHandlersTuner; 3020 int mResult; 3021 3022 private TunerHandler(Looper looper) { 3023 super(looper); 3024 } 3025 3026 public Tuner getTuner() { 3027 synchronized (mLock) { 3028 return mHandlersTuner; 3029 } 3030 } 3031 3032 public int getResult() { 3033 synchronized (mLock) { 3034 return mResult; 3035 } 3036 } 3037 3038 @Override 3039 public void handleMessage(Message msg) { 3040 switch (msg.what) { 3041 case MSG_TUNER_HANDLER_CREATE: { 3042 synchronized (mLock) { 3043 int useCase = msg.arg1; 3044 mHandlersTuner = new Tuner(mContext, null, useCase); 3045 } 3046 break; 3047 } 3048 case MSG_TUNER_HANDLER_TUNE: { 3049 synchronized (mLock) { 3050 FrontendSettings feSettings = (FrontendSettings) msg.obj; 3051 mResult = mHandlersTuner.tune(feSettings); 3052 } 3053 break; 3054 } 3055 case MSG_TUNER_HANDLER_CLOSE: { 3056 synchronized (mLock) { 3057 mHandlersTuner.close(); 3058 } 3059 break; 3060 } 3061 default: 3062 break; 3063 } 3064 mTunerHandlerTaskComplete.open(); 3065 } 3066 } 3067 } 3068